堆的图示以及代码实现

堆的Python代码实现

堆在计算机中能够帮助我们高效地按一定的规则存储和取出数据的方式,其通常用于实现优先队列。值得注意的是堆的结构与完全二叉树基本一致,即当第k层填满时,才会开始填充第k+1层。

一、代码实现

1. 堆的存储结构

  通常使用数组(动态数组)或链表作为堆的存储结构,在python中列表是一种动态数组结构,可以帮助我们定义任意大小的堆。
class Heap:
		def __init__(self, compare_function):
				self.store = []
				# 对于大顶堆compare_function = lambda x,y: x > y
				self.compare_function = compare_function
 其中对于列表索引为i的结点,其父结点索引为$\lfloor \frac{(i-1)}{2} \rfloor$,其左子结点索引为$2\times i + 1$,右结点索引为$2 \times \,i +2$ 。
  1. 大顶堆的插入操作

堆的存储结构如下图所示,

9
8
7
6
5
4
3
10

堆的逻辑结构如下图所示,其中粉红色结点为待插入结点

9
8
7
6
5
4
3
10
  1. 插入结点与其父节点比较,由于10 > 6 ,则二者调换位置
9
8
7
6
5
4
3
10

调换后,结果如下

9
8
7
10
5
4
3
6
9
8
7
10
5
4
3
6

通过循环对父节点进行比对和交换,最终可以得到最终的大顶堆

10
9
7
8
5
4
3
6

代码如下所示:

def parent(self, i):
        return (i - 1) // 2

def insert(self,val):
        self.store.append(val)
        t = len(self.store) - 1
        while t > 0 and self.cmp_function(self.store[t],self.store[self.parent(t)]):
            self.store[t],self.store[self.parent(t)] = self.store[self.parent(t)],self.store[t]
            t = self.parent(t)

3. 堆的删除操作(获取堆顶并删除)

首先将堆顶取出,并将最后结点放在堆顶。

6
9
7
8
5
4
3
10

通过将蓝色结点与其最大子结点交换,可得

9
6
7
8
5
4
3
10

交替进行,最终得到

9
8
7
6
5
4
3
10

其代码可写为:

def delete(self):
        heap_top = self.store[0]
        self.store[0] = self.store[-1]
        self.store.pop()
        len_ = len(self.store)
        i = 0
        while 2*i + 1 < len_:
            l,r = 2*i+1,2*i+2
            temp = l
            if r < len_ and self.cmp_function(self.store[r],self.store[temp]):
                temp = r
            if self.cmp_function(self.store[temp],self.store[i]):
                self.store[temp],self.store[i] = self.store[i],self.store[temp]
                i = temp
            else:
                break
        return heap_top

4. 堆的代码实现

class Heap:
    def __init__(self,cmp_function):
        self.cmp_function=cmp_function # 如果要交换返回True
        self.store = []

    def parent(self, i):
        return (i - 1) // 2

    def insert(self,val):
        self.store.append(val)
        t = len(self.store) - 1
        while t > 0 and self.cmp_function(self.store[t],self.store[self.parent(t)]):
            self.store[t],self.store[self.parent(t)] = self.store[self.parent(t)],self.store[t]
            t = self.parent(t)

    def delete(self):
        heap_top = self.store[0]
        self.store[0] = self.store[-1]
        self.store.pop()
        len_ = len(self.store)
        i = 0
        while 2*i + 1 < len_:
            l,r = 2*i+1,2*i+2
            temp = l
            if r < len_ and self.cmp_function(self.store[r],self.store[temp]):
                temp = r
            if self.cmp_function(self.store[temp],self.store[i]):
                self.store[temp],self.store[i] = self.store[i],self.store[temp]
                i = temp
            else:
                break
        return heap_top

    def __getitem__(self,index):
        return self.store[index]

    def __len__(self):
        return len(self.store)

猜你喜欢

转载自blog.csdn.net/YmgmY/article/details/129304941