堆排序

最近看STL源码的时候,对堆排序算法的思想记不起来了,特此找了点资料觉得不错转载下,以备下次之用:选择排序算法,是选择最值,然后将其调整到合适位置。如何确定最值,则是选择排序算法的关键。 简单排序算法是通过比较,确定最值的位置。假设未排序元素个数为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] view plaincopy//调整节点 大根堆 template 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 void CreateHeap(T a[],int n) { int iFirst=(n-1)/2; //第一个非叶子节点 for (;iFirst>=0;iFirst--) { AdjustHeapNode(a,iFirst,n); } } //堆排序 template 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 堆的意义
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值