您的位置:首页 > 其它

堆排序heapSort_legend

2014-08-30 13:21 232 查看

堆排序:

(一)定义:

从小到大排序则构建一个最大堆;从大到小排序,则构建一个最小堆。

(二)思想:

1.先建立一个最大堆;

2.然后将最大堆的堆顶元素(0号元素,最大值)与堆的最后一个元素(n-1号元素)交换,这样最后一个元素(n-1号)就保存的是最大值了。然后堆的个数-1;调整堆siftDown,(是从0号到n-2号调整),这样就可以在堆顶获得第二大的元素。

3.重复2;

4.最终从n-1号元素到0号元素,存储的就是递减的顺序。

所以:

(1)递增排序,应该构建一个最大堆。

(2)递减排序,应该构造一个最小堆。

(三)优点,适用于:

(1)优点:

堆的优点在于最快的 找到最大,最小值。取走最大,最小值后重新构成堆,其时间复杂度为O(lgn),其他方法一般至少都需要O(n);

(2)适用于:

1.调度算法中,取最高优先级。

2.求取TopN问题或者第N大/小问题。

(四)步骤:

(1)建堆:

1.siftdown;

2.buildHeap:

(2)堆排序:

(五)代码实现:

/*

从start~end,只有start这个位置不满足最大堆,其余位置满足最大堆的定义。

所以从start到end开始调整。

*/

//注意:siftdown是将start处的值data[strat]保存下来为temp,然后将temp的值不断往下调整。所以每次都是孩子中较大的与temp的比较。

void siftDown(HeapType data[], int start ,int end ){

 int maxChild=start*2+1;//初始化孩子中较大的一个为左孩子。

 HeapType temp=data[start];//保留值,挖一个坑。

 for(;maxChild<=end;){

  if(maxChild+1<=end && data[maxChild]<data[maxChild+1] )

  maxChild++;//取左右孩子中较大的一个。

  if(data[maxChild]<temp) break;

  else {

   data[start]=data[maxChild];//将较大的孩子填充到父节点中。

   //较大的孩子节点有了一个坑

   start=maxChild;//更新父节点为儿子节点,继续向下比较。

maxChild=2*start+1;

  }

 }

 data[start]=temp;

}

/*

构建堆,从下到上的非叶子节点,每一个非叶子节点从上往上的siftDown调整。

n为节点个数,即数组长度。

*/

void buildHeap(HeapType data[], int n){

 int mid=(n-1)/2;

 for(;mid>=0;mid--){

  siftDown(data,mid,n-1);

 }

}

/*

堆排序:n为叶子个数,即数组的长度。

*/

void heapSort(HeapType data[], int n){

 buildHeap(data,n);//先构造一个堆、

 for(int i=n-1;i>=0;i--){

  HeapType temp=data[0];//交换堆顶(0号元素)与堆的最后一个元素。

  data[0]=data[i];

  data[i]=temp;

  sitfDown(data,0,i);//堆的大小i不断的减小

 }

}

(六)堆的应用:

(1)求取TopN问题或者第N大/小问题:

1.topN大(即:最大的N个数),则采用最小堆,且堆顶元素为第N大的元素;

2.topN小(即:最小的N个数),则采用最大堆,且堆顶元素为第N小的元素;

如:已知文件中有10000个数据,求取其中的最大的100个数据,现在的内存限制为100个数据。

思想:

1.前100个数,建立一个最小堆;

2.然后i 从个101~10000, 当前元素data[i]与堆顶比较,如果比堆顶大,则覆盖堆顶,然后siftDown调整。

3.重复2直至结束,则最小堆里则为最大的100个数,且堆顶为第100大的数。

(2)快速求取,最大,最小值。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  堆排序