c#隊列及其操作

可以用數組、鏈表實現隊列,大致與棧相似,簡要介紹下隊列實現吧。值得注意的是循環隊列判空判滿操作,在用鏈表實現時需要額外思考下出入隊列條件。

設計頭文件

#ifndef ARRAY_QUEUE_H
#define ARRAY_QUEUE_H#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#define QUEUE_CAPACITY 10
typedef int ElementType;typedef struct {// 由于是固長數組隊列,所以直接把數組作為結構體對象的一個成員ElementType elements[QUEUE_CAPACITY];int front;  // 隊頭元素的索引int rear;   // 隊尾元素下一個位置的索引int size;   // 隊列數組中實際存儲元素的個數
} ArrayQueue;// 初始化一個空隊列
ArrayQueue *queue_create();
// 銷毀一個隊列
void queue_destroy(ArrayQueue *q);
// 判滿
bool is_full(ArrayQueue *q);
// 判空
bool is_empty(ArrayQueue *q);
// 入隊
bool enqueue(ArrayQueue *q, ElementType element);
// 出隊
ElementType dequeue(ArrayQueue *q);
// 訪問隊首元素
ElementType peek(ArrayQueue *q);#endif // !ARRAY_QUEUE_H

實現創建和銷毀隊列

// 初始化一個空隊列
ArrayQueue *queue_create() {return calloc(1, sizeof(ArrayQueue));
}
// 銷毀一個隊列
void queue_destroy(ArrayQueue *q) {free(q);
}

實現判空和判滿

// 判滿
bool is_full(ArrayQueue *q) {return q->size == QUEUE_CAPACITY;
}
// 判空
bool is_empty(ArrayQueue *q) {return q->size == 0;
}

實現入隊操作

// 入隊
bool enqueue(ArrayQueue *q, ElementType element) {// 1.判滿if (is_full(q)) {printf("error: queue is full.\n");return false;}// 2.隊列沒滿時才入隊q->elements[q->rear] = element;// 3.更新rear索引q->rear = (q->rear + 1) % QUEUE_CAPACITY;// 4.更新sizeq->size++;return true;    // 入隊成功
}

實現出隊操作

/*
* 出隊就是將front索引的元素返回,然后將front索引后移
* 注意:不需要對front位置的元素做任何修改
* 因為front和rear之間的元素才是隊列元素,其它位置即便有值也不算隊列元素
* 其他位置的垃圾值,會隨著隊列出入隊操作逐漸被覆蓋
*/
ElementType dequeue(ArrayQueue *q) {// 1.判空if (is_empty(q)) {printf("error: queue is empty.\n");exit(1);}// 2.隊列非空,記錄隊首元素以用于返回ElementType ret = q->elements[q->front];// 3.更新front索引q->front = (q->front + 1) % QUEUE_CAPACITY;// 4.不要忘記更新sizeq->size--;return ret;
}

實現訪問隊首元素

// 訪問隊首元素
ElementType peek(ArrayQueue *q) {// 1.判斷隊列是否是空的if (is_empty(q)) {printf("error: queue is empty.\n");exit(1);}// 2.隊列非空返回隊首元素return q->elements[q->front];
}

擴展: 鏈式隊列

#ifndef LIST_QUEUE_H
#define LIST_QUEUE_H#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>// 定義隊列中的元素類型
typedef int ElementType;// 隊列節點的結構
typedef struct node_s {ElementType data;struct node_s *next;
} QueueNode;// 隊列的結構
typedef struct {QueueNode *front;  // 隊頭結點指針QueueNode *rear;   // 隊尾結點指針
} LinkedListQueue;// 函數聲明
// 創建鏈式隊列
LinkedListQueue *create_queue();
// 銷毀鏈式隊列
void destroy_queue(LinkedListQueue *q);
// 入隊列
bool enqueue(LinkedListQueue *q, ElementType element);
// 出隊列并返回隊頭元素
ElementType dequeue(LinkedListQueue *q);
// 訪問隊頭元素
ElementType peek_queue(LinkedListQueue *q);
// 判空
bool is_empty(LinkedListQueue *q);#endif // !LIST_QUEUE_H

鏈式隊列實現-參考代碼

