C语言 优先队列

本文介绍了C语言中实现优先队列的概念,重点讲解了如何通过代码创建一个优先队列,该队列具备自动排序的功能。

优先队列

优先队列相比队列多了一个功能,就是自动排序

代码实现
#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define QUETYPE char
#define SORTTYPE int

typedef struct node {
    QUETYPE data;
    struct node *next;
} QueueNode, *QueueNodePtr;

typedef struct {
    QueueNodePtr head;
    QueueNodePtr tail;
} Queue, *QueuePtr;

QueuePtr createQueue();
QueueNodePtr createQueueNode(QUETYPE key);
void insertQueue(QueuePtr q, QUETYPE key);
QUETYPE outQueue(QueuePtr q);
void deleteQueue(QueuePtr q);

/**********排序**********/

SORTTYPE sortData(QueueNodePtr q) {
    return q->data;
}


void exchange(QueueNodePtr a, QueueNodePtr b) {
    SORTTYPE *aa = &(a->data);
    SORTTYPE tmp_a = a->data;

    SORTTYPE *bb = &(b->data);
    *aa = b->data;
    *bb = tmp_a;
}


void queueSort(QueuePtr q) {
    //选择排序
    QueueNodePtr tmp = NULL;
    tmp = q->head;
    while (tmp != NULL) {
        QueueNodePtr tmp2 = tmp;
        SORTTYPE data = sortData(tmp);
        while (tmp2 != NULL) {
            if (sortData(tmp2) < data) {
                exchange(tmp, tmp2);
            }
            tmp2 = tmp2->next;
        }
        tmp = tmp->next;
    }
}

/**********排序**********/

void main() {
    QueuePtr q = createQueue();
    for (int i = 10; i >0; i--) {
        insertQueue(q, i, 1);
    }
    outQueue(q);
    deleteQueue(q);
}

QueuePtr createQueue() {
    QueuePtr q = (QueuePtr)malloc(sizeof(Queue));
    memset(q, 0, sizeof(Queue));
    q->head = q->tail = NULL;
    return q;
}

QueueNodePtr createQueueNode(QUETYPE key) {
    QueueNodePtr q = (QueueNodePtr)malloc(sizeof(Queue));
    memset(q, 0, sizeof(Queue));
    q->next = NULL;
    q->data = key;
    return q;
}



void insertQueue(QueuePtr q, QUETYPE key, int isSort) {
    QueueNodePtr a = createQueueNode(key);
    if (q->head == NULL) {  //notice
        q->head = q->tail = a;
    }
    else {
        q->tail->next = a;
        q->tail = a;
    }
    if(isSort == 1) //自动排序
        queueSort(q);
}

QUETYPE outQueue(QueuePtr q) {
    QUETYPE v;
    if (q->head != NULL) {   //notice
        v = q->head->data;
        QueueNodePtr tmp = q->head->next;
        free(q->head);
        q->head = tmp;
    }
    else {
        v = NULL;
    }
    return v;
}

