欢迎大家来到IT世界,在知识的湖畔探索吧!
堆排序松木
优先队列,优先级,处理动态的情况。例如:100万元素,选出前100名。(N个元素,前M个),时间复杂度NlogM。完全二叉树结构。
构建堆:
template<typename Item>
class MaxHeap{
private:
Item *data;
int count;
public:
MaxHeap(int capacity){
data = new Item[capacity+1]; //注意堆中[0]位置不放元素,从1开始存,所以数组大小要+1。
count = 0;
}
~MaxHeap(){
delete[] data;
}
int size(){
return count;
}
bool isEmpty(){
return count == 0;
}
};
欢迎大家来到IT世界,在知识的湖畔探索吧!
最大(最小)堆情况:
向上移动和插入节点:
欢迎大家来到IT世界,在知识的湖畔探索吧! void shiftUp(int k){
while( k > 1 && data[k/2] < data[k] ){
swap( data[k/2], data[k] );
k /= 2;
}
}
void insert(Item item){
assert( count + 1 <= capacity );
data[count+1] = item;
count ++;
shiftUp(count);
}
向下移动和减少节点:
注意只能减少第一个节点,然后将最后一个节点放入第一个节点(为了保持完全二叉树),然后调整根节点和其他节点的位置。
void shiftDown(int k){
while( 2*k <= count ){
int j = 2*k; // 在此轮循环中,data[k]和data[j]交换位置
if( j+1 <= count && data[j+1] > data[j] )
j ++;
// data[j] 是 data[2*k]和data[2*k+1]中的最大值
if( data[k] >= data[j] ) break;
swap( data[k] , data[j] );
k = j;
}
}
Item extractMax(){
assert( count > 0 );
Item ret = data[1];
swap( data[1] , data[count] );
count --;
shiftDown(1);
return ret;
}
简单堆排序:
(针对最大最小堆)每次取得都是顶端最值,所以只要不断取出即可排序。
欢迎大家来到IT世界,在知识的湖畔探索吧! while( !maxheap.isEmpty() ) cout<<maxheap.extractMax()<<" "; cout<<endl;
堆排序:首先解决如何构建最大(最小)堆。
template<typename T>
void heapSort1(T arr[], int n){
MaxHeap<T> maxheap = MaxHeap<T>(n);
for( int i = 0 ; i < n ; i ++ )
maxheap.insert(arr[i]); //对数组每个元素都进行一遍插入操作
for( int i = n-1 ; i >= 0 ; i-- )
arr[i] = maxheap.extractMax();
}
堆排序改进:
其实对于完全二叉树,只需要交换根节点和叶子节点即可,而最大的一个根节点是n/2,在构建最大(最小)堆的时候,只需要对根节点往下交换即可。
//构建堆
MaxHeap(Item arr[], int n){
data = new Item[n+1];
capacity = n;
for( int i = 0 ; i < n ; i ++ )
data[i+1] = arr[i];
count = n;
for( int i = count/2 ; i >= 1 ; i -- )
shiftDown(i);
}
//排序
template<typename T>
void heapSort2(T arr[], int n){
MaxHeap<T> maxheap = MaxHeap<T>(arr,n);
for( int i = n-1 ; i >= 0 ; i-- )
arr[i] = maxheap.extractMax();
}
原地堆排序:
之前的排序都是先构造树,有没有可能原地排序(利用数组)?
思路:对数组第一位进行下移操作,然后和数组尾部进行交换。
需要注意:数组中从0开始计算,所以叶子节点为i*c+1和i*c+2,父节点为(i-1)/2。微修改下移函数。
template<typename T>
void __shiftDown(T arr[], int n, int k){
while( 2*k+1 < n ){
int j = 2*k+1;
if( j+1 < n && arr[j+1] > arr[j] )
j += 1;
if( arr[k] >= arr[j] )break;
swap( arr[k] , arr[j] );
k = j;
}
}
template<typename T>
void heapSort(T arr[], int n){
for( int i = (n-1)/2 ; i >= 0 ; i -- )
__shiftDown(arr, n, i);//数组中先构建最大(小)树
for( int i = n-1; i > 0 ; i-- ){
swap( arr[0] , arr[i] );
__shiftDown(arr, i, 0); //对[0]节点进行处理即可。
}
}
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/37172.html