堆排序
Posted a-runner
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了堆排序相关的知识,希望对你有一定的参考价值。
1 堆
堆是一个二叉堆的数组,可以被看成一个近似的完全二叉树。
有最大堆和最小堆的性质。最大堆就是某个节点的值至多于其父节点一样大。最小堆中最小的元素都存放在根节点中。
下面放上最小堆的伪代码:
MIN-HEAPIFY(A, i) l = LEFT(i) r = RIGHT(i) if l <= A.heap-size and A[l] < A[i] smallest = l else smallest = i if r <= A.heap-size and A[r] < A[smallest] smallest = r if smallest !=i exchange A[i] with A[smallest] MIN-HEAPIFY(A, smallest)
2 建堆
建堆 ,采用紫霞而上的方法。每个节点的左右孩子节点都是最大堆。
BUILD-MAX-HEAP(A): A.heap-size = A.length; //heap-size代表整个数组中在堆中的元素个数 for i = A.length/2 downto 1: MAX-HEAPIFY(i)
3 堆排序算法
因为,建堆之后,堆的根节点是整个数的最大节点,可以提取出来,在堆剩下的数进行建堆的处理。
我们从A.length到2循环调用,直到堆的元素只有两个。
HEAP-SORT(A): BUILD-MAX-HEAP(A); //构建最大堆 for i = A.length downto 2: exchange A[i] and A[1]; A.heap-size = A.heap-size-1; MAX-HEAPIFY(i); # 此后的左右子树都是最大堆
MAX-HEAPIFY的时间复杂度:
写出递归式: T(n)<=T(2n/3) + 1, 根据主方法确定时间复杂度为 log(n)。
时间复杂度为nlog(n).因为内次调用MAX-HEAPIFY的时间复杂度为log(n),进行n-1次循环。
对于按升序排列包含n个元素的有序数组来A说,HEAPSORT的时间复杂度为nlog(n),降序排列也一样。在SORT中,首先执行一次的BUILD,复杂度为n,之后进行(n-1)次MAX-HEAPIFY,进行递归的调用。
4 优先序列
有限队列是一种用来维护由一组元素构成的集合S的数据结构,每一个元素都有一个相关的值,称为关键字,key。
附上相关代码:
import math class Stack(): def __init__(self, a): self.a = a self.length = len(a)-1 self.heap_size = len(a)-1 def left(self, i): if 2 * i <= self.heap_size: return 2*i else: return None def right(self, i): if (2 * i + 1) <= self.heap_size: return (2*i+1) else: return None def parent(self,i): return math.floor(i/2) def max_heapify(self, i): l = self.left(i) r = self.right(i) largest = 0 if l: if self.a[l]>self.a[i]: largest = l else: largest = i if r: if self.a[r]>self.a[largest]: largest = r if largest!=i and largest!=0: self.a[i], self.a[largest] = self.a[largest], self.a[i] self.max_heapify(largest) def build_max_heap(self): for i in range(math.floor(self.length/2),0,-1): self.max_heapify(i) # 对最大堆进行排序 def heap_sort(self): self.build_max_heap() for i in range(self.length,1,-1): self.a[i],self.a[1] = self.a[1],self.a[i] self.heap_size -= 1 self.max_heapify(1) def sorted(self): print(‘升序排列的 最大堆元素(0除外):‘) for i in self.a: print(i,end=‘ ‘) # 返回当前具有最大关键字的元素的值(下一个要执行的优先级) def heap_maximum(self): return self.a[1] # 去掉并返回a中具有最大键子的元素 def heap_extract_max(self): if self.heap_size <1: print(‘heap underflow‘) raise max = self.a[1] self.a[1] = self.a[self.heap_size] self.heap_size -=1 self.max_heapify(1) return max # 改变某元素的关键字,增加到k,重新构建最大堆 def heap_increase_key(self,i,key): if key<self.a[i]: print(‘new key is smaller than current key‘) raise self.a[i] = key while i>1 and self.a[self.parent(i)]<self.a[i]: self.a[i],self.a[self.parent(i)] = self.a[self.parent(i)],self.a[i] i = self.parent(i) def max_heap_insert(self, key): self.heap_size += 1 self.a[self.heap_size] = 0 self.heap_increase_key(self.heap_size,key) if __name__ == ‘__main__‘: b = [0,3,8,5,6,1,32,13,18] a = Stack(b) a.heap_sort() a.sorted()
对于优先队列的操作有:插入,改变优先级等。在包含n个元素的堆中,所有优先队列的操作都可以在log(n)时间内完成。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
将k个有序列表合并为一个有序列表,这里的n是所有输入链表包含的总的元素的个数。大致思路为:
时间复杂度:因为有k个链表,总共有n个元素,因此发生了n次的最小堆化,时间复杂度为O(nlgk)
以上是关于堆排序的主要内容,如果未能解决你的问题,请参考以下文章