- 前言
虽然挺简单的,但还是决定记录一下,方便自己以后复习吧...
- 思路
1.待排序n个元素,看成一个完全二叉树,从倒数第一个具有子树的节点(n/2-1)开始,从右到左从下到上,保证每个子树的父节点都比左右子树的值大,一路交换上去最后保证根节点是最大值,将根节点与最后一个元素n交换;这样就得到了最后一个元素为该数组的最大值;
2.除去最后一个元素,将(n-1)个元素重复上述操作,直到元素个数为1个
结合图片理解:
a、假设无序序列如下图所示。
b、从倒数第一个有子树的节点开始(n/2-1)=1,即节点6,比较[6,5,9],9与6交换。
c、下一个节点4,比较[4,9,8],9与4交换
这样第一次堆调整就完成了,得到的根节点一定是该序列的最大值,将根节点与最后一个节点调换,那么就把最大值放到了数列最后面,再对前面0到n-1的数列进行上述的堆调整,即(下标0到3),直到待调整元素剩下一个时就完成了从小到大的排序
-代码实现
void adjustHeap(int arr[], int i, int len)
{
int temp = arr[i]; //先记录当前父节点
int k = 2 * i + 1; //待交换位置为左子节点
if (k + 1 < len) //如果有右子节点
{
if (arr[k] < arr[k + 1])//如果右子节点大于左子节点
{
k++; //待交换位置变为右子节点
}
}
if (arr[k] > arr[i]) //如果子节点比父节点大,交换
{
arr[i] = arr[k];
arr[k] = temp;
}
}
void heapsort(int arr[], int len)
{
for (int j_len = len; j_len > 0; j_len--)//进行堆调整的元素长度
{
for (int i = j_len / 2 - 1; i >= 0; i--)//从倒数第一个有孩子的节点开始
{
adjustHeap(arr, i, j_len);
}
//完成调整,将根节点(最大值)与参加调整的最后一个元素进行交换
int temp = arr[0];
arr[0] = arr[j_len - 1];
arr[j_len - 1] = temp;
}
}
//测试代码
int main()
{
int arr[] = {2,6,7,1,9};
heapsort(arr,5);
for(int i = 0;i<5;i++)
cout<<arr[i]<<" ";
return 0;
}
输出结果为:1 2 6 7 9
平均时间复杂度为nlog(n)