堆排序原理
首先了解一下堆的性质
1.堆中某个节点的值总是不大于或不小于其父节点的值;
2.堆总是一棵完全二叉树。
构建一个堆,通过堆的性质来进行排序,堆是完全二叉树,所以满足在数组中存储,左孩子节点下标等于父节点下标*2,右孩子节点下标等于父节点下标*2+1
如果要从小到大排序,就用大顶堆,如果从大到小排序,就用小顶堆。
堆排序是从最后一个元素向前逐步完成排序的(类比插入排序,是从第一个元素向后完成排序的)
堆排序步骤
1.给出一个序列,构建堆
2.根据排序要求,初始化大顶堆或小顶堆
3.构建完毕后,此时堆的根节点就是最大(最小)的元素,将这个元素和堆末尾的元素交换,然后将除了最后一个节点的其他节点重新初始化。
4.重复步骤3,直到所有节点都完成排序
具体流程
构建堆不说了,以后有机会会写文章
如果已经构建完堆了,将根节点和堆末尾的交换,这样从根节点到末尾的前一个节点,除了根节点其他的节点都满足大顶堆(小顶堆)的概念,只需要从根节点遍历,选出它的孩子节点最大的与他本身交换,如果他本身比两个孩子节点都大,说明新的大顶堆(小顶堆)完成构建,继续重复步骤就行了
void heapSort(int l,int r){
int i=l; //当前节点
int j=i*2; //当前节点的左孩子
while(j<=r){
if(j+1<=r&&b[j]<b[j+1]) //找两个孩子哪个大
j++; //将j的下标选择大的哪个
if(b[i]<b[j]) //如果最大的孩子节点大于本身
swap(b[i],b[j]); //交换
else //如果本身大于两个孩子节点,说明堆构建完成
break;
i=j; //继续向下遍历
j=i*2;
}
}
时间复杂度:O(nlogn)