【算法——Python实现】最小索引堆,最小堆的优化

class IndexMinHeap(object):
    """
    最小反向索引堆,出堆不删除data,只删除indexs
    """
    def __init__(self, n):
        self.capacity = n # 堆的最大容量
        self.data = [-1 for _ in range(n)]  # 创建堆
        self.indexs = [] # 创建索引堆
        self.reverse = [-1 for _ in range(n)] # 创建反向索引
        self.count = 0  # 元素数量

    def size(self):
        return self.count

    def isEmpty(self):
        return self.count == 0

    def contain(self, i):
        # 最小堆中是否包含i索引的元素
        return self.reverse[i] != -1

    def insert(self, i, item):
        # 插入元素入堆
        self.data[i] = item
        self.indexs.append(i)
        self.reverse[i] = self.count
        self.count += 1
        self.shiftup(self.count)

    def shiftup(self, count):
        # 将插入的元素放到合适位置,保持最小堆
        while count > 1 and self.data[self.indexs[(count/2)-1]] > self.data[self.indexs[count-1]]:
            self.indexs[(count/2)-1], self.indexs[count-1] = self.indexs[count-1], self.indexs[(count/2)-1]
            self.reverse[self.indexs[(count/2)-1]] = (count/2)-1
            self.reverse[self.indexs[count-1]] = count-1
            count /= 2

    def extractMin(self):
        # 出堆
        if self.count > 0:
            ret = self.data[self.indexs[0]]
            self.indexs[0], self.indexs[self.count-1] = self.indexs[self.count-1], self.indexs[0]
            self.reverse[self.indexs[0]] = 0
            self.reverse[self.indexs[self.count-1]] = self.count-1
            # for i in range(self.indexs[self.count-1]+1, self.count):
            #   self.indexs[self.reverse[i]] -= 1
            self.reverse[self.indexs[self.count-1]] = -1
            # self.data[self.indexs[self.count-1]] = -1
            self.indexs.pop(self.count-1)
            self.count -= 1
            self.shiftDown(1)
            return ret

    def extractMinIndex(self):
        # 出堆返回索引
        if self.count > 0:
            ret = self.indexs[0]
            self.indexs[0], self.indexs[self.count-1] = self.indexs[self.count-1], self.indexs[0]
            self.reverse[self.indexs[0]] = 0
            self.reverse[self.indexs[self.count-1]] = self.count-1
            # for i in range(self.indexs[self.count-1]+1, self.count):
            #   self.indexs[self.reverse[i]] -= 1
            self.reverse[self.indexs[self.count-1]] = -1
            # self.data[self.indexs[self.count-1]] = -1
            self.indexs.pop(self.count-1)
            self.count -= 1
            self.shiftDown(1)
            return ret

    def shiftDown(self, count):
        # 将堆的索引位置元素向下移动到合适位置,保持最小堆
        while 2 * count <= self.count :
            # 证明有孩子
            j = 2 * count
            if j + 1 <= self.count:
                # 证明有右孩子
                if self.data[self.indexs[j]] < self.data[self.indexs[j-1]]:
                    # 右孩子数值比左孩子数值小
                    j += 1
            if self.data[self.indexs[count-1]] <= self.data[self.indexs[j-1]]:
                # 堆的索引位置已经小于两个孩子节点,不需要交换了
                break
            self.indexs[count-1], self.indexs[j-1] = self.indexs[j-1], self.indexs[count-1]
            self.reverse[self.indexs[count-1]] = count-1
            self.reverse[self.indexs[j-1]] =j-1
            count = j

    def getItem(self, i):
        # 根据索引获取数值
        if i >=0 and i <= self.count-1:
            return self.data[i]
        else:
            return None

    def change(self, i, newItem):
        # 改变i索引位置的数值
        if i >=0:
            self.data[i] = newItem
            j = self.reverse[i]
            self.shiftup(j+1)
            self.shiftDown(j+1)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值