void deleteQueue(QueuePtr q) {
    if (q->head != NULL) {  //notice
        QueueNodePtr tmp = q->head;
        QueueNodePtr tmp2;
        while (tmp != NULL) {
            tmp2 = tmp;
            tmp = tmp->next;
            free(tmp2);
        }
    }
    free(q);
}
<think>我们被要求使用C语言实现优先队列优先队列通常使用二叉堆(特别是最大堆或最小堆)来实现,因为这样可以在O(log n)时间内完成插入和删除操作,并在O(1)时间内访问最大(或最小)元素。 根据引用[2]和引用[3]提供的结构,我们可以定义一个优先队列的数据结构,其中包含一个数组(用于存储堆)、当前元素数量和数组的最大容量。 我们将实现最小优先队列(最小堆),即每个节点的值都小于或等于其子节点的值。这样,堆顶元素(数组的第一个元素)就是最小的元素。 需要实现的操作包括: 1. 初始化优先队列 2. 销毁优先队列 3. 插入元素 4. 删除最小元素(出队) 5. 获取最小元素(查看队首) 6. 判断队列是否为空 7. 判断队列是否已满 此外,我们还需要一些辅助函数来维护堆的性质,例如上浮(swim)和下沉(sink)操作。 步骤: 1. 定义结构体PriorityQueue。 2. 实现初始化函数:分配内存,设置容量,当前大小为0。 3. 实现销毁函数:释放内部数组和结构体本身。 4. 实现插入操作:将新元素放在数组末尾,然后进行上浮操作(如果新元素比父节点小,则交换)。 5. 实现删除最小元素:将数组末尾元素移到根节点,然后进行下沉操作(与较小的子节点比较并交换,直到满足堆性质)。 6. 实现获取最小元素:直接返回数组第一个元素(如果队列不为空)。 7. 实现判断空和满的函数。 注意:数组下标从0开始,那么对于节点i,其左子节点为2*i+1,右子节点为2*i+2,父节点为(i-1)/2。 下面我们按照这个思路实现代码。 </think>### C语言实现优先队列算法 优先队列是一种特殊的队列,其中每个元素都有优先级优先级最高的元素最先出队。以下是基于二叉堆的最小优先队列实现(数值越小优先级越高): ```c #include <stdio.h> #include <stdlib.h> // 优先队列结构体 typedef struct { int *elements; // 存储元素的数组 int capacity; // 数组最大容量 int size; // 当前元素数量 } PriorityQueue; // 初始化优先队列 PriorityQueue* initPriorityQueue(int capacity) { PriorityQueue *pq = (PriorityQueue*)malloc(sizeof(PriorityQueue)); pq->elements = (int*)malloc(capacity * sizeof(int)); pq->capacity = capacity; pq->size = 0; // 初始为空队列 return pq; } // 销毁优先队列 void destroyPriorityQueue(PriorityQueue *pq) { if (pq) { free(pq->elements); free(pq); } } // 堆下沉操作(维护堆性质) void heapifyDown(PriorityQueue *pq, int index) { int smallest = index; int left = 2 * index + 1; int right = 2 * index + 2; // 找出当前节点和两个子节点中的最小值 if (left < pq->size && pq->elements[left] < pq->elements[smallest]) smallest = left; if (right < pq->size && pq->elements[right] < pq->elements[smallest]) smallest = right; // 如果需要交换,则继续下沉 if (smallest != index) { int temp = pq->elements[index]; pq->elements[index] = pq->elements[smallest]; pq->elements[smallest] = temp; heapifyDown(pq, smallest); } } // 堆上浮操作(维护堆性质) void heapifyUp(PriorityQueue *pq, int index) { int parent = (index - 1) / 2; while (index > 0 && pq->elements[index] < pq->elements[parent]) { int temp = pq->elements[parent]; pq->elements[parent] = pq->elements[index]; pq->elements[index] = temp; index = parent; parent = (index - 1) / 2; } } // 插入元素 void enqueue(PriorityQueue *pq, int value) { if (pq->size >= pq->capacity) { printf("Queue is full!\n"); return; } pq->elements[pq->size] = value; // 将新元素放入末尾 heapifyUp(pq, pq->size); // 上浮调整堆 pq->size++; // 更新大小 } // 删除并返回最小元素 int dequeue(PriorityQueue *pq) { if (pq->size <= 0) { printf("Queue is empty!\n"); return -1; // 错误值 } int minValue = pq->elements[0]; // 保存堆顶元素 pq->elements[0] = pq->elements[pq->size - 1]; // 将末尾元素移到堆顶 pq->size--; // 更新大小 heapifyDown(pq, 0); // 下沉调整堆 return minValue; } // 查看最小元素(不移除) int peek(PriorityQueue *pq) { if (pq->size <= 0) { printf("Queue is empty!\n"); return -1; // 错误值 } return pq->elements[0]; } // 检查队列是否为空 int isEmpty(PriorityQueue *pq) { return pq->size == 0; } // 示例使用 int main() { PriorityQueue *pq = initPriorityQueue(10); enqueue(pq, 5); enqueue(pq, 2); enqueue(pq, 8); enqueue(pq, 1); printf("Min element: %d\n", dequeue(pq)); // 输出 1 printf("Min element: %d\n", dequeue(pq)); // 输出 2 destroyPriorityQueue(pq); return 0; } ``` ### 关键实现说明: 1. **数据结构**:使用数组存储二叉堆,通过索引关系维护堆结构[^2][^3] 2. **时间复杂度**: - 插入操作(enqueue):$O(\log n)$ - 删除操作(dequeue):$O(\log n)$ - 查看最小元素(peek):$O(1)$ 3. **堆操作**: - `heapifyUp`:插入元素后从底部向上调整堆 - `heapifyDown`:删除元素后从顶部向下调整堆 4. **二叉堆性质**:对于任意节点i,满足: - $elements[i] \leq elements[2i+1]$ - $elements[i] \leq elements[2i+2]$ 该实现满足了优先队列的核心特性:最高优先级元素(最小值)始终位于堆顶,可通过常数时间访问[^1]。二叉堆的实现方式在时间和空间复杂度上达到了较好平衡。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值