在学习堆排序前要先知道什么是堆
百度百科上给出的定义:堆(Heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵完全二叉树的数组对象。
实际上就是将完全二叉树按行线性化存入数组中,所以呈现出的规律就是,每一个父节点下标x[i]对应的左孩子下标为x[i*2+1],右孩子下标为x[i*2+2]
基于数组实现堆的基础上对堆进行大顶堆变换或者小顶堆变换,即让每个父节点都大于两个孩子结点(大顶堆)或者小于两个孩子结点(小顶堆),根据树的特性【根为最开始的父节点】所以根结点就会变成最大的或者最小的,因此得到以下操作
1.对数组1~n进行大顶堆或者小顶堆变换,让所有结点都满足a[i]>a[i*2+1]&&a[i]>a[i*2+2]
这里i*2+1是左孩子下标,i*2+2是右孩子下标(堆定义的下标规律)
2.将根节点a[1]和数组末尾a[n]交换,继续对1~n-1进行堆变换,使其满足上述条件
int a[10]={1,9,8,7,6,5,4,3,2,10};
void createMaxHeap(int n){
for(int i=n;i>=0;i--){
int lChild=2*i+1,rChild=lChild+1;
if(lChild<=n&&a[lChild]>a[i]){
swap(a[lChild],a[i]);
int llChild=lChild*2+1,rrChild=llChild+1;
if(llChild<n&&a[llChild]>a[lChild])createMaxHeap(n);
if(rrChild<n&&a[rrChild]>a[lChild])createMaxHeap(n);
}
if(rChild<=n&&a[rChild]>a[i]){
swap(a[rChild],a[i]);
int llChild=rChild*2+1,rrChild=llChild+1;
if(llChild<n&&a[llChild]>a[rChild])createMaxHeap(n);
if(rrChild<n&&a[rrChild]>a[rChild])createMaxHeap(n);
}
}
}
void heapSort(){
for(int i=9;i>=0;i--){
createMaxHeap(i);
swap(a[i],a[0]);
}
}
这里存在的一个问题是,左孩子和父结点交换后可能使交换后的左孩子 堆结构混乱(也就是不满足父节点大于两个孩子结点)所以交换后要对左孩子和右孩子的堆结构进行判断。