堆排序
来源:互联网 发布:洛奇英雄传mac 编辑:程序博客网 时间:2024/06/02 01:17
假设有序列:K1,K2,...Kn
1、如果满足:Ki>=K2i且Ki>=K2i+1,则称这个序列为大根堆。
2、如果满足:Ki<=K2i且Ki<=K2i+1,则称这个序列为小根堆。
大根堆排序的大致流程如下:
整个过程在数组中进行操作,交换堆顶元素和最后一个元素就是交换数组中的第一个元素与最后一个元素。
假设有数组a[0]a[1]a[2]…a[n-1](大根堆),交换后成为a[n-1]a[1]a[2]…a[0]。从而形成新序列a[n-1]a[1]a[2]…a[n-2],对这个新序列再进行调整、交换。
一共会产生n-1个新序列。
最外层循环:
for(j=n-1;j>0;j--){};
注:去掉的部分为有序元素,不参与后面的排序。实际上在排序过程中原数组的长度是不变的。
j=0:
j=1:
j=2:
...
j=8:
数组中的元素看成是完全二叉树。
大根堆调整: HeapAdjust(int low,int high)
假设有以下数据:
写成完全二叉树如下:
先将这个完全二叉树的局部(根节点、左子树、右子树)调整成大根堆:
锁定要排序的元素,会有2种情况:(i为对应数组的下标)
上面的完全二叉树属于第1种情况,
共9个数,a[0]~a[8]。
low=0,high=8.
i分别取:8,6,4,2
再假设共10个数,a[0]~a[9],此时属于第2种情况,
low=0,high=9
i分别取:9,8,6,4,2
怎么区分这两种情况?
if(i%2==0)//第一种情况
if(i%2==1)//第二种情况
调整成大根堆:
if(i%2==0)
{
for(i=high;i>=2;i-=2)
{
if(a[(i-2)/2]<a[i-1])
{
temp=a[i-1];
a[i-1]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
if(a[(i-2)/2])<a[i])
{
temp=a[i];
a[i]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
}
}
if(i%2==1)
{
if(a[(high-1)/2]<a[high])
{
temp=a[high];
a[high]=a[(high-1)/2];
a[(high-1)/2]=temp;
}
for(i=high-1;i>=2;i-=2)
{
if(a[(i-2)/2]<a[i-1])
{
temp=a[i-1];
a[i-1]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
if(a[(i-2)/2])<a[i])
{
temp=a[i];
a[i]=a[(i-2)/2];
a[(i-2)/2]=temp;
}
}
}
交换大根堆中的堆顶元素和最后一个元素:
temp=a[0];
a[0]=a[j];
a[j]=temp;
最后套上最外层循环。- 堆及堆排序
- 堆/堆排序特点
- 【二叉堆、堆排序】
- 二叉堆 & 堆排序
- 二叉堆 & 堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆与堆排序
- 堆和堆排序
- 堆排序(最大堆)
- 堆和堆排序
- 堆和堆排序
- 堆及堆排序
- 堆和堆排序
- 堆与堆排序
- (ssm流程图详解)Spring+SpringMVC+Mybatis整合开发实践
- 接口与虚函数的区别
- 借用栈实现单链表逆向倒序输出
- CSU-1110 RMQ with Shifts (单点更新+区间最小值 zkw线段树)
- 初次接触bash脚本文件
- 堆排序
- XYNUOJ 问题 B: 敌兵布阵
- OC:希尔排序的理解
- 机器学习Chapter-1(线性模型)
- 143_IO_File_路径常量_绝对与相对路径_构建对象
- Android Input系统InputManagerService简介
- linux压缩解压命令
- linux系统编程之记录锁
- 金明的预算budget题解