当前位置: 首页 > news >正文

Linux环境下的C语言编程(四十二)

一、优先队列概念

优先队列是一种特殊的队列,元素出队顺序不是FIFO,而是按照优先级

  • 每次出队的是优先级最高(或最低)的元素

二、两种实现方式对比

特性使用数组/链表(朴素实现)使用堆(推荐实现)
入队时间复杂度O(1)O(log n)
出队(获取最高优先级)时间复杂度O(n)O(log n)
查找最高优先级O(n)O(1)

三、数组实现

1. 数组无序实现

#include <stdio.h> #include <stdlib.h> #include <limits.h> #define MAX_SIZE 100 typedef struct { int data[MAX_SIZE]; int size; } PriorityQueueArray; // 初始化 void initPriorityQueueArray(PriorityQueueArray* pq) { pq->size = 0; } // 入队 O(1) - 直接添加到尾部 void enqueueArray(PriorityQueueArray* pq, int value) { if (pq->size >= MAX_SIZE) { printf("队列已满!\n"); return; } pq->data[pq->size++] = value; } // 出队 O(n) - 需要遍历找到最大值 int dequeueArray(PriorityQueueArray* pq) { if (pq->size == 0) { printf("队列为空!\n"); return INT_MIN; } // 找到最大值的索引 int maxIndex = 0; for (int i = 1; i < pq->size; i++) { if (pq->data[i] > pq->data[maxIndex]) { maxIndex = i; } } // 保存最大值 int maxValue = pq->data[maxIndex]; // 用最后一个元素填补空缺 pq->data[maxIndex] = pq->data[pq->size - 1]; pq->size--; return maxValue; } // 查看最高优先级 O(n) int peekArray(PriorityQueueArray* pq) { if (pq->size == 0) return INT_MIN; int maxValue = pq->data[0]; for (int i = 1; i < pq->size; i++) { if (pq->data[i] > maxValue) { maxValue = pq->data[i]; } } return maxValue; } 2. 数组有序

四、堆实现

是一种特殊的完全二叉树,满足:

  • 最大堆:父节点 ≥ 子节点

  • 最小堆:父节点 ≤ 子节点

1. 最大堆实现优先队列

#include <stdio.h> #include <stdlib.h> #include <limits.h> #define MAX_HEAP_SIZE 100 typedef struct { int data[MAX_HEAP_SIZE]; int size; } MaxHeap; // 辅助函数:交换两个元素 void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } // 初始化堆 void initMaxHeap(MaxHeap* heap) { heap->size = 0; } // 获取父节点索引 int parent(int i) { return (i - 1) / 2; } // 获取左孩子索引 int leftChild(int i) { return 2 * i + 1; } // 获取右孩子索引 int rightChild(int i) { return 2 * i + 2; } // 上浮操作(维护堆性质)O(log n) void heapifyUp(MaxHeap* heap, int index) { while (index > 0 && heap->data[parent(index)] < heap->data[index]) { swap(&heap->data[parent(index)], &heap->data[index]); index = parent(index); } } // 下沉操作(维护堆性质)O(log n) void heapifyDown(MaxHeap* heap, int index) { int maxIndex = index; int left = leftChild(index); int right = rightChild(index); // 找到当前节点、左孩子、右孩子中的最大值 if (left < heap->size && heap->data[left] > heap->data[maxIndex]) { maxIndex = left; } if (right < heap->size && heap->data[right] > heap->data[maxIndex]) { maxIndex = right; } // 如果当前节点不是最大值,交换并继续下沉 if (index != maxIndex) { swap(&heap->data[index], &heap->data[maxIndex]); heapifyDown(heap, maxIndex); } } // 入队操作 O(log n) void heapEnqueue(MaxHeap* heap, int value) { if (heap->size >= MAX_HEAP_SIZE) { printf("堆已满!\n"); return; } // 1. 将新元素放到末尾 heap->data[heap->size] = value; heap->size++; // 2. 上浮调整 heapifyUp(heap, heap->size - 1); } // 出队操作 O(log n) int heapDequeue(MaxHeap* heap) { if (heap->size == 0) { printf("堆为空!\n"); return INT_MIN; } // 1. 保存堆顶(最大值) int maxValue = heap->data[0]; // 2. 用最后一个元素替换堆顶 heap->data[0] = heap->data[heap->size - 1]; heap->size--; // 3. 下沉调整 heapifyDown(heap, 0); return maxValue; } // 查看堆顶元素 O(1) int heapPeek(MaxHeap* heap) { if (heap->size == 0) return INT_MIN; return heap->data[0]; } // 构建堆 O(n) - 弗洛伊德建堆法 void buildHeap(MaxHeap* heap, int arr[], int n) { // 复制数据 for (int i = 0; i < n; i++) { heap->data[i] = arr[i]; } heap->size = n; // 从最后一个非叶子节点开始下沉 for (int i = n / 2 - 1; i >= 0; i--) { heapifyDown(heap, i); } } // 打印堆(树状结构) void printHeapTree(MaxHeap* heap, int index, int level) { if (index >= heap->size) return; // 先打印右子树 printHeapTree(heap, rightChild(index), level + 1); // 打印当前节点 for (int i = 0; i < level; i++) printf(" "); printf("%d\n", heap->data[index]); // 打印左子树 printHeapTree(heap, leftChild(index), level + 1); }

