堆操作與堆排序

bigbigship發表於2014-09-11

堆:堆是一個完全二叉樹或者近似於一個完全二叉樹

最大堆:父節點的值大於等於左右節點的值;

最小堆:父節點的值小於等於左右節點的值

堆可以用一個陣列來儲存:第i個節點的根節點是(i-1)/2,左節點為i*2+1,右節點為i*2+3;

堆有兩種操作一種是插入,一種是刪除

插入的時候插入在最後 然後進行向上維護

刪除的時候需要將最後一個元素來替換這個元素的位置 然後向下維護;

刪除和插入的操作都是log(n)的複雜度

每次操作都進行維護了 所以從每一個值的父節點到根節點都是一個有序的序列

下面是將所有操作 和 堆排序封裝起來的一個程式碼:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

const int maxn = 100000;

struct Heap{
    int heap[maxn];
    int Sort_heap[maxn];
    int size=0,cnt;
    void shift_up(int t){//向上維護
        bool done = 0;
        if(t == 0) return ;
        while(t && !done){
            if(heap[t]>heap[(t-1)/2])
                swap(heap[t],heap[(t-1)/2]);
            else
                done = 1;
            t=(t-1)/2;//返回根節點
        }
    }
    void shift_down(int t){//向下維護
        bool done = 0;
        if(2 * t + 1 > size) return ;
        while(2 * t + 1 < size && !done){
            t= 2 * t + 1;//找到子節點
            if(t+1 < size && heap[t+1] > heap[t]) t++;
            if(heap[(t-1)/2]<heap[t])
                swap(heap[(t-1)/2],heap[t]);
            else
                done = 1;
        }
    }
    void Insert(int x){
        heap[size]=x;
        shift_up(size++);
    }
    void Delete(int t){
        int last = heap[size-1];
        size--;
        if(t == size) return ;
        heap[t] = last;
        shift_down(t);
    }
    void Sort(){
        cnt = size;
        for(int i = 0; i < cnt; i++){
            Sort_heap[i]=heap[0];
            Delete(0);
        }
    }
};

int main()
{
    Heap h;
    int x;
    while(~scanf("%d",&x) && x){
        h.Insert(x);
    }
    h.Sort();
    for(int i=0;i<h.cnt;i++)
        cout<<h.Sort_heap[i]<<" ";
    cout<<endl;
    return 0;
}
/****
5 4 3 1 2
***/


相關文章