Python Heap堆的实现

Python 堆的实现

1.是一个有序数据类型,分为大根堆与小根堆
2.抽象数据类型:总是一颗完全二叉树,父子节点有序。需要实现的基本功能:获取最大/最小元素;插入节点
3. 具体存储结构:一般使用顺序存储结构/数组
4. python实现:set类型:从0创建堆;插入节点;删除根节点;从现有数据直接创建堆。get类型:获取最大/最小元素
5. 根堆插入节点:自下而上,percup()辅助函数。
6. 删除根节点:将最后一个叶子节点替换根节点,然后自上而下,percdown()辅助函数。
7. 以上两种自上而下 or 自下而上 的操作,本质上是为了不在插入或删除元素的时候,移动数组元素(只做了交换操作) and 破环有序结构。
8. 如果先查找应该插入的元素的位置,再插入–>查找的时间、插入移动元素的时间。后者就已经O(n)了

注意点:
使用现有数组直接构建堆,是借助percdown() 或者 percup()辅助函数实现的。

  • 从最后一个叶子节点的父节点开始遍历【索引是((heap list 的长度-1)-1)// 2,记得使用整除】,直至根节点,对每一个节点percdown()。
  • 从第二层第一个节点开始遍历,直至最后一个叶子节点,对每一个节点percup()。

python实现

class Heap:
    def __init__(self):
        """书上将0位置赋值0,只是为了做整数除法,这里不用这种处理"""
        self.heap_list = []
        self.size = 0

    def insert(self, new_node):
        self.heap_list.append(new_node)
        new_index = self.size
        self.percup(new_index)
        self.size += 1

    def percup(self, i):
        """
        辅助函数,将节点上浮至堆中合适位置
        i: 需要上浮的元素在数组中的索引
        return: None
        """
        # 循环直到达到根节点 or 达到合适位置
        swap_flag = True
        while i > 0 and swap_flag:
            swap_flag = False
            father_index = int((i - 1) / 2)
            if self.heap_list[i] > self.heap_list[father_index]:
                self.heap_list[i], self.heap_list[father_index] = self.heap_list[father_index], self.heap_list[i]  # 交换
                i = father_index
                swap_flag = True
            # 如果swap_flag是False,就说明达到合适位置。

    def remove(self):
        """
        删除根节点,借助辅助函数percdown
        :return: None
        """
        root = self.heap_list[0]
        self.heap_list[0] = self.heap_list[-1]  # 将根节点替换成叶子节点
        self.heap_list.pop()
        self.size -= 1
        self.percdown(0)

        return root

    def percdown(self, i):
        """辅助函数:如果比两个叶子节点都小,就下沉; 直到没有叶子节点 or 合适位置"""
        current = i
        child_index = self.maxChild(current)
        swap_flag = True
        while child_index is not None and swap_flag:
            swap_flag = False
            if self.heap_list[current] < self.heap_list[child_index]:
                self.heap_list[current], self.heap_list[child_index] = self.heap_list[
                                                                           child_index], self.heap_list[current]  # 交换
                current = child_index
                child_index = self.maxChild(current)
                swap_flag = True

    def maxChild(self, i):
        """
        辅助函数,返回最小孩子的index,如果没有孩子,就返回None
        """
        if 2 * i + 1 > self.size - 1:  # 没有子节点
            return None
        else:
            if 2 * i + 2 > self.size - 1:  # 没有右子节点
                return 2 * i + 1
            else:
                if self.heap_list[2 * i + 1] >= self.heap_list[2 * i + 2]:
                    return 2 * i + 1
                else:
                    return 2 * i + 2

    def getRoot(self):
        return self.heap_list[0]

    def isEmpty(self):
        """判断是否为空"""
        return self.size == 0

    def createheap(self, data):
        """将现有数据直接转换成堆
        自上而下percup
        这种需要从第二层遍历到底部"""
        self.heap_list = data
        self.size = len(data)
        for i in range(self.size):
            self.percup(i)

    def createHeap(self, data):
        """将现有数据直接转换成堆
                自下而上percdown
                这种需要从导数第二层遍历到顶部
                从最后一个节点的父开始"""
        self.heap_list = data
        self.size = len(data)
        for i in range((self.size-2) // 2 , -1, -1):
            self.percdown(i)

测试

rand_list = [random.randrange(200) for i in range(200)]
rand_list_copy = rand_list[:]
print("初始数组:")
print(rand_list)
my_heap = Heap()
my_heap.createheap(rand_list)
print("初始heap:")
print(my_heap.heap_list)

my_heap_oderlist = []
while not my_heap.isEmpty():
    my_heap_oderlist.append(my_heap.remove())
print(my_heap_oderlist)


print()
print('----------------------------------------------------')
heap_2 = Heap()
heap_2.createHeap(rand_list_copy)
print(heap_2.heap_list)
heap_2_orderlist = []
while not heap_2.isEmpty():
    heap_2_orderlist.append(heap_2.remove())

print(heap_2_orderlist)

print(heap_2_orderlist == my_heap_oderlist)
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值