#include "list_queue.h"// 函數聲明
LinkedListQueue *create_queue() {return calloc(1, sizeof(LinkedListQueue));
}void destroy_queue(LinkedListQueue *q) {// 從隊頭開始遍歷鏈表,銷毀每一個結點QueueNode *current = q->front;while (current != NULL) {QueueNode *temp = current->next;free(current);current = temp;}// 銷毀隊列結構體free(q);
}bool is_empty(LinkedListQueue *q) {// 隊頭指針是空指針,即表示空隊列return q->front == NULL;
}// 入隊操作: 只能在隊尾插入一個結點
// 由于已存在尾指針,所以這里的操作就是鏈表尾插
bool enqueue(LinkedListQueue *q, ElementType element) {QueueNode *new_node = malloc(sizeof(QueueNode));if (new_node == NULL) {printf("Error: malloc failed in enqueue.\n");return false;}// 初始化新結點new_node->data = element;new_node->next = NULL;// 開始進行尾插法插入一個結點// 分兩種情況:如果尾插插入的是第一個結點需要同步更新頭指針,否則僅需要更新尾指針if (q->front == NULL) {// 插入的是第一個結點q->front = new_node;q->rear = new_node;}else {// 插入的不是第一個結點q->rear->next = new_node;q->rear = new_node;}return true;
}// 出隊,在隊頭刪除一個結點。也就是在刪除鏈表的第一個結點
ElementType dequeue(LinkedListQueue *q) {if (is_empty(q)) {printf("Error: queue is empty.\n");exit(1);}QueueNode *tmp = q->front;// 將出隊的結點數據保存ElementType remove_data = tmp->data;// 更新隊頭指針q->front = tmp->next;if (q->front == NULL) {// 如果隊頭更新后,隊列為空,說明出隊的就是最后一個元素// 于是同步更新隊尾指針q->rear = NULL;}free(tmp);return remove_data;
}// 訪問隊頭元素但不出隊
ElementType peek_queue(LinkedListQueue *q) {if (is_empty(q)) {printf("Error: queue is empty.\n");exit(1);}return q->front->data;
}

擴展: 動態數組隊列

既然可以實現固定長度的隊列,那么基于動態數組,就可以實現一個動態數組隊列

#ifndef DYNAMIC_QUEUE_H
#define DYNAMIC_QUEUE_H#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>typedef int ElementType;    // 該隊列當前存儲int元素
#define DEFAULT_CAPACITY 10 // 數組隊列的初始長度是10
#define THRESHOLD 1000  // 超過閾值每次擴容1.5倍擴,否則2倍的擴// 定義隊列結構體
typedef struct {ElementType *data;   // 動態數組存儲隊列元素int front;           // 標記隊頭元素的索引int rear;            // 標記隊尾元素下一個位置的索引int size;            // 當前隊列中元素數量int capacity;        // 隊列容量
} DynamicQueue;// 隊列基本操作函數聲明
// 創建動態數組隊列
DynamicQueue *create_queue();
// 銷毀動態數組隊列
void destroy_queue(DynamicQueue *q);
// 判空
bool is_empty(DynamicQueue *q);
// 判滿
bool is_full(DynamicQueue *q);
// 入隊列
bool enqueue(DynamicQueue *q, ElementType data);
// 出隊列并且返回隊頭元素
ElementType dequeue(DynamicQueue *q);#endif // DYNAMIC_QUEUE_H

參考代碼

