理论知识:《算法导论》第六章 堆排序
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class PriorityQueue
{
public:
PriorityQueue() { };
~PriorityQueue() { };
int getParent(int i) { return (i - 1) / 2; } // 数组下标由0开始与书中从1开始不同!
int getLeftChild(int i) { return i * 2 + 1; }//左孩子在数组中的下标值
int getRightChild(int i) { return i * 2 + 2; }
inline void addElem(string, int); // 由输入初始化队列
void swapTwoElem(int, int);
void iniHeapSize() { heapSize = elemQueue.size() - 1; }
void display();
void maxHeapify(int); // 使以参数为根的子树成为最大堆
void buildMaxHeap(); // 构建最大堆
void heapSort(); // 堆排序
// 优先级队列
const string getElemVal(int elemIndex) { return elemQueue[elemIndex]; }
const int getElemPriVal(int elemIndex) { return priQueue[elemIndex]; }
const string maximum() { return getElemVal(0); } // 返回具有最大优先级的元素
void extractMax(); // 去掉并返回具有最大优先级的元素
void increaseKey(int, int); // 提升优先级的值
void heapInsert(string, int); // 插入优先级为num的元素
void heapDelete(int); // 通过下标删除元素(练习6.5-7)
void heapDelete(string); // 通过元素值删除元素(练习6.5-7)
private:
vector<string> elemQueue; // 时间队列
vector<int> priQueue; // 事件优先级队列
vector<int>::size_type heapSize; // 堆中元素个数
};
void PriorityQueue::addElem(string elem, int key)
{
elemQueue.push_back(elem);
priQueue.push_back(key);
}
void PriorityQueue::swapTwoElem(int i, int j)
{
int temp1 = priQueue[i];
priQueue[i] = priQueue[j];
priQueue[j] = temp1;
string temp2 = elemQueue[i];
elemQueue[i] = elemQueue[j];
elemQueue[j] = temp2;
}
void PriorityQueue::display()
{
cout << "----------------------------------" << endl;
for (unsigned int i = 0; i <= heapSize; i++)
cout << getElemVal(i) << "\t";
cout << endl;
for (unsigned int i = 0; i <= heapSize; i++)
cout << getElemPriVal(i) << "\t";
cout << endl;
cout << "----------------------------------" << endl;
}
/*
保持堆的最大化
运行时间:O(lgn)
(练习6.2-5)使用循环取代了递归
*/
/***************循环**************
//void PriorityQueue::maxHeapify(int i)
//{
// int largest = i;
// int isHeapify = 0; // 设置是否处理完成的标志
// while (isHeapify == 0) {
// unsigned int l = getLeftChild(i);
// unsigned int r = getRightChild(i);
// if (l <= heapSize && priQueue[l] > priQueue[largest])
// largest = l;
// if (r <= heapSize && priQueue[r] > priQueue[largest])
// largest = r;
// if (largest != i) {
// swapTwoElem(i, largest);
// i = largest;
// } else
// isHeapify = 1; // largest等于i时处理完成
// }
//}
***********************************/
/***************递归*********************/
void PriorityQueue::maxHeapify(int i)
{
int largest = i;
unsigned int l = getLeftChild(i);
unsigned int r = getRightChild(i);
if (l <= heapSize && priQueue[l] > priQueue[largest])
largest = l;
if (r <= heapSize && priQueue[r] > priQueue[largest])
largest = r;
if (largest != i)
{
swapTwoElem(i, largest);
maxHeapify(largest);
}
}
void PriorityQueue::buildMaxHeap()
{
for (int i = heapSize / 2; i >= 0; i--) // 《算法导论》上的downto都是<= to是<
maxHeapify(i);
}
/*
对一个数组进行原地排序
运行时间:O(nlgn)
*/
void PriorityQueue::heapSort()
{
buildMaxHeap();
for (int i = heapSize; i >= 1; i--) {
swapTwoElem(0, i);
--heapSize;
maxHeapify(0);
}
}
void PriorityQueue::extractMax()
{
if (heapSize < 0)
throw "heap underflow";
cout << "被移除的元素是: "<< getElemVal(0) << " 优先级: " << getElemPriVal(0) << endl;
priQueue[0] = priQueue[heapSize];
elemQueue[0] = elemQueue[heapSize];
--heapSize;
maxHeapify(0);
}
void PriorityQueue::increaseKey(int elemIndex, int newKey)
{
if (newKey < priQueue[elemIndex])
throw "new key is smaller than current key";
priQueue[elemIndex] = newKey;
while (elemIndex > 0 && priQueue[getParent(elemIndex)] < priQueue[elemIndex]) {
swapTwoElem(elemIndex, getParent(elemIndex));
elemIndex = getParent(elemIndex);
}
}
void PriorityQueue::heapInsert(string elem, int key)
{
++heapSize;
priQueue[heapSize] = INT_MIN;
elemQueue[heapSize] = elem;
increaseKey(heapSize, key);
}
void PriorityQueue::heapDelete(int elemIndex)
{
elemQueue[elemIndex] = elemQueue[heapSize];
priQueue[elemIndex] = priQueue[heapSize];
--heapSize;
maxHeapify(elemIndex);
}
void PriorityQueue::heapDelete(string elem)
{
unsigned int elemIndex;
for (elemIndex = 0; elemIndex <= heapSize; elemIndex++)
if (elemQueue[elemIndex] == elem) {
break;
}
elemQueue[elemIndex] = elemQueue[heapSize];
priQueue[elemIndex] = priQueue[heapSize];
--heapSize;
maxHeapify(elemIndex);
}
int main()
{
PriorityQueue queue;
string elem;
int key;
while (cin >> elem >> key)
queue.addElem(elem, key);
// 堆排序演示
queue.iniHeapSize();
queue.heapSort();
queue.iniHeapSize(); // heapSort后heapSize将为0
cout << "堆排序:" << endl;
queue.display();
// 优先级队列演示
cout << "构建最大优先级队列:" << endl;
queue.buildMaxHeap();
queue.display();
cout << "返回最大优先级元素/移除元素/提升某元素优先级/插入新元素:" << endl;
cout <<"堆中优先级最高的元素是: " << queue.maximum() << "优先级: " << queue.getElemPriVal(0) << endl;
queue.extractMax();
queue.increaseKey(2, 99);
queue.heapInsert("shit", 999); // 插入优先级为num的元素str
queue.heapDelete("music");
queue.display();
system("pause");
return 0;
}
输入至少五个字符串和关键字,运行结果如下: