python实现最大堆,最小堆和堆排序

目录

 

0.什么是堆

1.最大堆的实现

2.最小堆的实现

3.堆排序


python实现最大堆,最小堆和堆排序_第1张图片

0.什么是堆

小堆和大堆分为如下图: 

堆需要满足的条件:

1. 必须是二叉树,且必须是完全二叉树

2. 各个父节点必须大于或小于左右结点, 其中最顶层的根结点必须是最大或者最小的

堆可以使用list实现,就是按照层序遍历顺序将每个节点上的值存放在数组中。父节点和子节点之间存在如下的关系:
i 从0 开始
 parent = (i-1) // 2; left = 2*i + 1 ; right = 2*(i+1)

1.最大堆的实现

堆使用数组的形式表示,不需要使用指针

 

2. 在堆中增加元素

3,删除根节点,并重建堆结构

 

#最大堆的实现
class MaxHeap():
    def __init__(self, maxSize=None):
        self.maxSize = maxSize 
        self.li = [None] * maxSize
        self.count = 0
    
    def length(self):
        #求数组的长度
        return self.count 
    
    def show(self):
        if self.count <= 0:
            print('null')
        else:
            print(self.li[: self.count])
    
    def add(self, value):
        if self.count >= self.maxSize: #判断是否数组越界
            raise Exception('full')
        
        self.li[self.count] = value #将新节点增加到最后
        self._shift_up(self.count) # 递归构建大堆
        self.count += 1
    
    def _shift_up(self, index):
        #往大堆中添加元素,并保证根节点是最大的值:
        #1.增加新的值到最后一个结点,在add实现; 2.与父节点比较,如果比父节点值大,则交换
        if index > 0:
            parent = (index - 1) // 2 # 找到根节点
            if self.li[index] > self.li[parent]: #交换结点
                self.li[index], self.li[parent] = self.li[parent], self.li[index]
                self._shift_up(parent) #继续递归从底往上判断
            
    def extract(self):    
        #弹出最大堆的根节点,即最大值
        #1.删除根结点,将最后一个结点作为更结点 ; 2.判断根结点与左右结点的大小,交换左右结点较大的
        if not self.count:
            raise Exception('null')
        value = self.li[0] 
        self.count -= 1
        self.li[0] = self.li[self.count]  #将最后一个值变为第一个
        self._shift_down(0)
        return value
    
    def _shift_down(self, index):
        # 1.判断是否有左子节点并左大于根,左大于右;2.判断是否有右子节点,右大于根
        left = 2 * index +1
        right = 2 * index + 2
        largest = index 
        #判断条件
# 下面2个条件包含了,判断左右结点那个大的情况。如果为3, 4, 5,:
第一个判断条件使得largest=1,再执行第二个条件,则判断其左结点与右结点的大小
       if left < self.length() and self.li[left] > self.li[largest]:
            largest = left
        if right < self.length() and self.li[right] > self.li[largest]:
            largest = right

        if largest != index: # 将 两者交换
            self.li[index], self.li[largest] = self.li[largest], self.li[index]
            self._shift_down(largest)
        

m = MaxHeap(10)  
import numpy as np 
np.random.seed(123)
num = np.random.randint(100, size =10) #创建随机的10个数
print(m.length())
for i in num:
    m.add(i)
m.show()    
print(m.length())     
for i in range(5):
    print(m.extract(), end=' ,') 

 

2.最小堆的实现

#构造最小堆 
class MinHeap():
    def __init__(self, maxSize=None):
        self.maxSize = maxSize 
        self.array = [None] * maxSize 
        self._count = 0
    
    def length(self):
        return self._count 
    
    def show(self):
        if self._count <= 0:
            print('null')
        print(self.array[: self._count], end=', ')
    
    def add(self, value):
        #增加元素
        if self._count >= self.maxSize:
            raise Exception('The array is Full')
        self.array[self._count] = value
        self._shift_up(self._count)
        self._count += 1
    
    def _shift_up(self, index):
        #比较结点与根节点的大小, 较小的为根结点
        if index > 0:
            parent = (index - 1) // 2
            if self.array[parent] > self.array[index]:
                self.array[parent], self.array[index] = self.array[index], self.array[parent]
                self._shift_up(parent)
    
    def extract(self):           
        #获取最小值,并更新数组
        if self._count <= 0:
            raise Exception('The array is Empty')
        value = self.array[0]
        self._count -= 1 #更新数组的长度
        self.array[0] = self.array[self._count] #将最后一个结点放在前面
        self._shift_down(0)
        
        return value 
             
    def _shift_down(self, index):  
        #此时index 是根结点
        if index < self._count:
            left = 2 * index + 1
            right = 2 * index + 2
            #判断左右结点是否越界,是否小于根结点,如果是这交换
            if left < self._count and right < self._count and self.array[left] < self.array[index] and self.array[left] < self.array[right]:
                self.array[index], self.array[left] = self.array[left], self.array[index] #交换得到较小的值
                self._shift_down(left)
            elif left < self._count and right < self._count and self.array[right] < self.array[left] and self.array[right] < self.array[index]:
                self.array[right], self.array[index] = self.array[index], self.array[right]
                self._shift_down(right)
            
            #特殊情况: 如果只有做叶子结点
            if left < self._count and right > self._count and self.array[left] < self.array[index]:
                self.array[left], self.array[index] = self.array[index], self.array[left]
                self._shift_down(left)

mi = MinHeap(10)
print()
print('-------小顶堆----------')
for i in num:
    mi.add(i)
mi.show()
print(mi.length())
for _ in range(len(num)):
    print(mi.extract(), end=', ')
print()
print(mi.length())

参考:https://blog.csdn.net/qq_23869697/article/details/82735088

https://python-data-structures-and-algorithms.readthedocs.io/zh/latest/15_%E5%A0%86%E4%B8%8E%E5%A0%86%E6%8E%92%E5%BA%8F/heap_and_heapsort/#_4

 

3.堆排序

def maxHeapfy(alist, length, parent):
    left = 2 * parent + 1
    right = 2 * parent + 2
    largest = parent
    if left < length and alist[left] > alist[largest]:
        largest = left
    if right < length and alist[right] > alist[largest]:
        largest = right
    if largest != parent:
        alist[largest], alist[parent] = alist[parent], alist[largest]
        maxHeapfy(alist, length, largest)  # 递归构建

def buildMaxHeap(alist):  # 构建最大堆
    n = len(alist)
    lastParent = (n-1) // 2
    for i in range(lastParent, -1, -1):
        maxHeapfy(alist, n, i)

def heapSort(alist):
    buildMaxHeap(alist)
    n = len(alist)
    for i in range(n-1, -1, -1):
        alist[0], alist[i] = alist[i], alist[0]  # 将最大值放在最后面
        maxHeapfy(alist, i, 0)
    return alist

a = [30,50,57,77,62,78,94,80,84]
print(a)
print(heapSort(a))
alist = [2, 4, 1, 2, 5, 58, 45, 24, 67]
print(heapSort(alist))
b = [random.randint(1,1000) for i in range(1000)]
print(b)
print(heapSort(b))

 

 

 

你可能感兴趣的:(leetcode)