堆排序算法是选择排序的一种,该算法只是通过堆,最大堆、或者最小堆选择出一个待排序序列中的最大值,或者最小值。
什么是堆:
n个关键字序列Kl,K2,…,Kn称为(Heap),当且仅当该序列满足如下性质(简称为堆性质): (1)ki<=k(2i)且ki<=k(2i+1)(1≤i≤ n),当然,这是小根堆,大根堆则换成>=号。//k(i)相当于二叉树的非叶结点,K(2i)则是左孩子,k(2i+1)是右孩子
排序过程:
不断的交换,得到堆顶最大元素9,堆顶与堆尾交换,除了9重新变成一个无序堆
重新生成堆
再把堆顶与倒数第二位交换,除了9,8剩下的又变成一个无序堆
重新生成堆
.....
生成一个完全有序堆
堆排序的C语言实现
#include <stdio.h>
#include <stdlib.h>
void HeapSort(int num[],int size);
void BuildHeap(int num[] ,int size);
void PercolateDown(int num[] , int index,int size);
void PrintHeap(const char* strMsg,int array[],int nLength);
void Swap(int num[] , int v, int u);
int main(int argc, char *argv[])
{
int data[13]={8,5,4,6,13,7,1,9,12,11,3,10,2};
HeapSort(data,13);
system("PAUSE");
return 0;
}
void HeapSort(int num[] ,int size)
{
int i;
int iLength=size;
PrintHeap("Befor Sort:",num,iLength);
BuildHeap(num,size);// 建立小顶堆
for (i = iLength - 1; i >= 1; i--) {
Swap(num, 0, i);// 交换
size--;// 每交换一次让规模减少一次
PercolateDown(num, 0,size);// 将新的首元素下滤操作
PrintHeap("Sort Heap:",num,iLength);
}
}
// 建堆方法,只需线性时间建好
void BuildHeap(int num[] ,int size) {
int i;
for (i = size / 2 - 1; i >= 0; i--) {// 对前一半的节点(解释为“从最后一个非叶子节点开始,将每个父节点都调整为最小堆”更合理一些)
PercolateDown(num, i,size);// 进行下滤操作
PrintHeap("Build heap:",num,size);
}
}
// 对该数进行下滤操作,直到该数比左右节点都小就停止下滤
void PercolateDown(int num[] , int index,int size) {
int min;// 设置最小指向下标
while (index * 2 + 1<size) {// 如果该数有左节点,则假设左节点最小
min = index * 2 + 1;// 获取左节点的下标
if (index * 2 + 2<size) {// 如果该数还有右节点
if (num[min] > num[index * 2 + 2]) {// 就和左节点分出最小者
min = index * 2 + 2;// 此时右节点更小,则更新min的指向下标
}
}
// 此时进行该数和最小者进行比较,
if (num[index] < num[min]) {// 如果index最小,
break;// 停止下滤操作
} else {
Swap(num, index, min);// 交换两个数,让大数往下沉
index = min;// 更新index的指向
}
}// while
}
// 给定数组交换两个数的位置
void Swap(int num[] , int v, int u) {
int temp = num[v];
num[v] = num[u];
num[u] = temp;
}
void PrintHeap(const char* strMsg,int array[],int nLength)
{
int i;
printf("%s",strMsg);
for(i=0;i<nLength;i++)
{
printf("%d ",array[i]);
}
printf("\n");
}