其他分享
首页 > 其他分享> > 堆排序 Heap Sort

堆排序 Heap Sort

作者:互联网

堆和优先队列 Heap and priority Queue

❓什么是优先队列?
普通队列:先进先出,后进后出
优先队列:出队顺序和入队顺序无关,和优先级相关
❓为什么使用优先队列?
在1,000,000个元素中选出前100名?
抽象:在N个元素中选出前M个元素
排序?NlogN
使用优先队列?NlongM
❓优先队列主要操作?
入队
出队:取出优先级最高的元素
❓优先队列的实现?
在这里插入图片描述
【注】使用堆实现优先队列对于总共有N个请求:
使用普通数组或者顺序数组,最差情况:O(N2)
使用堆:O(nlgn)

堆的基本存储

在这里插入图片描述
【特点】
(1)堆中某个节点的值总是不大于其父节点的值
(2)堆总是一棵完全二叉树(最大堆)
【注】所谓完全二叉树就是,这是一棵二叉树,对于这个二叉树,除了最后一层节点之外,其他每层节点个数必须是最大值,在最后一层虽然节点个数不是最大值,但是必须都位于最左侧,如下图所示。
在这里插入图片描述
在这里插入图片描述
【代码】

#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cmath>
#include <cassert>
using namespace std;

template <typename Item>
class MaxHeap {
private:
    Item* data;
    int count;
public:
    MaxHeap(int capacity) {
        data = new Item[capacity + 1];
        count = 0;
    }
    ~MaxHeap() {
        delete [] data;
    }
    //堆里有多少元素
    int size() {
        return count;
    }
    //判断堆是否为空
    bool isEmpty() {
        return count == 0;
    }
};

int main() {
    MaxHeap<int> maxheap = MaxHeap<int>(100);
    cout << maxheap.size() << endl;
    return 0;
}

Shift up

在这里插入图片描述
添加一个元素相当于在数组的末尾添加一个元素(52),相应的堆如下图所示,此时是不满足最大堆的定义的,因为52比其父节点16还要大,违背了定义,所以接下来要进行一系列的操作维护堆的定义。
在这里插入图片描述
首先,52和16节点交换位置。
在这里插入图片描述
同理,52和41节点也需要交换位置。
在这里插入图片描述
最终52上升到了满足最大堆定义的位置,这个过程叫做Shift up过程。
在这里插入图片描述
【代码实现】

#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cmath>
#include <cassert>
using namespace std;

template <typename Item>
class MaxHeap {
private:
    Item* data;
    int count;
    int capacity;
    void shiftUp(int k) {
        while(k > 1 && data[k/2] < data[k]) {
            swap(data[k/2], data[k]);
            k /= 2;
        }
    }
public:
    MaxHeap(int capacity) {
        data = new Item[capacity + 1];
        count = 0;
        this->capacity = capacity;
    }
    ~MaxHeap() {
        delete [] data;
    }
    //堆里有多少元素
    int size() {
        return count;
    }
    //判断堆是否为空
    bool isEmpty() {
        return count == 0;
    }
    //向堆中插入一个元素
    void insert(Item item) {
        assert(count + 1 <= capacity);
        data[count+1] = item;
        count++;
        shiftUp(count);
    }
};

int main() {
    MaxHeap<int> maxheap = MaxHeap<int>(100);
    cout << maxheap.size() << endl;
    //随机添加15个元素,打印出来会发现这个树满足最大堆的性质
    srand(time(NULL));
    for(int i = 0; i < 15; i++)
        maxheap.insert(rand()%100);
    return 0;
}

Shift down

对于堆来说,只能取出根节点的那个元素,即最大堆只能取出优先级最高的那个元素。
在这里插入图片描述
为了维持最大堆的性质,把最后一个元素移动到根节点的位置,相应的记录堆元素个数的count的值要减1,此时满足完全二叉树的性质,但不是最大堆,需要进行Shift Down操作。
在这里插入图片描述
首先,16要和52或30交换位置,因为52大于30,所以和52交换位置。
在这里插入图片描述
在这里插入图片描述
同理,继续上面的操作,直到满足最大堆性质。
在这里插入图片描述
【代码实现】

#include <iostream>
#include <algorithm>
#include <string>
#include <ctime>
#include <cmath>
#include <cassert>
using namespace std;

template <typename Item>
class MaxHeap {
private:
    Item* data;
    int count;
    int capacity;
    void shiftUp(int k) {
        while(k > 1 && data[k/2] < data[k]) {
            swap(data[k/2], data[k]);
            k /= 2;
        }
    }
    void shiftDown(int k) {
        while(2 * k <= count) {
            int j = 2 * k;
            if(j + 1 <= count && data[j + 1] > data[j])
                j += 1;
            if(data[k] >= data[j])
                break;
            swap(data[k], data[j]);
            k = j;
        }
    }
public:
    MaxHeap(int capacity) {
        data = new Item[capacity + 1];
        count = 0;
        this->capacity = capacity;
    }
    ~MaxHeap() {
        delete [] data;
    }
    //堆里有多少元素
    int size() {
        return count;
    }
    //判断堆是否为空
    bool isEmpty() {
        return count == 0;
    }
    //向堆中插入一个元素
    void insert(Item item) {
        assert(count + 1 <= capacity);
        data[count+1] = item;
        count++;
        shiftUp(count);
    }
    //从堆中删除一个元素
    Item extractMax() {
        assert(count > 0);
        Item ret = data[1];
        swap(data[1], data[count]);
        count--;
        shiftDown(1);
        return ret;
    }
};

int main() {
    MaxHeap<int> maxheap = MaxHeap<int>(100);
    cout << maxheap.size() << endl;
    //随机添加15个元素,打印出来会发现这个树满足最大堆的性质
    srand(time(NULL));
    for(int i = 0; i < 15; i++)
        maxheap.insert(rand()%100);
    while(!maxheap.isEmpty()) {
        cout << maxheap.extractMax() << " ";
    }
    cout << endl;
    return 0;
}

标签:Sort,count,capacity,int,MaxHeap,堆排序,Heap,include,data
来源: https://blog.csdn.net/weixin_41462017/article/details/104789575