数据结构之堆和priority_queue

一、堆的定义

堆是一棵有着特殊性质的完全二叉树,可以用优先级队列(priority queue)实现

堆的性质:

1.是一棵完全二叉树

2.树的每个结点,如果存在子树,那么该结点的权值大于等于(或小于等于)子树中所有的结点的权值

如果根节点大于等于子树结点的权值,称为大根堆;反之,称为小根堆

二、堆的存储

由于堆是一个完全二叉树,因此可以用一个数组来存储

const int N = 1e5 + 10;
int n; // 标记堆的大小
int heap[N]; // 存堆(默认大根堆)

三、堆的核心操作

1.向上调整算法

void up(int child) // 向上调整算法(孩子向上走,比父亲大就交换)
{
    int parent = child / 2;

    while(parent >= 1 && heap[child] > heap[parent])
    {
        swap(heap[child], heap[parent]);
        // 先变形参
        child = parent;
        parent = child / 2;
    }
}

2.向下调整算法

void down(int parent) // 向下调整算法(父亲向下走,与大孩子小就交换)
{
    int child = parent * 2;

    while(child <= n)
    {
        if(child + 1 <= n && heap[child + 1] > heap[child]) child++;
        if(heap[child] <= heap[parent]) return;
        swap(heap[child], heap[parent]);
        parent = child;
        child = parent * 2;
    }
}

四、堆的模拟实现

1.堆的创建

const int N = 1e6 + 10;
int n; // 标记堆的大小
int heap[N]; // 存堆(大根堆)

2.插入

// 插入(把新来的元素放在最后一个位置,执行一次向上调整算法)
void push(int x)
{
    heap[++n] = x;
    up(n);
}

3.删除栈顶元素

void pop()
{
    swap(heap[1], heap[n]);
    n--;
    down(1);
}

4.堆顶元素

下标为1位置的元素就是堆顶元素

int top()
{
    return heap[1];
}

5.堆的大小

int size()
{
    return n;
}

五、priority_queue

1.创建priority_queue初级

#include 
#include 
#include  // 优先级队列在头文件queue中

using namespace std;

void test1()
{
    int a[10] = {1, 41, 23, 10, 11, 2, -1, 99, 14, 0};
    priority_queue heap; // 默认是大根堆
    for(auto x : a)
    {
        heap.push(x); // 插入元素
    }
    while(heap.size())
    {
        cout << heap.top() << " "; // 获取堆顶元素
        heap.pop(); // 删除元素
    }
}
int main()
{
    test();
    return 0;
}

2.创建priority_queue进阶

结构体类型

#include 
#include 
#include 

using namespace std;

struct node
{
    int a, b, c;
    // //以 b 为基准,定义大根堆
    // bool operator < (const node& x) const
    // {
    //     return b < x.b;
    // }
    // 以 b 为基础,定义小根堆
    bool operator < (const node& x) const
    {
        return b > x.b;
    }
};
void test()
{
    priority_queue heap;
    for(int i = 1; i <= 10; i++)
    {
        heap.push({i, i + 1, i * 2});
    }
    while(heap.size())
    {
        auto [a, b, c] = heap.top();
        heap.pop();
        cout << a << " " << b << " " c << endl;
    }
}
int main()
{
    test();
    return 0;
}

内置类型

#include 
#include 
#include 
using namespace std;

void test()
{
    int a[10] = {1, 41, 23, 10, 11, 2, -1, 99, 14, 0};

    priority_queue heap1; // 默认大根堆
    priority_queue, less> heap2; // 大根堆 priority_queue<数据类型, 存数据的结构, 数据之间的比较方式>
    priority_queue, greater> heap3; // 小根堆
    // 测试
    for(auto x : a)
    {
        heap1.push(x);
        heap2.push(x);
        heap3.push(x);
    }
    while(heap1.size())
    {
        cout << heap1.top() << " ";
        heap1.pop();
    }
    cout << endl;
    while(heap2.size())
    {
        cout << heap2.top() << " ";
        heap2.pop();
    }
    cout << endl;
    while(heap3.size())
    {
        cout << heap3.top() << " ";
        heap3.pop();
    }
    cout << endl;
}
int main()
{
    test();
    return 0;
}

你可能感兴趣的:(数据结构,C++,数据结构,c++)