最大堆及堆排序的實現

 堆數據結構用於排序算法中,空間複雜度O(1),時間複雜度O(NlogN),但是在實踐中還是不如快速排序(好像快速排序可以更好的利用硬件特性)。堆的意義就在於:最快的找到最大/最小值,在堆結構中插入一個值重新構造堆結構,取走最大/最下值後重新構造堆結構 其時間複雜度爲O(logN),而其他方法最少爲O(N).堆實踐中用途不在於排序,其主要用在調度算法中,比如優先級調度,每次取優先級最高的,時間驅動,取時間最小/等待最長的 等等 ,分爲最大堆/最小堆。

這裏討論最大堆,最小堆與最大堆類似。

void MaxHeapify(int i):移動一個指定的元素使其符合最大堆。

void BuildMaxHeap():對已知的數組元素構造最大堆。通過調用MaxHeapify來實現。

T Maximum():返回最大值。

T ExtractMaximum():提取最大值,堆中元素少一,提取後還是一個最大堆。

void IncreaseKey(int i, T key):對指定位置的元素進行增大操作,操作後仍爲最大堆。

void HeapInsert(T key):在最大堆中執行插入操作,先在數組最後邊添加一個無窮小元素,然後調用IncreaseKey來實現。

void HeapSort():對最大堆進行排序,注意,排序後的數組不再是最大堆。

下面是具體的實現:

template <typename T>
class MaxHeap
{
public:
    MaxHeap(
int max_size, int cur_size, T data[]) : cur_size_(cur_size), max_size_(max_size)
    
{
        
if (max_size_ < cur_size_)
            
throw logic_error("Maximum size must no more less then the current size!");

        heap_ 
= new T[max_size_ + 1];
        copy(data, data 
+ cur_size_, heap_ + 1);
    }

    
~MaxHeap() 
    
{
        delete []heap_;
    }

    
void MaxHeapify(int i)
    
{
        
int l = left(i);
        
int r = right(i);
        
int largest = i;

        
if (l <= cur_size_ && heap_[l] > heap_[largest])
            largest 
= l;

        
if (r <= cur_size_ && heap_[r] > heap_[largest])
            largest 
= r;

        
if (largest != i)
        
{
            swap(heap_[largest], heap_[i]);
            MaxHeapify(largest);
        }

    }

    
void BuildMaxHeap()
    
{
        
for (int i = cur_size_ / 2; i >= 1; i--)
        
{
            MaxHeapify(i);
        }

    }

    T Maximum()
    
{
        
return heap_[1];
    }

    T ExtractMaximum()
    
{
        
if (cur_size_ <= 1)
            
throw logic_error("No element in max heap!");

        T max 
= heap_[1];
        heap_[
1= heap_[cur_size_];
        cur_size_
--;
        MaxHeapify(
1);

        
return max;
    }

    
void IncreaseKey(int i, T key)
    
{
        
if (key < heap_[i])
            
throw logic_error("the new key is smaller than current key!");

        heap_[i] 
= key;
        
while (i > 1 && heap_[parent(i)] < heap_[i])
        
{
            swap(heap_[parent(i)], heap_[i]);
            i 
= parent(i);
        }

    }

    
void HeapInsert(T key)
    
{
        
if (max_size_ <= cur_size_)
            
throw logic_error("The heap is out of size, can't insert!");

        cur_size_
++;
        heap_[cur_size_] 
= T(-0xFFFF);
        IncreaseKey(cur_size_, key);
    }
    
    
void HeapSort()
    
{
        
int tmp_size = cur_size_;
        
for (int i = tmp_size; i > 1; i--)
        
{
            swap(heap_[
1], heap_[i]); 
            cur_size_
--;
            MaxHeapify(
1);
        }

        
// restore the size
        cur_size_ = tmp_size;
    }

    ostream
& print(ostream& out
    
{
        copy(heap_ 
+ 1, heap_ + cur_size_ + 1, ostream_iterator<T>(out" ")); 
        
return out
    }
    

private:
    
int parent(int i) return i / 2; }
    
int left(int i)   return i * 2; }
    
int right(int i)  return i * 2 + 1; }

private:
    
int cur_size_;
    
int max_size_;
    T
* heap_;
}
;

template 
<typename T>
ostream
& operator <<(ostream& out, MaxHeap<T>& mh)
{
    
return mh.print(out);
}

下面是測試代碼:

int main()
{
    
int data[10= {4132169101487};
    
int count = sizeof(data) / sizeof(int);

    MaxHeap
<int> mh(2 * count, count, data);
    cout 
<< "Before build: " << mh << endl;

    mh.BuildMaxHeap();
    cout 
<< "After build: " << mh << endl;

    mh.HeapSort();
    cout 
<< "After sort: " << mh << endl;

    
return getchar();
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章