C#實(shí)現(xiàn)雙端隊(duì)列的示例代碼
話說(shuō)有很多數(shù)據(jù)結(jié)構(gòu)都在玩組合拳,比如說(shuō):塊狀鏈表,塊狀數(shù)組,當(dāng)然還有本篇的雙端隊(duì)列,是的,它就是棧和隊(duì)列的組合體。
一、概念
我們知道普通隊(duì)列是限制級(jí)的一端進(jìn),另一端出的 FIFO 形式,棧是一端進(jìn)出的 LIFO 形式,而雙端隊(duì)列就沒有這樣的限制,也就是我們可以在隊(duì)列兩端進(jìn)行插入或者刪除操作。
二、編碼
2.1、定義結(jié)構(gòu)體
通常情況下,隊(duì)列的內(nèi)部都是采用數(shù)組來(lái)實(shí)現(xiàn),而且?guī)в袃蓚€(gè)指針 head 和 tail 來(lái)指向數(shù)組的區(qū)間段,為了充分利用數(shù)組空間,我們也會(huì)用 % 來(lái)實(shí)現(xiàn)邏輯上的循環(huán)數(shù)組,如下圖。
public class MyQueue { public int head; public int tail; public int maxSize; public int size; public T[] list; public MyQueue() { head = tail = size = 0; maxSize = 3; list = new T[maxSize]; } }
這里有一個(gè)注意的細(xì)節(jié)就是“size 字段“,它是為了方便統(tǒng)計(jì)隊(duì)列是否為滿或者隊(duì)列是否為空。
2.2、隊(duì)尾入隊(duì)
剛才也說(shuō)了,雙端隊(duì)列是可以在隊(duì)列的兩端進(jìn)行插入和刪除的,要注意的是我們用 head 和 tail 指針的時(shí)候,tail 指針是指向元素的下一個(gè)位置,
而 head 指針是指向當(dāng)前元素,所以我們可以從 tail 端 push 數(shù)據(jù)的時(shí)候只要”順時(shí)針“下移一個(gè)位置即可。
/// <summary> /// 隊(duì)尾入隊(duì) /// </summary> /// <param name="t"></param> /// <returns></returns> public bool Push_Tail(T t) { //判斷隊(duì)列是否已滿 if (myQueue.size == myQueue.list.Length) return false; myQueue.list[myQueue.tail] = t; //順時(shí)針旋轉(zhuǎn) myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize; myQueue.size++; return true; }
2.3、隊(duì)尾出隊(duì)
和隊(duì)尾入隊(duì)一樣,我們只要將 tail 指針”逆時(shí)針“下移一個(gè)位置,當(dāng)然有一個(gè)細(xì)節(jié)需要注意,就是 tail 指針有存在負(fù)值的情況,畢竟我們是做”–操作“的,所以需要 tail+maxSize,即:
myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;
/// <summary> /// 隊(duì)尾出隊(duì) /// </summary> /// <param name="edges"></param> /// <param name="t"></param> public T Pop_Tail() { //判斷隊(duì)列是否已空 if (myQueue.size == 0) return default(T); //逆時(shí)針旋轉(zhuǎn)(防止負(fù)數(shù)) myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize; var temp = myQueue.list[myQueue.tail]; //賦予空值 myQueue.list[myQueue.tail] = default(T); myQueue.size--; return temp; }
2.4、隊(duì)首入隊(duì)
從 head 端來(lái)說(shuō),我們 push 數(shù)據(jù)的時(shí)候是 head 指針“逆時(shí)針”旋轉(zhuǎn),要注意的是同樣要防止負(fù)數(shù)的產(chǎn)生,并且 head 指針是指向當(dāng)前元素。
/// <summary> /// 隊(duì)首入隊(duì) /// </summary> /// <param name="t"></param> /// <returns></returns> public bool Push_Head(T t) { //判斷隊(duì)列是否已滿 if (myQueue.size == myQueue.list.Length) return false; //逆時(shí)針旋轉(zhuǎn)(防止負(fù)數(shù)產(chǎn)生) myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize; //賦予元素 myQueue.list[myQueue.head] = t; myQueue.size++; return true; }
2.5、隊(duì)首出隊(duì)
說(shuō)到這個(gè)方法,我想大家應(yīng)該都懂了雙端隊(duì)列的大概流程了,這個(gè)方法我也不用贅敘了。
/// <summary> /// 隊(duì)首出隊(duì) /// </summary> /// <param name="edges"></param> /// <param name="t"></param> public T Pop_Head() { //判斷隊(duì)列是否已空 if (myQueue.size == 0) return default(T); //獲取隊(duì)首元素 var temp = myQueue.list[myQueue.head]; //原來(lái)單位的值賦默認(rèn)值 myQueue.list[myQueue.head] = default(T); //順時(shí)針旋轉(zhuǎn) myQueue.head = (myQueue.head + 1) % myQueue.maxSize; myQueue.size--; return temp; }
從上面的四個(gè)方法可以看出:
當(dāng)我們只使用 Push_Tail 和 Pop_Tail 的話,那它就是棧。
當(dāng)我們只使用 Push_Tail 和 Pop_Head 的話,那它就是隊(duì)列。
最后是全部代碼:
using System.Net; using System; using System.IO; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Drawing.Imaging; class Program { static void Main(string[] args) { DoubleQueue<int> queue = new DoubleQueue<int>(); queue.Push_Tail(10); queue.Push_Tail(20); queue.Push_Tail(30); queue.Pop_Tail(); queue.Pop_Tail(); queue.Pop_Tail(); queue.Push_Tail(10); queue.Push_Head(20); queue.Push_Head(30); queue.Push_Head(30); queue.Pop_Tail(); queue.Pop_Tail(); queue.Pop_Head(); queue.Push_Head(40); queue.Push_Tail(50); queue.Push_Tail(60); } } /// <summary> /// 雙端隊(duì)列 /// </summary> public class DoubleQueue<T> { public class MyQueue { public int head; public int tail; public int maxSize; public int size; public T[] list; public MyQueue() { head = tail = size = 0; maxSize = 3; list = new T[maxSize]; } } MyQueue myQueue = new MyQueue(); /// <summary> /// 隊(duì)尾入隊(duì) /// </summary> /// <param name="t"></param> /// <returns></returns> public bool Push_Tail(T t) { //判斷隊(duì)列是否已滿 if (myQueue.size == myQueue.list.Length) return false; myQueue.list[myQueue.tail] = t; //順時(shí)針旋轉(zhuǎn) myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize; myQueue.size++; return true; } /// <summary> /// 隊(duì)尾出隊(duì) /// </summary> /// <param name="edges"></param> /// <param name="t"></param> public T Pop_Tail() { //判斷隊(duì)列是否已空 if (myQueue.size == 0) return default(T); //逆時(shí)針旋轉(zhuǎn)(防止負(fù)數(shù)) myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize; var temp = myQueue.list[myQueue.tail]; //賦予空值 myQueue.list[myQueue.tail] = default(T); myQueue.size--; return temp; } /// <summary> /// 隊(duì)首入隊(duì) /// </summary> /// <param name="t"></param> /// <returns></returns> public bool Push_Head(T t) { //判斷隊(duì)列是否已滿 if (myQueue.size == myQueue.list.Length) return false; //逆時(shí)針旋轉(zhuǎn)(防止負(fù)數(shù)產(chǎn)生) myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize; //賦予元素 myQueue.list[myQueue.head] = t; myQueue.size++; return true; } /// <summary> /// 隊(duì)首出隊(duì) /// </summary> /// <param name="edges"></param> /// <param name="t"></param> public T Pop_Head() { //判斷隊(duì)列是否已空 if (myQueue.size == 0) return default(T); //獲取隊(duì)首元素 var temp = myQueue.list[myQueue.head]; //原來(lái)單位的值賦默認(rèn)值 myQueue.list[myQueue.head] = default(T); //順時(shí)針旋轉(zhuǎn) myQueue.head = (myQueue.head + 1) % myQueue.maxSize; myQueue.size--; return temp; } }
到此這篇關(guān)于C#實(shí)現(xiàn)雙端隊(duì)列的示例代碼的文章就介紹到這了,更多相關(guān)C# 雙端隊(duì)列內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- c#隊(duì)列Queue學(xué)習(xí)示例分享
- C#隊(duì)列Queue用法實(shí)例分析
- C#隊(duì)列Queue多線程用法實(shí)例
- C#多線程處理多個(gè)隊(duì)列數(shù)據(jù)的方法
- C#使用隊(duì)列(Queue)解決簡(jiǎn)單的并發(fā)問(wèn)題
- C#數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(Quene)實(shí)例詳解
- C#環(huán)形隊(duì)列的實(shí)現(xiàn)方法詳解
- C#實(shí)現(xiàn)rabbitmq 延遲隊(duì)列功能實(shí)例代碼
- C#調(diào)用RabbitMQ實(shí)現(xiàn)消息隊(duì)列的示例代碼
- C#多線程處理多個(gè)隊(duì)列數(shù)據(jù)的方法
相關(guān)文章
C#使用Lambda表達(dá)式簡(jiǎn)化代碼的示例詳解
Lambda,希臘字母λ,在C#編程語(yǔ)言中,被引入為L(zhǎng)ambda表達(dá)式,表示為匿名函數(shù)(匿名方法)。本文將利用Lambda表達(dá)式進(jìn)行代碼的簡(jiǎn)化,感興趣的可以了解一下2022-12-12C# paddlerocrsharp識(shí)別身份證號(hào)的實(shí)現(xiàn)示例
paddlerocrsharp可以進(jìn)行圖片識(shí)別,本文主要介紹了C# paddlerocrsharp識(shí)別身份證號(hào)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-02-02C#中同步和異步回調(diào)的實(shí)現(xiàn)
在C#中,同步回調(diào)和異步回調(diào)都是用于處理任務(wù)或事件完成的機(jī)制,本文主要介紹了C#中同步和異步回調(diào)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-04-04C#實(shí)現(xiàn)的Win32控制臺(tái)線程計(jì)時(shí)器功能示例
這篇文章主要介紹了C#實(shí)現(xiàn)的Win32控制臺(tái)線程計(jì)時(shí)器功能,結(jié)合實(shí)例形式分析了C#基于控制臺(tái)的時(shí)間操作相關(guān)技巧,需要的朋友可以參考下2016-08-08c#中string的特性介紹及注意事項(xiàng)小結(jié)
這篇文章主要給大家介紹了關(guān)于c#中string的特性介紹及注意事項(xiàng)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用c#具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11C#中創(chuàng)建統(tǒng)一API接口的實(shí)現(xiàn)方案
在 C# 中創(chuàng)建統(tǒng)一 API 接口需要從架構(gòu)設(shè)計(jì)、技術(shù)選型和代碼實(shí)現(xiàn)等多個(gè)層面進(jìn)行規(guī)劃,本文給大家詳細(xì)介紹了實(shí)現(xiàn)方案和完整示例代碼,對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2025-04-04C#生成單頁(yè)靜態(tài)頁(yè)簡(jiǎn)單實(shí)例
這篇文章主要介紹了C#生成單頁(yè)靜態(tài)頁(yè)簡(jiǎn)單實(shí)例,是一個(gè)非常實(shí)用的技巧,需要的朋友可以參考下2014-10-10