堆排序
2015-11-11 21:04
344 查看
堆排序是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
堆排序的平均时间复杂度为Ο(nlogn) 。
算法步骤:
1)创建一个堆H[0..n-1]
2)把堆首(最大值)和堆尾互换
3)把堆的尺寸缩小1,并调用shift_down(0),目的是把新的数组顶端数据调整到相应位置
4) 重复步骤2,直到堆的尺寸为1
简单排序算法是通过比较,确定最值的位置。假设未排序元素个数为N,则遍历一趟,需比较N-1次,再遍历下一趟时,需比较N-2次。但是,第二趟比较完全是独立的,没有利用第一次比较的信息。因为,第一趟比较时也没有把比较信息保留下来。
能不能找到一种方法,可以将本趟比较信息记录下来,以供下一趟求最值时使用,从而达到减少比较次数的目的。
一维数组,从直观上来看,是一种线性结构,这也是我们所熟知的。
但是,一维数组,还可以表达完全二叉树结构,这个确是不经常用到。
简单选择排序,是将一维数组看做线性结构,逐个比较。
但是,如果将其看做二叉树结构,有没有方法将其比较次数降低呢,于是便有了堆排序算法。
堆排序正是利用一维数组可表示完全二叉树,从而借助完全二叉树的性质来保存比较信息。从而达到减少比较次数的算法。
(1) ki≤K2i且ki≤K2i+1或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ )
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
plaincopy
//调整节点 大根堆
template<class T>
void AdjustHeapNode(T a[],int i,int n){ //调整节点i,数组共有N个节点
if (n==1||i>(n-2)/2) //i为叶子节点 (n-2)/2 最后一个非叶子节点的位置
return;
int iLeft=2*i+1;
int iRight=2*i+2;
if (iRight<=n-1) //说明i有左右两个子节点 三个节点找最大值
{
if (a[i]>=a[iLeft]&&a[i]>=a[iRight]) // i 最大 不用调整
return;
if (a[i]<a[iLeft]&&a[iRight]<=a[iLeft]) // iLeft 最大
{
T temp=a[iLeft];
a[iLeft]=a[i];
a[i]=temp;
AdjustHeapNode(a,iLeft,n);
return;
}
if (a[i]<a[iRight]&&a[iLeft]<=a[iRight]) // iRight 最大
{
T temp=a[iRight];
a[iRight]=a[i];
a[i]=temp;
AdjustHeapNode(a,iRight,n);
return;
}
}else{ // 说明i只有左节点 二个节点找最大值
//iLeft为最后一个节点
if (a[i]>=a[iLeft])
return;
else
{
T temp=a[iLeft];
a[iLeft]=a[i];
a[i]=temp;
AdjustHeapNode(a,iLeft,n);
return;
}
}
}
//建立堆
template<class T>
void CreateHeap(T a[],int n)
{
int iFirst=(n-1)/2; //第一个非叶子节点
for (;iFirst>=0;iFirst--)
{
AdjustHeapNode(a,iFirst,n);
}
}
//堆排序
template<class T>
void HeapSort(T a[],int n)
{
CreateHeap(a,n);
T temp;
for (int i=0;i<n-1;i++)
{
temp=a[n-1-i];
a[n-1-i]=a[0];
a[0]=temp;
AdjustHeapNode(a,0,n-1-i);
}
}
堆排序的平均时间复杂度为Ο(nlogn) 。
算法步骤:
1)创建一个堆H[0..n-1]
2)把堆首(最大值)和堆尾互换
3)把堆的尺寸缩小1,并调用shift_down(0),目的是把新的数组顶端数据调整到相应位置
4) 重复步骤2,直到堆的尺寸为1
简单排序算法是通过比较,确定最值的位置。假设未排序元素个数为N,则遍历一趟,需比较N-1次,再遍历下一趟时,需比较N-2次。但是,第二趟比较完全是独立的,没有利用第一次比较的信息。因为,第一趟比较时也没有把比较信息保留下来。
能不能找到一种方法,可以将本趟比较信息记录下来,以供下一趟求最值时使用,从而达到减少比较次数的目的。
一维数组,从直观上来看,是一种线性结构,这也是我们所熟知的。
但是,一维数组,还可以表达完全二叉树结构,这个确是不经常用到。
简单选择排序,是将一维数组看做线性结构,逐个比较。
但是,如果将其看做二叉树结构,有没有方法将其比较次数降低呢,于是便有了堆排序算法。
堆排序正是利用一维数组可表示完全二叉树,从而借助完全二叉树的性质来保存比较信息。从而达到减少比较次数的算法。
1.1定义
n个关键字序列Kl,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):(1) ki≤K2i且ki≤K2i+1或(2)Ki≥K2i且ki≥K2i+1(1≤i≤ )
若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构,则堆实质上是满足如下性质的完全二叉树:树中任一非叶结点的关键字均不大于(或不小于)其左右孩子(若存在)结点的关键字。
1.2建堆方法
1.3建堆时间复杂度
1.4建堆算法
[cpp] viewplaincopy
//调整节点 大根堆
template<class T>
void AdjustHeapNode(T a[],int i,int n){ //调整节点i,数组共有N个节点
if (n==1||i>(n-2)/2) //i为叶子节点 (n-2)/2 最后一个非叶子节点的位置
return;
int iLeft=2*i+1;
int iRight=2*i+2;
if (iRight<=n-1) //说明i有左右两个子节点 三个节点找最大值
{
if (a[i]>=a[iLeft]&&a[i]>=a[iRight]) // i 最大 不用调整
return;
if (a[i]<a[iLeft]&&a[iRight]<=a[iLeft]) // iLeft 最大
{
T temp=a[iLeft];
a[iLeft]=a[i];
a[i]=temp;
AdjustHeapNode(a,iLeft,n);
return;
}
if (a[i]<a[iRight]&&a[iLeft]<=a[iRight]) // iRight 最大
{
T temp=a[iRight];
a[iRight]=a[i];
a[i]=temp;
AdjustHeapNode(a,iRight,n);
return;
}
}else{ // 说明i只有左节点 二个节点找最大值
//iLeft为最后一个节点
if (a[i]>=a[iLeft])
return;
else
{
T temp=a[iLeft];
a[iLeft]=a[i];
a[i]=temp;
AdjustHeapNode(a,iLeft,n);
return;
}
}
}
//建立堆
template<class T>
void CreateHeap(T a[],int n)
{
int iFirst=(n-1)/2; //第一个非叶子节点
for (;iFirst>=0;iFirst--)
{
AdjustHeapNode(a,iFirst,n);
}
}
//堆排序
template<class T>
void HeapSort(T a[],int n)
{
CreateHeap(a,n);
T temp;
for (int i=0;i<n-1;i++)
{
temp=a[n-1-i];
a[n-1-i]=a[0];
a[0]=temp;
AdjustHeapNode(a,0,n-1-i);
}
}
1.5堆插入
1.6 删除堆顶后调整
1.7 堆的意义
相关文章推荐
- ubuntu下,批量更改文件后缀
- UITableViewEdit
- mac中使用redis cluster 配置出现的问题
- 1.0.2 eclipse中Ctrl点击某个类提示Class File Editor Source not foun
- 计算1~10阶乘然后累加
- ubuntu,forever自动启动node.js
- httpclient笔记(一)
- CentOS下的C连接MySQL数据库
- Linux安装软件包过慢怎么办?
- leetcode题后感-01
- sqlserver2008r2实现镜像
- OC-Q&A
- nyoj 236 心急的c小加【贪心】
- sqlserver2008r2实现镜像
- ASP.NET MVC - Display UTC time from server as local time on client side
- 移动端学习笔记
- 1.0.1 javadoc生成文档时总是报错java.lang.IllegalArgumentException解决方法
- 昂贵的聘礼(条件Dij)
- hdoj4990Reading comprehension【矩阵快速幂】
- zabbix 添加对网卡流量超出阈值的监控