C#實現(xiàn)雙端隊列的示例代碼
話說有很多數(shù)據(jù)結(jié)構(gòu)都在玩組合拳,比如說:塊狀鏈表,塊狀數(shù)組,當然還有本篇的雙端隊列,是的,它就是棧和隊列的組合體。
一、概念
我們知道普通隊列是限制級的一端進,另一端出的 FIFO 形式,棧是一端進出的 LIFO 形式,而雙端隊列就沒有這樣的限制,也就是我們可以在隊列兩端進行插入或者刪除操作。
二、編碼
2.1、定義結(jié)構(gòu)體
通常情況下,隊列的內(nèi)部都是采用數(shù)組來實現(xiàn),而且?guī)в袃蓚€指針 head 和 tail 來指向數(shù)組的區(qū)間段,為了充分利用數(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];
}
}
這里有一個注意的細節(jié)就是“size 字段“,它是為了方便統(tǒng)計隊列是否為滿或者隊列是否為空。
2.2、隊尾入隊
剛才也說了,雙端隊列是可以在隊列的兩端進行插入和刪除的,要注意的是我們用 head 和 tail 指針的時候,tail 指針是指向元素的下一個位置,
而 head 指針是指向當前元素,所以我們可以從 tail 端 push 數(shù)據(jù)的時候只要”順時針“下移一個位置即可。
/// <summary>
/// 隊尾入隊
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public bool Push_Tail(T t)
{
//判斷隊列是否已滿
if (myQueue.size == myQueue.list.Length)
return false;
myQueue.list[myQueue.tail] = t;
//順時針旋轉(zhuǎn)
myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize;
myQueue.size++;
return true;
}
2.3、隊尾出隊
和隊尾入隊一樣,我們只要將 tail 指針”逆時針“下移一個位置,當然有一個細節(jié)需要注意,就是 tail 指針有存在負值的情況,畢竟我們是做”–操作“的,所以需要 tail+maxSize,即:
myQueue.tail = (--myQueue.tail + myQueue.maxSize) % myQueue.maxSize;
/// <summary>
/// 隊尾出隊
/// </summary>
/// <param name="edges"></param>
/// <param name="t"></param>
public T Pop_Tail()
{
//判斷隊列是否已空
if (myQueue.size == 0)
return default(T);
//逆時針旋轉(zhuǎn)(防止負數(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、隊首入隊
從 head 端來說,我們 push 數(shù)據(jù)的時候是 head 指針“逆時針”旋轉(zhuǎn),要注意的是同樣要防止負數(shù)的產(chǎn)生,并且 head 指針是指向當前元素。
/// <summary>
/// 隊首入隊
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public bool Push_Head(T t)
{
//判斷隊列是否已滿
if (myQueue.size == myQueue.list.Length)
return false;
//逆時針旋轉(zhuǎn)(防止負數(shù)產(chǎn)生)
myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize;
//賦予元素
myQueue.list[myQueue.head] = t;
myQueue.size++;
return true;
}
2.5、隊首出隊
說到這個方法,我想大家應該都懂了雙端隊列的大概流程了,這個方法我也不用贅敘了。
/// <summary>
/// 隊首出隊
/// </summary>
/// <param name="edges"></param>
/// <param name="t"></param>
public T Pop_Head()
{
//判斷隊列是否已空
if (myQueue.size == 0)
return default(T);
//獲取隊首元素
var temp = myQueue.list[myQueue.head];
//原來單位的值賦默認值
myQueue.list[myQueue.head] = default(T);
//順時針旋轉(zhuǎn)
myQueue.head = (myQueue.head + 1) % myQueue.maxSize;
myQueue.size--;
return temp;
}
從上面的四個方法可以看出:
當我們只使用 Push_Tail 和 Pop_Tail 的話,那它就是棧。
當我們只使用 Push_Tail 和 Pop_Head 的話,那它就是隊列。
最后是全部代碼:
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>
/// 雙端隊列
/// </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>
/// 隊尾入隊
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public bool Push_Tail(T t)
{
//判斷隊列是否已滿
if (myQueue.size == myQueue.list.Length)
return false;
myQueue.list[myQueue.tail] = t;
//順時針旋轉(zhuǎn)
myQueue.tail = (myQueue.tail + 1) % myQueue.maxSize;
myQueue.size++;
return true;
}
/// <summary>
/// 隊尾出隊
/// </summary>
/// <param name="edges"></param>
/// <param name="t"></param>
public T Pop_Tail()
{
//判斷隊列是否已空
if (myQueue.size == 0)
return default(T);
//逆時針旋轉(zhuǎn)(防止負數(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>
/// 隊首入隊
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
public bool Push_Head(T t)
{
//判斷隊列是否已滿
if (myQueue.size == myQueue.list.Length)
return false;
//逆時針旋轉(zhuǎn)(防止負數(shù)產(chǎn)生)
myQueue.head = (--myQueue.head + myQueue.maxSize) % myQueue.maxSize;
//賦予元素
myQueue.list[myQueue.head] = t;
myQueue.size++;
return true;
}
/// <summary>
/// 隊首出隊
/// </summary>
/// <param name="edges"></param>
/// <param name="t"></param>
public T Pop_Head()
{
//判斷隊列是否已空
if (myQueue.size == 0)
return default(T);
//獲取隊首元素
var temp = myQueue.list[myQueue.head];
//原來單位的值賦默認值
myQueue.list[myQueue.head] = default(T);
//順時針旋轉(zhuǎn)
myQueue.head = (myQueue.head + 1) % myQueue.maxSize;
myQueue.size--;
return temp;
}
}到此這篇關(guān)于C#實現(xiàn)雙端隊列的示例代碼的文章就介紹到這了,更多相關(guān)C# 雙端隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C# paddlerocrsharp識別身份證號的實現(xiàn)示例
paddlerocrsharp可以進行圖片識別,本文主要介紹了C# paddlerocrsharp識別身份證號的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下2024-02-02
C#中創(chuàng)建統(tǒng)一API接口的實現(xiàn)方案
在 C# 中創(chuàng)建統(tǒng)一 API 接口需要從架構(gòu)設計、技術(shù)選型和代碼實現(xiàn)等多個層面進行規(guī)劃,本文給大家詳細介紹了實現(xiàn)方案和完整示例代碼,對大家的學習或工作有一定的幫助,需要的朋友可以參考下2025-04-04