#include "dynamic_queue.h"// 創建并初始化隊列
DynamicQueue *create_queue() {DynamicQueue *q = calloc(1, sizeof(DynamicQueue));if (q == NULL) {printf("error: calloc failed in create_queue.\n");return NULL;}// front、rear、size自動初始化0值,無需再手動初始化了q->data = calloc(DEFAULT_CAPACITY, sizeof(ElementType));    // 使用calloc避免隨機值if (q->data == NULL) {printf("error: calloc failed in create_queue.\n");free(q);return NULL;}q->capacity = DEFAULT_CAPACITY;return q;
}// 銷毀隊列
void destroy_queue(DynamicQueue *q) {free(q->data);free(q);
}// 檢查隊列是否為空
bool is_empty(DynamicQueue *q) {return q->size == 0;
}// 檢查隊列是否已滿
bool is_full(DynamicQueue *q) {return q->size == q->capacity;
}/*這里采用一種簡單粗暴的擴容手段:直接分配新容量的內存塊然后遍歷舊內存塊中的隊列元素,將這些元素全部從頭開始復制到新內存塊中這樣的操作在完成后,需要更新front索引和rear索引
*/
static bool resize_queue(DynamicQueue *q) {int old_capacity = q->capacity;int new_capacity = (old_capacity < THRESHOLD) ?(old_capacity << 1) :(old_capacity + (old_capacity >> 1));// 重新分配一個新的,更長的動態數組ElementType *new_data = malloc(new_capacity * sizeof(ElementType));if (new_data == NULL) {printf("error: realloc failed in resize_queue.\n");return false;}int curr = q->front;    // curr索引用于遍歷整個隊列中的元素int index = 0;while (index < q->size) {new_data[index] = q->data[curr];curr = (curr + 1) % q->capacity;index++;} // while循環結束時,new_data就從頭開始包含了隊列的所有元素 free(q->data);q->data = new_data;q->front = 0;q->rear = q->size;q->capacity = new_capacity;return true;
}// 入隊操作
bool enqueue(DynamicQueue *q, ElementType data) {if (is_full(q)) {if (!resize_queue(q)) {printf("error: 擴容失敗.\n");return false; // 隊列擴容失敗,入隊也同步失敗}}q->data[q->rear] = data;q->rear = (q->rear + 1) % q->capacity;  // 循環隊列q->size++;return true;
}// 出隊操作
ElementType dequeue(DynamicQueue *q) {if (is_empty(q)) {printf("error: 隊列為空,無法出隊。\n");exit(1);}ElementType item = q->data[q->front];q->front = (q->front + 1) % q->capacity; // 循環隊列q->size--;return item;
}

隊列的應用場景

  1. 操作系統的任務調度,進程/線程按照到達順序來排隊等待CPU執行權。
  2. 各種數據處理系統中的緩沖區/緩存機制。比如stdin/stdout緩沖區,先輸入緩沖區的數據,總是先從緩沖區輸出。
  3. 打印機的任務管理,當多個打印任務同時到達時,它們在隊列中排隊,按照提交的順序進行打印。
  4. 后端應用系統中的消息隊列。
  5. 廣度優先搜索(比如二叉搜索樹的層次遍歷)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/80363.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/80363.shtml
英文地址,請注明出處:http://en.pswp.cn/web/80363.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

開源項目實戰學習之YOLO11:12.3 ultralytics-models-sam-encoders.py源碼分析

?? 點擊關注不迷路 ?? 點擊關注不迷路 ?? 另外,前些天發現了一個巨牛的AI人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。感興趣的可以點擊相關跳轉鏈接。 點擊跳轉到網站。 ultralytics-models-sam 1.sam-modules-encoders.pyblocks.py: 定義模型中的各…

STM32 | FreeRTOS 消息隊列

01 一、概述 隊列又稱消息隊列&#xff0c;是一種常用于任務間通信的數據結構&#xff0c;隊列可以在任務與任務間、中斷和任務間傳遞信息&#xff0c;實現了任務接收來自其他任務或中斷的不固定長度的消息&#xff0c;任務能夠從隊列里面讀取消息&#xff0c;當隊列中的消…

Java 安全漏洞掃描工具:如何快速發現和修復潛在問題?

Java 安全漏洞掃描工具&#xff1a;如何快速發現和修復潛在問題&#xff1f; 在當今的軟件開發領域&#xff0c;Java 作為一種廣泛使用的編程語言&#xff0c;其應用的規模和復雜度不斷攀升。然而&#xff0c;隨著應用的拓展&#xff0c;Java 應用面臨的潛在安全漏洞風險也日益…

Python繪制克利夫蘭點圖:從入門到實戰

Python繪制克利夫蘭點圖&#xff1a;從入門到實戰 引言 克利夫蘭點圖&#xff08;Cleveland Dot Plot&#xff09;是一種強大的數據可視化工具&#xff0c;由統計學家William Cleveland在1984年提出。這種圖表特別適合展示多個類別的數值比較&#xff0c;比傳統的條形圖更直觀…

LVGL- Calendar 日歷控件

1 日歷控件 1.1 日歷背景 lv_calendar 是 LVGL&#xff08;Light and Versatile Graphics Library&#xff09;提供的標準 GUI 控件之一&#xff0c;用于顯示日歷視圖。它支持用戶查看某年某月的完整日歷&#xff0c;還可以實現點擊日期、標記日期、導航月份等操作。這個控件…

多指標組合策略

該策略(MultiConditionStrategy)是一種基于多種技術指標和市場條件的交易策略。它通過綜合考慮多個條件來生成交易信號,從而決定買入或賣出的時機。 以下是對該策略的詳細分析: 交易邏輯思路 1. 條件1:星期幾和價格變化判斷 - 該條件根據當前日期是星期幾以及價格的變化…

BC 范式與 4NF

接下來我們詳細解釋 BC 范式&#xff08;Boyce-Codd范式&#xff0c;簡稱 BCNF&#xff09;&#xff0c;并通過具體例子說明其定義和應用。 一、BC范式的定義 BC范式&#xff08;Boyce-Codd范式&#xff0c;BCNF&#xff09;是數據庫規范化理論中的一種范式&#xff0c;它比第…

基于 CSS Grid 的網頁,拆解頁面整體布局結構

通過以下示例拆解網頁整體布局結構&#xff1a; 一、基礎結構&#xff08;HTML骨架&#xff09; <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"…

采購流程規范化如何實現?日事清流程自動化助力需求、采購、財務高效協作

采購審批流程全靠人推進&#xff0c;內耗嚴重&#xff0c;效率低下&#xff1f; 花重金上了OA&#xff0c;結果功能有局限、不靈活&#xff1f; 問題出在哪里&#xff1f;是我們的要求太多、太苛刻嗎&#xff1f;NO&#xff01; 流程名稱&#xff1a; 采購審批管理 流程功能…

全棧項目搭建指南:Nuxt.js + Node.js + MongoDB

全棧項目搭建指南&#xff1a;Nuxt.js Node.js MongoDB 一、項目概述 我們將構建一個完整的全棧應用&#xff0c;包含&#xff1a; 前端&#xff1a;Nuxt.js (SSR渲染)后端&#xff1a;Node.js (Express/Koa框架)數據庫&#xff1a;MongoDB后臺管理系統&#xff1a;集成在同…

NVMe簡介6之PCIe事務層

PCIe的事務層連接了PCIe設備核心與PCIe鏈路&#xff0c;這里主要基于PCIe事務層進行分析。事務層采用TLP傳輸事務&#xff0c;完整的TLP由TLPPrefix、TLP頭、Payload和TLP Digest組成。TLP頭是TLP中最關鍵的部分&#xff0c;一般由三個或四個雙字的長度&#xff0c;其格式定義如…

Python異常模塊和包

異常 當檢測到一個錯誤時&#xff0c;Python解釋器就無法繼續執行了&#xff0c;反而出現了一些錯誤的提示&#xff0c;這就是所謂的“異常”, 也就是我們常說的BUG 例如&#xff1a;以r方式打開一個不存在的文件。 f open(‘python1.txt’,‘r’,encoding‘utf-8’) 當我們…

匯編:循環程序設計

一、 實驗要求 熟練掌握循環程序設計的基本方法熟練掌握單片機外部存儲空間的訪問方法 二、 實驗設計 1.整體思路 先初始化一些寄存器和數據存儲位置&#xff0c;然后調用兩個子程序Procedure1和Procedure2&#xff0c;分別從SRC復制數據到DEST&#xff0c;一個從開頭到末尾&…

典籍知識問答模塊AI問答bug修改

一、修改流式數據處理問題 1.問題描述&#xff1a;由于傳來的數據形式如下&#xff1a; event:START data:350 data:< data:t data:h data:i data:n data:k data:> data: data: data: data: data:嗯 data:&#xff0c; 導致需要修改獲取正常的當前信息id并更…

【金倉數據庫征文】- 金融HTAP實戰:KingbaseES實時風控與毫秒級分析一體化架構

文章目錄 引言&#xff1a;金融數字化轉型的HTAP引擎革命一、HTAP架構設計與資源隔離策略1.1 混合負載物理隔離架構1.1.1 行列存儲分區策略1.1.2 四級資源隔離機制 二、實時流處理與增量同步優化2.1 分鐘級新鮮度保障2.1.1 WAL日志增量同步2.1.2 流計算優化 2.2 物化視圖實時刷…

季報中的FPGA行業:U型反轉,春江水暖

上周Lattice,AMD兩大廠商相繼發布2025 Q1季報,盡管恢復速度各異,但同時傳遞出FPGA行業整體回暖的復蘇信號。 5月5日,Lattice交出了“勉強及格”的答卷,報告季度營收1億2000萬,與華爾街的預期基本相符。 對于這家聚焦在中小規模器件的領先廠商而言,按照其CEO的預期,長…

使用 javap 深入理解 Java 字節碼

引言 Java 是一種廣泛使用的高級編程語言,其獨特之處在于編譯后的代碼不是直接的機器碼,而是一種稱為字節碼的中間表示形式。字節碼存儲在 .class 文件中,由 Java 虛擬機 (JVM) 解釋或即時編譯為特定平臺的機器碼。這種設計賦予了 Java 平臺無關性,即“一次編寫,到處運行…

LeetCode_sql刷題(3482.分析組織層級)

題目描述&#xff1a;3482. 分析組織層級 - 力扣&#xff08;LeetCode&#xff09; 表&#xff1a;Employees ------------------------- | Column Name | Type | ------------------------- | employee_id | int | | employee_name | varchar | | manager_id …

工業場景輪式巡檢機器人純視覺識別導航的優勢剖析與前景展望

一、引言 1.1 研究背景與意義 在工業 4.0 的大背景下&#xff0c;工業生產的智能化、自動化水平不斷提高&#xff0c;對工業場景的巡檢工作提出了更高的要求。傳統的人工巡檢方式不僅效率低下、成本高昂&#xff0c;而且容易受到人為因素的影響&#xff0c;難以滿足現代工業生…

《棒球萬事通》球類運動有哪些項目·棒球1號位

以棒球運動為例&#xff0c;棒球運動涉及多個核心項目和比賽形式&#xff0c;以下為主要分類&#xff1a; 一、比賽環節 投球&#xff08;Pitching&#xff09; 防守方投手向擊球員投球&#xff0c;目標是讓對方難以擊中或制造出局。 擊球&#xff08;Batting&#xff09; …