堆排序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)快速求取,最大,最小值。
堆排序:
(一)定义:
从小到大排序则构建一个最大堆;从大到小排序,则构建一个最小堆。
(二)思想:
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)快速求取,最大,最小值。
相关文章推荐
- 【数据结构】中的堆(HeapSort)排序
- 排序——堆排序(HeapSort)
- 八大排序算法之四选择排序—堆排序(Heap Sort)
- 堆积排序-堆排序-heap sort
- 堆排序(heapsort)
- 堆排序(Heap-Sort)
- 基本排序方法及分析(七):HeapSort 堆排序
- 09-排序3 Insertion or Heap Sort
- PHP实现排序堆排序(Heap Sort)算法
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 选择排序算法:堆排序-Heap Sort
- PAT - 甲级 - 1098. Insertion or Heap Sort (25)(排序)
- PAT--1098. Insertion or Heap Sort(排序)
- 堆排序 Heap Sort
- 排序之堆排序(Heap Sort)
- 浙大pat | 浙大pat 牛客网甲级 1098. Insertion or Heap Sort (25)判断是哪种排序方式
- 排序1+4:归并排序(MergeSort)和堆排序(HeapSort)
- 【排序】Heap Sort
- 堆排序(Heap Sort)的C语言实现
- 09-排序3 Insertion or Heap Sort