堆排序比一般的排序算法略为复杂。
1.什么是二叉堆?
2.如何用数组描述一个二叉堆?
3.如果构建最大堆或最小堆
4.构建好最大堆或最小堆后,对堆的排序
堆的性质:(1)是棵完全二叉树;(2)某个节点的值总是大于或小于子节点(最大堆和最小堆)
算法过程:
1.构造最大堆或者最小堆(从小到大排序--->最大堆,从大到小排序--->最小堆)
2.然后把最上面的元素跟最末尾的元素互换,然后就不管最后一个,因为互换后,最后一个肯定是最大(/最小)值。
3.然后重新建造最大堆或者最小堆。再重复过程2,直到剩下最后一个元素。
1.什么是二叉堆?
二叉堆是完全二叉树或近似完全二叉树。而且任何父节点的键值都大于等于(或小于等于)任何一点子节点的兼职。
父节点键值大等于他的子节点的键值为最大堆,父节点键值小于等于他的子节点的键值为最小堆。
如下图,是一个二叉堆:
2.用数组描述一个二叉堆
如上面的二叉堆,用数组表示就是A[ 6 ] = {16,7,3,20,17,8};
这个方法跟描述树的方法是一样的。
3.构建最小堆(最大堆)
(以最大堆为例)
从堆 最后一个有叶子结点的结点 开始,设堆有 n 个元素,则该节点序号为:(n/2)-1,上图中该节点就是 3,也就是 A[ 6/2 -1 ] = A[2 ]
构建最大堆的过程:
原始堆。
先从 最后一个有叶子结点的结点(A[ 2 ]) 开始,8比3大,因此 位置互换。
然后到A[ 1 ] ,首先选出比较大的孩子结点,再跟父节点比,看哪个大。大的跟父节点换位置
然后到A[ 0 ].同上
把16换下来后,会发现红色圈的三个里面是 17 最大,因此把 17和 16的位置互换。
这就完成了最大堆了。可以开始排序
构成最大堆(or最小堆后):(又叫大根堆,小根堆)
def buildHeap(arr): #建堆:建堆的目的是 先给数组中的数字建立一个规律,即父节点大于(or小于)子节点
n = len(arr)
for i in reversed(range(n // 2)): #从最后一个非叶子结点开始
heapify(arr,n,i)
return arr
def heapify(arr,n,i):
left = 2*i+1
right = 2*i+2
max_index = i
if left<n and arr[left]>arr[i]: #arr[left]<arr[i]为建最小堆===》从大到小排序。
max_index = left #arr[left]>arr[i]为建最大堆===>从小到大排序
if right<n and arr[right]>arr[max_index]:
max_index = right
if max_index!=i:
arr[i],arr[max_index] = arr[max_index],arr[i]
heapify(arr,n,max_index)
def heapSort(arr):
arr = buildHeap(arr) #建堆
n = len(arr)
while n>0:
arr[0],arr[n-1] = arr[n-1],arr[0]
n-=1
heapify(arr,n,0) #再次堆化,把arr[0]的数值沉到堆的应有位置
return arr
a = [0,1,6,5,2,7,8,2,99,12,3]
b = heapSort(a)
print(b) #[0, 1, 2, 2, 3, 5, 6, 7, 8, 12, 99]
时间复杂度:O(nlogn) 空间复杂度O(1)
Java版本:
public class HeapSort {
public static void buildHeap(int[] arr,int n){
for(int i=n/2 -1;i>=0;i--){
heapify(arr,n,i);
}
}
public static void heapify(int[] arr,int n,int i){
int left = 2*i+1;
int right = 2*i+2;
int max_index = i;
if(left<n && arr[left]>arr[max_index]){
max_index = left;
}
if(right<n && arr[right]>arr[max_index]){
max_index = right;
}
if(max_index!=i){
int t = arr[i];
arr[i] = arr[max_index];
arr[max_index] = t;
heapify(arr,n,max_index);
}
}
public static void heapSort(int[] arr,int n){
buildHeap(arr,n);
while(n>0){
int t = arr[0];
arr[0] = arr[n-1];
arr[n-1] = t;
n--;
heapify(arr,n,0);
}
}
public static void main(String[] args) {
int[] arr = {1,3,4,3,2,3,5,6,3,3,1,2};
heapSort(arr,arr.length);
System.out.println(arr);
}
}