堆排序
利用堆这种数据结构进行排序的一种算法,它是选择排序的一种。
我们可以把堆看成一棵完全二叉树,这棵完全二叉树满足:
- 任何一个非叶结点的值都不大于(或不小于)其左右孩子结点的值。
- 若父亲大孩子小,则这样的堆叫做大堆;
- 若父亲小孩子大,则这样的堆叫作小堆。
大堆:每个节点的值大于等于孩子节点的堆)
小堆:每个节点的值小于等于孩子节点的堆
基本思想
代表堆的完全二叉树的根结点的值是最值的,也是数组的第一个元素,将一个无序序列调整为一个堆,就可以找出这个序列的最值,然后将找出的这个最大值交换到序列的最后(或最前),这样有序序列关键字增加1个,无序序列关键字减少1个,对新的无序序列重复这样的操作,就实现了排序。
注意:
堆排序中最关键的操作是将序列调整为堆,整个排序的过程就是通过不断调整,使得不符合堆定义的完全二叉树变为符合堆定义的完全二叉树。
堆的存储结构:
逻辑结构:
内存结构:
代码实现:
//堆化
void heapify(int a[], int size, int index){
int left = index * 2 + 1;
int right = index * 2 + 2;
int max;
if (left > size||right>size){
return;
}
max = a[left] >= a[right] ? left : right;
if (a[index] >= a[max]){
return;
}
else{
swap(a[index], a[max]);
heapify(a, size, max);
}
}
//建堆
int creatHeap(int a[],int size){
for(int i=size/2-1;i>=0;i--){ //从最后一个叶节点的双亲节点开始堆化
heapify(a,size,i);
}
}
void HeapSort(int a[], int size){
creatHeap(a, size);
for (int i = size-1; i >= 0; i--){
swap(a[0], a[i]);
heapify(a, i - 1, 0);
}
}
堆排序的特性总结:
- 堆排序使用堆来选数,效率就高了很多
- 时间复杂度:O(N*logN)
- 空间复杂度:O(1)
- 稳定性:不稳定