2. 最小堆实现

typedef struct { int data[MAX_HEAP_SIZE]; int size; } MinHeap; // 最小堆的上浮操作 void minHeapifyUp(MinHeap* heap, int index) { while (index > 0 && heap->data[parent(index)] > heap->data[index]) { swap(&heap->data[parent(index)], &heap->data[index]); index = parent(index); } } // 最小堆的下沉操作 void minHeapifyDown(MinHeap* heap, int index) { int minIndex = index; int left = leftChild(index); int right = rightChild(index); if (left < heap->size && heap->data[left] < heap->data[minIndex]) { minIndex = left; } if (right < heap->size && heap->data[right] < heap->data[minIndex]) { minIndex = right; } if (index != minIndex) { swap(&heap->data[index], &heap->data[minIndex]); minHeapifyDown(heap, minIndex); } }

五、时间复杂度对比分析

各种实现的时间复杂度:

操作无序数组/链表有序数组
插入(入队)O(1)O(n)O(log n)
删除最大(出队)O(n)O(1)O(log n)
获取最大(查看)O(n)O(1)O(1)
构建O(1)O(n log n)O(n)
http://www.cnnetsun.cn/news/23881.html

相关文章:

  • P11960 [GESP202503 五级] 平均分配
  • PINNs-Torch:实现9倍加速的物理信息神经网络框架
  • GPT-5.2发布!这些超强新功能,快来看看它是怎么让你的工作更轻松的!
  • ChromePass:三分钟掌握Chrome密码提取的终极指南
  • 【方法】IP66.net:如何查到自己的IP?
  • 南京大学开源SteadyDancer模型实现完美动作迁移,首帧保留彻底解决身份漂移难题
  • 机器视觉相机参数
  • springboot基于vue的观赏鱼养殖互助商城系统的设计与实现_1vlf0334
  • 压差式静力水准仪液体选择必看!从充液到排气:沉降监测系统安装全流程避雷手册
  • 构建可靠数据库连接:人大金仓JDBC驱动8.6.0实战指南
  • 嵌入式零基础到就业年班
  • 如何快速提取Chrome密码:跨平台开源工具完整指南
  • 5分钟掌握RichTextKit:SwiftUI富文本编辑器终极指南
  • 如何有效准备编程竞赛?五个阶段科学备考方法
  • BG3模组管理器终极指南:5分钟快速上手博德之门3模组管理
  • 6、黑客必备:Linux 网络技能与软件管理
  • Font Awesome 7全面解析:现代化图标解决方案的革新之路
  • MySQL业务数据量增长到单表成为瓶颈时,该如何做?
  • 13、Linux 系统日志处理与服务使用技巧
  • Paperzz 论文查重:从 “重复率焦虑” 到 “合规清晰”,学术新人如何用工具搞定论文的 “终稿安检”
  • Bananas屏幕共享:3分钟学会零门槛跨平台协作
  • 使用二进制文件方式部署kubernetes(1)
  • 如何在Mac上安装KeyCastr:5步搞定按键可视化工具
  • 小学生学C++编程 (位运算精讲)
  • 鸿蒙投屏工具HOScrcpy深度实战:突破传统镜像的进阶玩法
  • 基于MATLAB的胃癌检测实现方案
  • 图像分割新利器:预训练骨干网络快速构建高质量分割模型
  • 论文重复率 / AI 率双超?paperxie 的 “精准优化” 功能:如何在不碰专业内容的前提下过检测?
  • 36、Linux 系统安全防护全攻略
  • React Native语音识别终极指南:让你的应用听懂用户心声