什么是最大堆和最小堆,最小堆和最大堆

  什么是最大堆和最小堆,最小堆和最大堆

  背景知识:

  这是一棵完整的二叉树。什么是完全二叉树?除了最后一层节点,其他层的节点数必须最大,最后一层的节点必须全部集中在左侧。堆分为最大堆和最小堆。最大堆是当父节点大于或等于子节点时,导致根节点是最大的。最小堆意味着父节点小于或等于子节点,导致根节点最小。本文基于最大堆解释,并提供了python代码实现。1.背景知识中提到,堆是一棵完全二叉树,最大堆的特征是父节点大于等于子节点。要更直观地了解最大堆是什么,请参见下图:

  图A是最大堆。第一,满足完全二叉树的性质,即除了最后一层节点外,其他层的节点数达到最大,最后一层节点全部集中在左侧。其次,满足最大性质,即每个父节点的值大于等于子节点。

  图B不是最大堆,因为它不是完全二叉树,因为第二层的节点数没有达到最大。

  图C不是最大的堆。虽然除了最后一层,它的节点数最多,但最后一层的节点并不集中在左侧。

  图D不是最大堆。虽然从定义上来说是完全二叉树,但是并不满足最大堆的每个父元素的值都大于等于子元素,因为我们可以清楚的看到62是50的右子。

  2.经过上面的分析,相信读者对最大堆已经有了深刻的理解,然后如果我们从上到下从左到右对最大堆进行排序,例如:

  我们可以发现,左边孩子的下标是父亲下标的两倍,右边孩子的下标是父亲下标的两倍加一,父亲下标是孩子下标除以二。基于这个性质,我们可以使用数组的数据结构来存储最大堆。

  3.利用数组的数据结构构建最大堆的过程称为上移。什么是升档?在数组中添加一个元素后,根据新添加的子元素的下标找到父元素的下标,比较两个元素的大小。如果父亲的值小于孩子的值,交换相应的值,然后向前比较,以此类推,直到父亲的值小于孩子的值,然后停止。具体代码实现:

  import random class maxstack:def _ _ init _ _(self):#将下标为0的元素赋值为0,说明约束下标0不可用,因为这种情况下实现的最大堆是self.data=[0] self.count=0 #第一个元素是def insert(self,Item):self . data . append(Item)self . count=1 self。_ _ ShiftUp (self.count) #判断新添加的元素是否大于父元素,如果是,则切换位置,以此类推def __shiftUp(self,count): while count 1和self . data[count//2]self . data[count]:self . data[count//2]=self . data[count//2]count=count//2IF _ _ name _ _= _ _ main _ :stack=max stack()for I in range(0,10): stack.insert (random我们都知道树形结构是取根元素的,最大堆也是,也就是下标1的元素就是根元素。这时候就不得不提一个对应升档、降档操作的操作。什么是降档操作?当我们取出数组的第一个元素,也就是下标为1的元素,交换第一个元素和最后一个元素的值,删除最后一个元素,那么数组可能不满足最大堆的性质。怎么解决?从根元素开始,比较两个子元素的大小,将较大的子元素与父元素进行比较。如果它小于父元素,则停止;否则,交换位置,依次向下跟踪,直到该节点是叶节点(即没有子节点)或者父元素的值大于子元素的值。具体代码实现如下:

  import random class maxstack:def _ _ init _ _(self):#将下标为0的元素赋值为0,说明约束下标0不可用,因为本例实现的最大堆从下标1开始,self.data=[0] self.count=0 #获取元素:堆的元素获取只能获取根节点,即下标为1的元素,然后将最后一个元素移到根节点。那么count减1相当于去掉最后一个元素def get max (self):如果self . count=0:return root=self . data[1]self . data[1],self . data[self . count]=self . data[self . count],Self.data [1] self.count-=1self。_ _ ShiftDown (1) returnRoot #首先比较当前节点的两个子节点的大小,如果较大的子节点大于父元素,则交换位置def __shiftDown(self,key): #在一个完整的二叉树中,只要有一个左节点,那么这个节点就有子节点, 因为完全二叉树在2 * key=self.count时没有右节点也没有左节点:#默认变化指向左节点变化=2 * key #如果有右节点且右节点大于左节点,则加1变化,此时, 如果change 1=self.count和self . data[change 1]self . data[change]:change=1 #经过以上两步,此时change指向的值是if self . data[change]=self . data[key]:break self . data[change],self.data [key]=self.data [key],self.data [change] key=change5。 完整的python测试案例:

  导入random#最大堆的实现(完全二叉树,且父元素大于等于子元素),使用array的方法(python中使用list)。class MaxStack:def _ _ init _ _(self):#将下标为0的元素赋值为0,显示约束下标0不可用,因为这种情况下实现的最大堆是self . data=[0]self . count=0 def is _ empty(self):返回0!=self.count def get _ size (self):返回self.count #第一个元素是def insert(self,Item):self . data . append(Item)self . count=1 self。_ _ ShiftUp (self.count) #判断新添加的元素是否大于父元素,如果是,则切换位置,以此类推def __shiftUp(self,count): while count 1和self . data[count//2]self . data[count]:self . data[count]=self . data[count],self . data[count]=self . data[count//2]count=count//2 # Get elements:堆的元素获取只能获取根节点,即下标为1的元素,然后移动最后一个元素那么count减1相当于去掉最后一个元素def get max (self):如果self . count=0:return root=self . data[1]self . data[1],self . data[self . count]=self . data[self . count],Self.data [1] self.count-=1self。 _ _ ShiftDown (1) returnRoot #首先比较当前节点的两个子节点的大小,如果较大的子节点大于父元素,则交换位置def __shiftDown(self,key): #在一个完整的二叉树中,只要有一个左节点,那么这个节点就有子节点, 因为完全二叉树在2 * key=self.count时没有右节点也没有左节点:#默认变化指向左节点变化=2 * key #如果有右节点且右节点大于左节点,则加1变化,此时, 如果change 1=self.count和self . data[change 1]self . data[change]:change=1 #经过以上两步,此时change指向的值为if self . data[change]=self . data[key]:break self . data[change],self.data [key]=self.data [key],self . data[change]key=change if _ _ name _ _= _ _ main _ :stack=max stack()list=[random . randint(10,100)对于范围内的I end= )print(list)for I in range(0,100):stack . insert(list[I])print(最大堆数组:,end= ) print(stack.data) #循环出堆的元素,可以发现最大堆循环取出的元素是whilestack.stack。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: