堆实现优先队列以及初始化堆的时间复杂度分析

定义

优先队列是利用堆来实现的,堆可以看做是一棵完全二叉树的顺序存储结构。在这棵二叉树中,如果每一个节点的值都大于等于左右孩子的值,则称之为“最大堆”。如果每一个节点的值都小于等于左右孩子的值,则称之为“最小堆”。

应用

在算法设计中,经常用到从序列中找一个最小值(最大值)的操作,例如最短路径,哈夫曼编码等都需要找到一个最小值,如果从序列中顺序查找最值需要 O ( n ) O(n) O(n)
的时间。而从优先队列中查找最值,则需要 O ( l o g n ) O(logn) O(logn)的时间。
优先队列中堆的创建需要 O ( n ) O(n) O(n)的时间(下面讲解原因),而取最值只需要 O ( l o g n ) O(logn) O(logn)的时间。也就是二叉树的高度。

python创建最大堆

# coding=utf-8


class Heap(object):
    def __init__(self, nums):
        """
        创建最大堆
        :param nums:
        """
        self.nums = nums
        self.length = len(nums)
        
    
    def _sink(self, k):
        """
        节点下沉
        :param k: 
        :return: 
        """
        while 2 * k < self.length:
            j = 2 * k # 指向右孩子
            if j < self.length and self.nums[j] < self.nums[j + 1]:
                j += 1 # 指向左孩子
            if self.nums[k] >= self.nums[j]:
                break #满足最大堆
            else:
                self.nums[k], self.nums[j] = self.nums[j], self.nums[k]
            k = j
    
    def create(self):
        i = self.length // 2
        # 从最后一个分支节点n/2开始下沉调整为堆,直到第一个节点
        while i >= 0:
            self._sink(i)
            i -= 1

if __name__ == '__main__':
    nums = [12,16,2,30,28,20,16,6,10,18]
    heap = Heap(nums)
    heap.create()
    print(heap.nums)
    

创建堆的时间复杂度

在这里插入图片描述
这里有一个二叉树的简化图,节点没有填值(聚焦分析)。设节点总数为n,二叉树高度 k = l o g 2 n k=log_2{n} k=log2n。则有1/2的节点需要下沉1次,有1/4的节点需要下降2次…有1/2**k的节点需要下降k次。其中1/2**k<=1。
所有节点下沉总次数为:
T = ∑ k = 1 l o g 2 n ( 1 2 k ∗ k ) ∗ n T = \sum_{k=1}^{log_2^n}{(\frac{1}{2^k}*k)}*n T=k=1log2n(2k1k)n

s = ∑ k = 1 l o g 2 n 1 2 k ∗ k = 1 2 ∗ 1 + 1 4 ∗ 2 + . . . + 1 2 k ∗ k s = \sum_{k=1}^{log_2^n}{\frac{1}{2^k}*k}=\frac{1}{2}*1+\frac{1}{4}*2+...+\frac{1}{2^k}*k s=k=1log2n2k1k=211+412+...+2k1k

s 2 = 1 4 ∗ 1 + 1 8 ∗ 2 + . . . + 1 2 k + 1 ∗ k \frac{s}{2} =\frac{1}{4}*1+\frac{1}{8}*2+...+\frac{1}{2^{k+1}}*k 2s=411+812+...+2k+11k
s − s 2 = 1 2 + 1 4 + 1 8 + . . . + 1 2 k − 1 2 k + 1 ∗ k s-{\frac{s}{2}} =\frac{1}{2}+\frac{1}{4}+\frac{1}{8}+...+\frac{1}{2^k}-\frac{1}{2^{k+1}}*k s2s=21+41+81+...+2k12k+11k

s − s 2 s-{\frac{s}{2}} s2s的前k项为等比数列求和 a 1 ( 1 − q n ) 1 − q = 1 − ( 1 2 ) n \frac{a_1(1-q^n)}{1-q}=1-(\frac{1}{2})^n 1qa1(1qn)=1(21)n,最后一项趋近0
s 2 \frac{s}{2} 2s趋近1,s趋近2。故时间复杂度T为 O ( n ) O(n) O(n)
有问题可以交流,q我:1678354579

猜你喜欢

转载自blog.csdn.net/weixin_42662358/article/details/101979639
今日推荐