C# 数据结构 之 堆栈和队列
堆棧(Stack)是一種特殊的線性表,是一種操作只允許在尾端進行插入或刪除等操作的線性表。表尾允許進行插入刪除操作,稱為棧頂(Top),另一端是固定的,稱為棧底(Bottom).棧的操作使按照先進后出或后進先出的原則進行的。
用一片連續的存儲空間來存儲棧中的數據元素,稱為順序棧(Sequence Stack)。類似于順序表,用一維數組來存放棧中的數據元素。缺點:浪費存儲空間。
用鏈式存儲結構來存儲的棧為鏈棧(Linked Stack).鏈棧通常用單鏈表來表示。
Stack using System; using System.Collections.Generic; using System.Linq; using System.Text;namespace DataStructure {interface IStack<T>{void Push(T item); //入棧操作T Pop(); //出棧操作T GetTop(); //取棧頂元素int GetLength(); //求棧的長度bool IsEmpty(); //判斷棧是否為空void Clear(); //清空操作 }/// <summary>/// 順序棧/// </summary>/// <typeparam name="T"></typeparam>class SequenceStack<T> : IStack<T>{private int maxsize; //順序棧的容量private T[] data; //數組,用于存儲順序棧中的數據元素private int top; //指示順序棧的棧頂//索引器public T this[int index]{get { return data[index]; }set { data[index] = value; }}//容量屬性public int Maxsize{get { return maxsize; }set { maxsize = value; }}//棧頂屬性public int Top{get{return top;}}public SequenceStack(int size){data = new T[size];maxsize = size;top = -1;}//求棧的長度public int GetLength(){return top + 1;}//清空順序棧public void Clear(){top = -1;}//判斷順序棧是否為空public bool IsEmpty(){if (top == -1){return true;}elsereturn false;}//判斷棧是否為滿public bool IsFull(){if (top == maxsize - 1){return true;}elsereturn false;}//入棧public void Push(T elem){if (IsFull()){Console.WriteLine("Stack is Full !");return;}data[++top] = elem;}//出棧public T Pop(){T tem = default(T);if (IsEmpty()){Console.WriteLine("Stack is Empty !");return default(T);}tem = data[top];--top;return tem;}//獲取棧頂元素public T GetTop(){if (IsEmpty()){Console.WriteLine("Stack is Empty !");return default(T);}return data[top];}}/// <summary>/// 用順序棧解決火車車廂重排問題/// </summary>class TrainArrangwBySeqStack{//車廂重排算法,K個緩沖鐵軌,車廂初始排序存放在P中public bool RailRoad(int[] p, int n, int k){//創建與緩沖鐵軌對應的堆棧SequenceStack<int>[] H;H = new SequenceStack<int>[k + 1];for (int i = 0; i <= k; i++)H[i] = new SequenceStack<int>(p.Length);int NowOut = 1; //下次要輸出的車廂int minH = n + 1; //緩沖鐵軌中編號最小的車廂int minS = 0; //minH號車廂對應的緩沖鐵軌//車廂重排for (int i = 0; i < n; i++){if (p[i] == NowOut){Console.WriteLine("Move car {0} from input to output", p[i]);NowOut++;//從緩沖鐵軌中輸出while (minH == NowOut){Output(ref minH, ref minS, ref H, k, n);NowOut++;}}else{if (!Hold(p[i], ref minH, ref minS, ref H, k, n)){return false;}}}return true;}//在一個緩沖區中放入車廂Cpublic bool Hold(int c, ref int minH, ref int minS, ref SequenceStack<int>[] H, int k, int n){//如果沒有可用的緩沖鐵軌,則返回false//否則返回true//為車廂c尋找最優的鐵軌//初始化int BestTrack = 0; //目前最優的鐵軌int BestTop = n + 1; //最優鐵軌上的頭輛車廂int x; //車廂索引//掃描緩沖鐵軌for (int i = 1; i <= k; i++)//!!!i=1 {if (!H[i].IsEmpty()){//鐵軌i不為空x = H[i][H[i].Top];if (c < x && x < BestTop){//鐵軌i頂部的車廂編號最小BestTop = x;BestTrack = i;}}else//鐵軌i為空 {if (BestTrack == 0){BestTrack = i;}break;}}if (BestTrack == 0)return false;//沒有可用鐵軌//把車廂c送入緩沖鐵軌 H[BestTrack].Push(c);Console.WriteLine("Move car{0} from input to holding track {1}", c, BestTrack);//必要時修改minH minSif (c < minH){minH = c;minS = BestTrack;}return true;}//把車廂從緩沖區鐵軌送至出軌處,同時修改minH minSpublic void Output(ref int minH, ref int minS, ref SequenceStack<int>[] H, int k, int n){int c;//車廂索引//從堆棧minS中刪除編寫、好最小的車廂minHc = H[minS].Pop();Console.WriteLine("Move car{0} from holding track {1} to output", minH, minS);//通過檢查所有的棧頂,搜索新的minH minSminH = n + 2;for (int i = 1; i <= k; i++){if (!H[i].IsEmpty() && (c = H[i][H[i].Top]) < minH){minH = c;minS = i;}}}}/// <summary>/// 鏈棧結點/// </summary>class StackNode<T>{private T data; //數據域private StackNode<T> next; //引用域public StackNode(){data = default(T);next = null;}public StackNode(T val){data = val;next = null;}public StackNode(T val, StackNode<T> p){data = val;next = p;}//數據域屬性public T Data{get { return data; }set { data = value; }}//引用域屬性public StackNode<T> Next{get { return next; }set { next = value; }}}/// <summary>/// 鏈棧/// </summary>/// <typeparam name="T"></typeparam>class LinkStack<T> : IStack<T>{private StackNode<T> top; //棧頂指示器private int size; //棧中元素的個數//棧頂指示器屬性public StackNode<T> Top{get { return top; }set { top = value; }}//元素個數屬性public int Size{get { return size; }set { size = value; }}public LinkStack(){top = null;size = 0;}//判斷鏈棧是否為空public bool IsEmpty(){if ((top == null) && (size == 0))return true;elsereturn false;}public int GetLength(){return size;}public void Clear(){top = null;size = 0;}//入棧操作//在單鏈表的起始處插入一個結點public void Push(T item){StackNode<T> q = new StackNode<T>(item);if (top == null){top = q;}else{//將新結點的next指向棧頂指示器top所指向的結點q.Next = top;//將棧頂指示器top指向新結點top = q;}++size;}//出棧操作public T Pop(){if (IsEmpty()){Console.WriteLine("Stack is empty !");return default(T);}StackNode<T> p = top;top = top.Next;--size;return p.Data;}//獲取棧頂結點的值public T GetTop(){if (IsEmpty()){Console.WriteLine("Stack is empty !");return default(T);}return top.Data;}}/// <summary>/// 用鏈棧解決火車車廂重排問題/// </summary>class TrainArrangeByLinkStack{//k個緩沖鐵軌,車廂初始排序存儲在p中public bool RailRoad(int[] p, int n, int k){//創建與緩沖鐵軌對應的堆棧LinkStack<int>[] H;H = new LinkStack<int>[k + 1];for (int i = 1; i <= k; i++){H[i] = new LinkStack<int>();}int NowOut = 1; //下一次要輸出的車廂int minH = n + 1; //緩沖鐵軌中編號最小的車廂int minS = 0; //minH號車廂對應的緩沖鐵軌//車廂重排for (int i = 0; i < n; i++){if (p[i] == NowOut){Console.WriteLine("Move car {0} from input to output", p[i]);NowOut++;//從緩沖鐵軌中輸出while (minH == NowOut){Output(ref minH, ref minS, ref H, k, n);NowOut++;}}else{//將p[i]送入緩沖鐵軌if (!Hold(p[i], ref minH, ref minS, ref H, k, n))return false;}}return true;}//在一個緩沖鐵軌中放入車廂cpublic bool Hold(int c, ref int minH, ref int minS, ref LinkStack<int>[] H, int k, int n){//如果沒有可用緩沖鐵軌,則返回false//否則返回true//為車廂c尋找最優的緩沖鐵軌//初始化int BestTrack = 0; //目前最優的鐵軌int BestTop = n + 1; //最優鐵軌上的頭輛車廂int x; //車廂索引//掃描緩沖鐵軌for (int i = 1; i <= k; i++){if (!H[i].IsEmpty()){//鐵軌不為空x = H[i].Top.Data;if (c < x && x < BestTop){BestTop = x;BestTrack = i;}}else{if (BestTrack == 0)BestTrack = i;break;}}if (BestTrack == 0)return false;//沒有可用鐵軌//把車廂c送入緩沖鐵軌 H[BestTrack].Push(c);Console.WriteLine("Move car {0} from input to holding track {1}", c, BestTrack);if (c < minH){minH = c;minS = BestTrack;}return true;}//把車廂從緩沖鐵軌送至出軌處,同時修改minH minSpublic void Output(ref int minH,ref int minS ,ref LinkStack <int>[] H,int k,int n){int c; //車廂索引c = H[minS].Pop();Console.WriteLine("Move car {0} form holding track {1} to output", minH, minS);//通過檢查所有的棧頂,搜索新的minH和minSminH = n + 2;for (int i = 1; i <= k; i++){if (!H[i].IsEmpty() && (c = H[i].Top.Data) < minH){minH = c;minS = i;}}}}class Stack{static void Main(){int[] p = new int[] { 3, 6, 9, 2, 4, 7, 1, 8, 5 };int k = 3;//用順序棧解決火車車廂重排問題TrainArrangwBySeqStack tas = new TrainArrangwBySeqStack();bool results;results = tas.RailRoad(p, p.Length, k);do{if (results == false){Console.WriteLine("need more holding track, please enter additional number:");k = k + Convert.ToInt32(Console.ReadLine());results = tas.RailRoad(p, p.Length, k);}} while (results == false);Console.ReadLine();//用鏈棧解決火車車廂重排問題TrainArrangeByLinkStack ta = new TrainArrangeByLinkStack();bool result;result = ta.RailRoad(p, p.Length, k);do{if (result == false){Console.WriteLine("need more holding track,please enter additional number:");k = k + Convert.ToInt32(Console.ReadLine());result = ta.RailRoad(p, p.Length, k);}} while (result == false);Console.ReadLine();}} }隊列(Queue)是插入操作限定在表的尾部而其他操作限定在表的頭部進行的線性表。把進行插入操作的表尾稱為隊尾(Rear).把進行其他操作的頭部稱為隊頭(Front).
隊列的操作使按照先進先出后進后出的原則進行的。
用一片連續的存儲空間來存儲隊列中的數據元素,稱為順序隊列(Sequence Queue)。類似于順序表,用一維數組來存放隊列中的數據元素。
解決順序隊列的假溢出的方法是將順序隊列看成是首位相接的循環結構,叫循環順序隊列(Circular sequence Queue)。
隊列的另外一種存儲方式是鏈式存儲,稱為鏈隊列(Linked Queue)。通常用單鏈表表示。
Queue using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;namespace DataStructure {/// <summary>/// 隊列接口/// </summary>interface IQueue<T>{void EnQueue(T elem); //入隊列操作T DeQueue(); //出隊列操作T GetFront(); //取對頭元素int GetLength(); //求隊列的長度bool IsEmpty(); //判斷隊列是否為空void Clear(); //清空隊列bool IsFull(); //判斷隊列是否為滿 }/// <summary>/// 銀行隊列接口/// </summary>interface IBankQueue : IQueue<int>{int GetCallnumber(); //獲取服務號碼 }/// <summary>/// 循環順序隊列/// </summary>/// <typeparam name="T"></typeparam>class CSeqQueue<T> : IQueue<T>{private int maxsize; //循環順序隊列的容量private T[] data; //數組,用于存儲循環順序隊列中的數據元素private int front; //指示最近一個已經離開隊列的元素所占有的位置 循環順序隊列的對頭private int rear; //指示最近一個進入隊列的元素的位置 循環順序隊列的隊尾public T this[int index]{get { return data[index]; }set { data[index] = value; }}//容量屬性public int Maxsize{get { return maxsize; }set { maxsize = value; }}//對頭指示器屬性public int Front{get { return front; }set { front = value; }}//隊尾指示器屬性public int Rear{get { return rear; }set { rear = value; }}public CSeqQueue(){}public CSeqQueue(int size){data = new T[size];maxsize = size;front = rear = -1;}//判斷循環順序隊列是否為滿public bool IsFull(){if ((front == -1 && rear == maxsize - 1) || (rear + 1) % maxsize == front)return true;elsereturn false;}//清空循環順序列表public void Clear(){front = rear = -1;}//判斷循環順序隊列是否為空public bool IsEmpty(){if (front == rear)return true;elsereturn false;}//入隊操作public void EnQueue(T elem){if (IsFull()){Console.WriteLine("Queue is Full !");return;}rear = (rear + 1) % maxsize;data[rear] = elem;}//出隊操作public T DeQueue(){if (IsEmpty()){Console.WriteLine("Queue is Empty !");return default(T);}front = (front + 1) % maxsize;return data[front];}//獲取對頭數據元素public T GetFront(){if (IsEmpty()){Console.WriteLine("Queue is Empty !");return default(T);}return data[(front + 1) % maxsize];//front從-1開始 }//求循環順序隊列的長度public int GetLength(){return (rear - front + maxsize) % maxsize;}}/// <summary>/// 鏈隊列結點類/// </summary>/// <typeparam name="T"></typeparam>class QueueNode<T>{private T data; //數據域private QueueNode<T> next; //引用域public QueueNode(T val, QueueNode<T> p){data = val;next = p;}public QueueNode(QueueNode<T> p){next = p;}public QueueNode(T val){data = val;next = null;}public QueueNode(){data = default(T);next = null;}//數據域屬性public T Data{get { return data; }set { data = value; }}//引用域屬性public QueueNode<T> Next{get { return next; }set { next = value; }}}/// <summary>/// 鏈隊列類/// </summary>/// <typeparam name="T"></typeparam>class LinkQueue<T> : IQueue<T>{private QueueNode<T> front; //隊列頭指示器private QueueNode<T> rear; //隊列尾指示器private int size; //隊列結點個數//隊列屬性public QueueNode<T> Front{get { return front; }set { front = value; }}public QueueNode<T> Rear{get { return rear; }set { rear = value; }}public int Size{get { return size; }set { size = value; }}//初始化鏈隊列public LinkQueue(){front = rear = null;size = 0;}public int GetLength(){return size;}public void Clear(){front = rear = null;size = 0;}public bool IsEmpty(){if ((front == rear) && (size == 0))return true;elsereturn false;}//鏈隊列沒有容量限制 返回falsepublic bool IsFull(){return false;}//入隊操作public void EnQueue(T item){QueueNode<T> q = new QueueNode<T>(item);if (IsEmpty()){front = q;rear = q;}else{rear.Next = q;rear = q;}++size;}//出對操作public T DeQueue(){if (IsEmpty()){Console.WriteLine("Queue is Empty !");return default(T);}QueueNode<T> p = front;front = front.Next;if (front == null){rear = null;}--size;return p.Data;}//獲取鏈隊列頭結點的值public T GetFront(){if (IsEmpty()){Console.WriteLine("Queue is Empty !");return default(T);}return front.Data;}}/// <summary>/// 銀行叫號鏈隊列類/// </summary>class LinkBankQueue : LinkQueue<int>, IBankQueue{private int callnumber;public int Callnumber{get { return callnumber; }set { callnumber = value; }}//獲取服務號碼public int GetCallnumber(){if ((IsEmpty()) && callnumber == 0){callnumber = 1;}elsecallnumber++;return callnumber;}}/// <summary>/// 銀行叫號順序隊列類/// </summary>class CSeqBankQueue : CSeqQueue<int>, IBankQueue{private int callnumber; //記錄系統自動產生的新來顧客的服務號碼public int Callnumber{get { return callnumber; }set { callnumber = value; }}public CSeqBankQueue(){}public CSeqBankQueue(int size): base(size){}//獲得服務號碼public int GetCallnumber(){if ((IsEmpty()) && callnumber == 0){callnumber = 1;}else{callnumber++;}return callnumber;}}/// <summary>/// 服務窗口類/// </summary>class ServiceWindow{IBankQueue bankQ;//服務隊列屬性public IBankQueue BankQ{get { return bankQ; }set { bankQ = value; }}public void Service(){while (true){Thread.Sleep(10000);if (!bankQ.IsEmpty()){Console.WriteLine();lock (bankQ){Console.WriteLine("請{0}號到{1}號窗口!", bankQ.DeQueue(), Thread.CurrentThread.Name);}}}}}class Queue{static void Main(){IBankQueue bankQueue = null;Console.WriteLine("請選擇存儲結構的類型:1.順序隊列 2.鏈隊列:");char selectFlag = Convert.ToChar(Console.ReadLine());switch (selectFlag){/*初始化順序隊列*/case '1':int count; //接受循環順序隊列的容量Console.WriteLine("請輸入隊列可容納的人數:");count = Convert.ToInt32(Console.ReadLine());bankQueue = new CSeqBankQueue(count);break;/*初始化鏈隊列*/case '2':bankQueue = new LinkBankQueue();break;}int windowcount = 4; //設置銀行柜臺的服務窗口數 ServiceWindow[] sw = new ServiceWindow[windowcount];Thread[] swt = new Thread[windowcount];for (int i = 0; i < windowcount; i++){sw[i] = new ServiceWindow();sw[i].BankQ = bankQueue;swt[i] = new Thread(new ThreadStart(sw[i].Service));swt[i].Name = "" + (i + 1);swt[i].Start();}while (true){Console.WriteLine("請點擊觸摸屏獲取號碼:");Console.ReadLine();int callnumber;if (!bankQueue.IsFull()){callnumber = bankQueue.GetCallnumber();Console.WriteLine("您的號碼是:{0},您前面有{1}位,請等待!", callnumber, bankQueue.GetLength());bankQueue.EnQueue(callnumber);}elseConsole.WriteLine("現在業務繁忙,請稍后再來!");Console.WriteLine();}}} }注:本文整理自《數據結構(C#語言版)》 清華大學出版社!!!
?
復制搜索 復制搜索 復制搜索 復制搜索轉載于:https://www.cnblogs.com/YuanSong/archive/2012/08/20/2648115.html
總結
以上是生活随笔為你收集整理的C# 数据结构 之 堆栈和队列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ 1195 Mobile phon
- 下一篇: [转]C#算法 一对小兔子一年后长成大兔