堆數據結構用於排序算法中,空間複雜度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():對最大堆進行排序,注意,排序後的數組不再是最大堆。
下面是具體的實現:
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 data[10] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};
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();
}