c++数据结构-----选择排序(堆排序)

1、堆排序
改进着眼点:如何减少关键码之间的比较次数,查找最小值的同时,找出较小值
2、堆的定义
堆是具有下列性质的完全二叉树
(1)每个结点的值都小于或者等于其左右孩子结点的值(小根堆)
小根堆的根节点是所有结点的最小者
(2)每个结点的值都大于或者等于其左右孩子结点的值(大根堆)
大根堆的根结点是所有结点的最大者
较大结点靠近根节点,但不绝对
3、将堆用顺序存储结构存储,则堆对应一组序列
完全二叉树的基本性质:
对一棵具有n个结点的完全二叉树中从1开始层序编号
(1)结点i的双亲是i/2;
(2)结点i的左孩子是2i;
(3)结点i的右孩子是2i+1;
完全二叉树,顺序存储,编号从1开始
4.堆排序
基本思想:首先将待排序的记录序列构造成一个堆,此时选出堆中记录最大者,然后将这个最大者从堆中移走,将剩余的记录再调整成堆,找到次小的记录,依次类推,直到堆中只剩一个记录。
5.堆调整
在一个完全二叉树中,如果根结点的左右孩子均是堆,调整根节点,使整个完全二叉树成为一个堆
算法描述:

void sift(int r[],int k,int m)
{//要筛选的结点编号为k,堆中最后一个结点的编号为m
i=k;
j=2*i;
temp=r[i];//将筛选的记录暂存
while(j<=m)
{ if(j<m&&r[j]<r[j+1] j++;//左右还在取较大者
if(r[i]>r[j]) break;
else
{swap(r[i],r[j]);
i=j;
j=2i;
}
}
}

6.自己看图模拟堆调整算法

void sift(int r[],int k,int m)
{//待筛选的结点的编号k,最后一个结点的编号m
i=k;
j=2i;
temp=r[i];//筛选记录暂存
while(j<=m)//还没筛选到最后一个结点if((j<m&&r[j]<r[j+1]) j++;//左右孩子取最大的
  if(r[i]>r[j]) break;
  else
  {swap(r[i],r[j]);
  i=j;
  j=2i;
  }
  }
  }

7.如何将一个无需序列建成一个堆
分支结点(n/2)有(孩子的最大编号n) 对它进行内部调整
再锁定(n/2-1) 对它内部进行调整
以此类推。。。。

算法描述

for(i=n/2;i>=1;i--)
sift(r,i,n);
//最后一个结点(叶子)的序号是n,
//则最后一个分支结点(n/2)即为结点n的双亲;也即编号最大的分支结点开始逆序调整        

8、调整剩余记录,使其成为一个新堆
第i次调整剩余记录,此时,剩余记录n-i个,再调整根节点至第n-i个记录
算法描述:
sift(r,1,n-i);
堆排序的算法

void HeapSort(int r[] ,int n)
{
for(i=n/2;i=1;i--)//初建堆
sift(r,i,n);
for(i=1;i<n;i++)
{swap(r[i],r[n-i+1])//将堆顶元素移走,放置在依次是倒一个,倒二个····一直到根节点
 sift(r,1,n-i)//对剩余元素进行堆调整,重建堆
 }
 }

9.自己看图模拟堆排序的过程

void HeapSort(int r[],int n)
{  
for(i=n/2;i=1;i--)
sift(r,i,n);
for(i=1;i<n;i++)//只剩最后一个记录的时候,就要不用调整了,所以i<n
{
swap(r[1],r[n-i+1]);//移走堆顶
sift(r,1,n-i);//重建堆
}
}

10算法描述 堆调整和堆排序

//堆调整
void sift(int r[],int k,int m)
//k是待筛选的编号,m是最后一个编号
{i=k;
j=2*j;
temp=r[i];//未被筛选的记录暂存
while(j<=m)//还未筛选到叶子结点if(j<m&&r[j]<r[j+1] j++;//选取孩子最大的结点
if(r[i]<r[j]) break;
else
{
swap(r[i],r[j];
i=j;
j=2i;
}
}
}
//堆排序
void heapSort(int r[] ,int n)
{
for(i=n/2;i=1;i--)
sift(r,i,n);//小堆里面进行堆调整
for(i=1;i<n;i++)//大堆里面进行堆调整swap(r[1],r[n-i+1];//交换堆顶和该循环的最后一个元素,移走堆顶,倒1个,倒2个
sift(r,1,n-i);//重新建立堆
}

11.堆排序算法性能分析
第一个for循环初建堆,需要O(n)的时间
第二个for循环输出堆顶再重建堆,共需要取n-1次堆顶
第i次取堆顶记录重建堆需要O(log2 i)的时间,总共需要O(nlog2 n)时间
整个时间复杂度为O(nlog2 n),这是堆排序最好 最坏和平均的时间代价 。堆排序是不稳定的排序算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值