堆数据结构用于排序算法中,空间复杂度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);
}
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] = ...{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();
}
... {
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();
}