[其它应用] 基于堆的优先队列

[复制链接]
5982|12
 楼主| cr315 发表于 2024-11-12 13:00 | 显示全部楼层 |阅读模式
堆是一种特殊的树形数据结构,具有以下性质:堆是一个完全二叉树(Complete Binary Tree)。堆中的每个节点的值都必须满足堆的性质,即父节点的值必须大于或等于(最大堆)或小于或等于(最小堆)其子节点的值。优先队列是一种特殊的队列,其中每个元素都有一个与之关联的优先级。元素的出队顺序是根据优先级确定的,具有较高优先级的元素先出队。下面是一个基于堆的优先队列的 C 语言实现,包括创建、判空、判满、插入、查找最值、删除和摧毁等操作。#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 100

typedef struct {
    int data[MAX_SIZE];
    int size;
} PriorityQueue;

// 初始化优先队列
void initialize(PriorityQueue *queue) {
    queue->size = 0;
}

// 判断优先队列是否为空
int isEmpty(PriorityQueue *queue) {
    return queue->size == 0;
}

// 判断优先队列是否已满
int isFull(PriorityQueue *queue) {
    return queue->size == MAX_SIZE;
}

// 插入元素到优先队列
void insert(PriorityQueue *queue, int item) {
    if (isFull(queue)) {
        printf("Priority Queue is full. Cannot insert element.\n");
        return;
    }

    // 将元素插入到队尾
    queue->data[queue->size] = item;
    queue->size++;

    // 对插入的元素进行上浮操作,以维护堆的性质
    int i = queue->size - 1;
    while (i > 0 && queue->data > queue->data[(i - 1) / 2]) {
        int parent = (i - 1) / 2;
        int temp = queue->data;
        queue->data = queue->data[parent];
        queue->data[parent] = temp;
        i = parent;
    }
}

// 查找优先队列中的最大值(最大堆)或最小值(最小堆)
int findMax(PriorityQueue *queue) {
    if (isEmpty(queue)) {
        printf("Priority Queue is empty.\n");
        return -1;
    }

    return queue->data[0];
}

// 删除优先队列中的最大值(最大堆)或最小值(最小堆)
void deleteMax(PriorityQueue *queue) {
    if (isEmpty(queue)) {
        printf("Priority Queue is empty. Cannot delete element.\n");
        return;
    }

    // 将堆顶元素与队尾元素交换
    queue->data[0] = queue->data[queue->size - 1];
    queue->size--;

    // 对交换后的堆顶元素进行下沉操作,以维护堆的性质
    int i = 0;
    while (1) {
        int leftChild = 2 * i + 1;
        int rightChild = 2 * i + 2;
        int largest = i;

        if (leftChild < queue->size && queue->data[leftChild] > queue->data[largest]) {
            largest = leftChild;
        }

        if (rightChild < queue->size && queue->data[rightChild] > queue->data[largest]) {
            largest = rightChild;
        }

        if (largest != i) {
            int temp = queue->data;
            queue->data = queue->data[largest];
            queue->data[largest] = temp;
            i = largest;
        } else {
            break;
        }
    }
}

// 销毁优先队列
void destroy(PriorityQueue *queue) {
    queue->size = 0;
}

int main() {
    PriorityQueue queue;
    initialize(&queue);

    // 插入元素到优先队列
    insert(&queue, 10);
    insert(&queue, 30);
    insert(&queue, 20);

    // 输出优先队列中的最大值
    printf("Max value: %d\n", findMax(&queue));

    // 删除优先队列中的最大值
    deleteMax(&queue);

    // 输出优先队列中的最大值
    printf("Max value: %d\n", findMax(&queue));

    // 销毁优先队列
    destroy(&queue);

    return 0;
}
这段代码实现了一个最大堆的优先队列。可以根据需要修改代码中的 MAX_SIZE 宏定义来调整队列的最大容量。在 main 函数中,我们先初始化一个优先队列 queue,然后插入一些元素,查找并输出最大值,删除最大值,最后销毁队列。
szt1993 发表于 2024-11-20 10:42 | 显示全部楼层
堆是一种特殊的树形数据结构,具有以下性质:堆是一个完全二叉树(Complete Binary Tree)。
LOVEEVER 发表于 2024-11-25 23:48 | 显示全部楼层
这段代码实现了一个最大堆的优先队列非常不错
中国龙芯CDX 发表于 2024-11-27 09:33 | 显示全部楼层
堆是一种特殊的树形数据结构
小夏天的大西瓜 发表于 2024-11-28 00:11 | 显示全部楼层
堆是一个完全二叉树
小小蚂蚁举千斤 发表于 2024-11-29 21:03 | 显示全部楼层
堆是一种特殊的树形数据结构
Henryko 发表于 2024-11-30 08:38 来自手机 | 显示全部楼层
完全二叉树是什么啊
AdaMaYun 发表于 2024-11-30 16:23 | 显示全部楼层
基于堆的优先队列的 C 语言实现案例非常不错
Bowclad 发表于 2024-12-13 15:53 | 显示全部楼层
堆为什么是树形结构啊?
OKAKAKO 发表于 2024-12-22 21:45 | 显示全部楼层
堆与栈有什么区别
玫瑰凋零日记 发表于 2025-6-28 15:03 | 显示全部楼层
基于堆的优先队列是一种数据结构,核心在于利用堆(完全二叉树且父节点值≥子节点的大顶堆,或≤的小顶堆)特性实现 “优先” 操作。堆的根节点始终是优先级最高(或最低)的元素,插入和删除操作均保持堆性质:

插入:新元素添加到堆末尾,然后向上 “上浮” 调整,直至满足堆序(如大顶堆中比父节点大则交换)。
删除:删除根节点后,将堆尾元素移至根,再向下 “下沉” 调整,确保新根为优先级最高元素。
时间复杂度:插入和删除均为 O (log n),优于普通数组的 O (n)。常用于任务调度(高优先级任务先执行)、Dijkstra 算法(选最短路径节点)、堆排序等场景,本质是通过堆的结构高效维护元素优先级顺序。

野玫瑰 发表于 2025-7-13 19:55 | 显示全部楼层
基于堆的优先队列可在 O (log n) 时间完成插入和获取最值操作,效率高且实现简单,适合动态数据的优先级管理。
一点点晚风 发表于 2025-7-19 11:03 | 显示全部楼层
基于堆的优先队列:插入删除 O (logn),高效维护优先级。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1466

主题

4980

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部