堆排序
2017-07-23 20:02
113 查看
http://blog.csdn.net/morewindows/article/details/6709644/#reply
参照这个博客写一个最大堆:
父节点与子节点的关系:
堆一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。
堆的增删操作:
堆的插入:
每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中。
i!=0不能省略的原因,举个例子:第一个插入的数是2(i=0),然后紧接着再插入3(i=1),看插入3这个过程:
i = 1 ; j = (1-1)/2 = 0 ; 满足while循环,中间不管,到了j = (i-1)/2这一步,i=0 -> j=(0-1)/2 = 0!!所以会出现死循环,这就是i的作用。
接着是堆建立:
堆排序:
#include <bits/stdc++.h>
using namespace std;
const int AX = 5e4+6;
int a[AX];
int n ;
void Fixdown( int i , int n ){
int j , tmp ;
tmp = a[i];
j = 2 * i + 1;
while( j < n ){
if( j + 1 < n && a[j+1] < a[j] ) j++;
if( a[j] >= tmp ) break;
a[i] = a[j];
i = j;
j = 2 * i + 1;
}
a[i] = tmp;
}
void DeleteNumber( int n ){
swap(a[0],a[n-1]);
Fixdown(0,n-1);
}
void Fixup( int i ){
int j , tmp;
tmp = a[i];
j = ( i - 1 ) / 2 ;
while( j >= 0 && i ){
if( a[j] <= tmp ) break;
a[i] = a[j];
i = j ;
j = ( i - 1 ) / 2;
}
a[i] = tmp;
}
void build_heap(int n){
for( int i = n / 2 ; i >= 0 ; i-- ){
Fixdown(i,n);
}
}
void add( int i , int val ){
a[i] = val;
Fixup(i);
}
void heapSort( int len ){
for( int i = len - 1 ; i ; i-- ){
swap(a[i],a[0]);
Fixdown(0,i);
}
}
int main(){
cin >> n;
for( int i = 0 ; i < n ; i++ ){
cin >> a[i];
}
DeleteNumber(n);
build_heap(n-1);
heapSort(n-1);
for( int i = n - 2 ; i >= 0 ; i-- ){
cout << a[i] << endl;
}
return 0 ;
}
参照这个博客写一个最大堆:
父节点与子节点的关系:
堆一般都用数组来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。
堆的增删操作:
堆的插入:
每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中。
void MaxHeapFixup(int a[],int i){ int j,temp; temp = a[i]; j = (i-1)/2; //父节点 往上 while(j >= 0 && i){ //这个i!=0在这种算法实现上不能省略,下面给出原因 if(a[j] >= temp) break; a[i] = a[j]; i = j; j = (i-1)/2; } a[i] = temp; } void MaxHeapAddNumber(int a[],int i,int val){ a[i] = val; MaxHeapFixup(a,i); }
i!=0不能省略的原因,举个例子:第一个插入的数是2(i=0),然后紧接着再插入3(i=1),看插入3这个过程:
i = 1 ; j = (1-1)/2 = 0 ; 满足while循环,中间不管,到了j = (i-1)/2这一步,i=0 -> j=(0-1)/2 = 0!!所以会出现死循环,这就是i的作用。
堆的删除
按定义,堆中每次都只能删除第0个数据。为了便于重建堆,实际的操作是将最后一个数据的值赋给根结点,然后再从根结点开始进行一次从上向下的调整。调整时先在左右儿子结点中找最小的,如果父结点比这个最小的子结点还小说明不需要调整了,反之将父结点和它交换后再考虑后面的结点。相当于从根结点将一个数据的“下沉”过程。void MaxHeapFixdown(int a[],int i,int length){ int j,temp; temp = a[i]; j = 2*i+1; //往下 while(j < length){ if( j+1 < length && a[j+1] > a[j]) j+=1; if(a[j] <= temp) break; a[i] = a[j]; i = j; j = 2*i + 1; } a[i] = temp; } void MaxHeapDeleteNumber(int a[],int length){ printf("%d\n",a[0]); swap(a[0],a[length-1]); //先把最后一个数据给根节点 MaxHeapFixdown(a,0,length-1); }
接着是堆建立:
void buildMaxHeap(int a[],int length){ for(int i = length/2-1;i >= 0;i--){ MaxHeapFixdown(a,i,length-1); } }
堆排序:
void HeapSort(int a[],int length){ for(int i=length-1;i >= 1;i--){ swap(a[i],a[0]); MaxHeapFixdown(a,0,i); } }
#include <bits/stdc++.h>
using namespace std;
const int AX = 5e4+6;
int a[AX];
int n ;
void Fixdown( int i , int n ){
int j , tmp ;
tmp = a[i];
j = 2 * i + 1;
while( j < n ){
if( j + 1 < n && a[j+1] < a[j] ) j++;
if( a[j] >= tmp ) break;
a[i] = a[j];
i = j;
j = 2 * i + 1;
}
a[i] = tmp;
}
void DeleteNumber( int n ){
swap(a[0],a[n-1]);
Fixdown(0,n-1);
}
void Fixup( int i ){
int j , tmp;
tmp = a[i];
j = ( i - 1 ) / 2 ;
while( j >= 0 && i ){
if( a[j] <= tmp ) break;
a[i] = a[j];
i = j ;
j = ( i - 1 ) / 2;
}
a[i] = tmp;
}
void build_heap(int n){
for( int i = n / 2 ; i >= 0 ; i-- ){
Fixdown(i,n);
}
}
void add( int i , int val ){
a[i] = val;
Fixup(i);
}
void heapSort( int len ){
for( int i = len - 1 ; i ; i-- ){
swap(a[i],a[0]);
Fixdown(0,i);
}
}
int main(){
cin >> n;
for( int i = 0 ; i < n ; i++ ){
cin >> a[i];
}
DeleteNumber(n);
build_heap(n-1);
heapSort(n-1);
for( int i = n - 2 ; i >= 0 ; i-- ){
cout << a[i] << endl;
}
return 0 ;
}
相关文章推荐
- 算法--堆排序
- Python 面试题 - 堆排序 & 演算过程
- 排序算法-堆排序
- 为什么从5000个数中找出10个最大的堆排序最快?
- 算法设计与分析基础-6.4、堆和堆排序
- 哈夫曼树结合堆排序 POJ(3253)
- 算法学习笔记----第二部分:排序和顺序统计量----第6章、堆排序
- 算法导论之插入排序,选择排序,归并排序,冒泡排序,希尔排序,堆排序,快速排序的c语言实现
- 堆排序 一个综合了插入排序和二路归并特点的排序算法(未测试)
- Heap-堆排序
- [字符串hash][堆排序][AC自动机][usaco3.1.5]Contact
- 堆排序
- 算法导论堆排序Java实现
- C++数据结构--堆排序
- C/C++排序之五(堆排序)
- 堆排序
- 图灵标准版堆排序
- 堆排序详解以及java实现
- 堆排序
- 堆排序