堆排序

理论知识:《算法导论》第六章   堆排序

 

#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;
}


输入至少五个字符串和关键字,运行结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值