首页 > 编程知识 正文

二叉树的基本算法的实现,二叉树算法思想

时间:2023-05-04 00:06:07 阅读:187054 作者:3203

二叉堆是基于数组的数据结构,通过数组中定义的left () right ) (parent ) )操作和heapsize属性,可以看作二叉树。

如图所示,根节点有两个叶节点,分别对应序列的下标为1和2,通过left (和right ) )操作实现,在下标的位移上增加更多的偏移),叶节点的父节点为parent ) )操作实现由于heapsize为3,因此数组中下标为3的第四个元素不会添加到堆中。

二叉堆分为最大堆和最小堆。 最大堆的定义是满足根节点以外的所有点I。 a[parent[I]=a[I],换言之,根节点必须等于或大于子节点。 如果最大堆已完成。 整个二叉山表示各层的要素大于下一层的要素,最大的要素是根节点。 因此,如果能形成两股山,我们很快就能得到其中最大的元素。 最小堆的定义相反,省略说明。

为了生成二叉树,首先需要进行保持二叉树山性质的操作heaplify (),其作用对象是某个节点,对其进行检查,检查是否符合山的性质,如果符合则返回,如果不符合则进行修正为了提高效率,我把末尾递归改为迭代。

inlineintprior(intl,int i,int r )//根据性质最优先的if(l=heap_size|||r=heap_size ) return i; if(compare(L,I ) ) i=l; if(compare(r,I ) ) i=r; return i; }voidheapify(intindx )//堆维护while ) indxheap_size/2 )//根节点的inttemp=prior ) left ) indx ),right ) ELSEswap(data[indx],data[temp] ); indx=temp; }假设最佳情况,heaplify只需要一定的时间(indx节点不需要维护),但考虑到最坏情况,indx每次都必须移动到叶节点。 因此,时间复杂度为o(n ),n为初始indx的节点规模。

严格的方法是递归描述执行时间。

只有保证数组中的所有元素都满足堆的性质,才能形成两股堆。 有一种方法可以维护堆,但不需要维护每个元素。 理由是叶节点不需要维护,只需要根节点。

因此,从每个叶节点到根节点,对父节点递归执行堆维护操作。 由于总共进行了n/2次heaplify ()操作,堆维护的复杂度为o ) lgn ),因此估计渐进且不严格的复杂度之一为o ) O(nlogn )。

void build () heap_size=data.size ); for(intI=heap_size/2-1; i=0; I----heapify(I ); 但是,这里有个问题。 堆维护的复杂性与树的高度有关。 在生成堆的过程中,高度逐层上升,每层需要维护的节点数也越来越少。 对于高度为h的节点,堆维护只需要o(h )时间。

因此,在共享时:

hi=0nio(I )

这里,ni是高度I的堆中包含的节点数,可以如下求出。

nin/2i 1

赋值:

hi=0n/2I1o(I ) hi=0o (ni/2i ) ) )。

根据级数的知识对I求极限后得到的时间复杂度的上限为o(n )

详细的证明过程看起来像原书,但在这里只指出大致的思想和两个细节。 在原书中是证明问题。 节点数n的堆高度最大为lgn,高度h的堆节点数最大为n/2h 1

第一个(如果是二叉树,则节点共有n=2h个,所以积累到最大lgn的高度; 如果不是二叉树,节点数n2h,高度lgn向下整数化。

第二个:如果是二叉树的话,从下层到上层的元素是2lgnh,h是该层的高度,所以高度h的堆中包含的节点数是hi=02lgni=hi=0n(1/2) I,等比数列加起来,n 如果与二叉树方法不同,则结果为n/220

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。