今天學習c#當中實現棧,學過C#的都知道,c#本身已經寫好 了棧和隊列,我們可以直接用,這里自己實現以下,就是為了更深刻的理解。
首先說明線性表,棧、隊列他們的數據元素以及數據元素之間的邏輯關系實際上都是相同的,不同的是線性表的操作不受限制,而棧和隊列則受限制,棧的操作只能在一端進行,隊列的扎入在一端進行,別的操作在另一端進行。
我們通常把表尾看做是棧頂,另一端是固定的叫棧底,棧中沒有數據時我們稱為空棧。
實現棧的代碼

public class SeqStack<T> { private int maxSize;// 順序棧的容量 public int MaxSize { get { return maxSize; } set { maxSize = value; } } public T[] data; // 數組,用於存儲順序棧中的數據元素 private int top; // 指示順序棧的棧頂 public int Top { get { return top; } } //構造器 public SeqStack(int size) { data = new T[size]; maxSize = size; top = -1; } // 定義索引器 public T this[int index] { get { return data[index]; } set { data[index] = value; } } // 由於數組是 0 基數組,即數組的最小索引為 0,所以,順序棧的長度就是數組中最后一個元素的索引 top 加 1 public int GetLength() { return top + 1; } public bool IsEmpty() { if ( -1 == top ) { return true; } return false; } public bool IsFull() { if ( top == maxSize - 1 ) { return true; } return false; } public void Push( T item) { if ( IsFull() ) { Console.WriteLine("棧已滿,無法壓棧"); return; } data[++top] = item; } public T Pop() { if ( IsEmpty() ) { Console.WriteLine("棧為空,無法彈棧"); return default(T); } return data[top--]; } public T Peek() { if ( IsEmpty() ) { Console.WriteLine("棧為空,無法彈棧"); return default(T); } return data[top]; } } // 鏈表實現棧 public class LinkStack<T> { private Node<T> top; // 棧頂指示器 internal Node<T> Top { get { return top; } set { top = value; } } private int nCount; //棧中結點的個數 public int NCount { get { return nCount; } set { nCount = value; } } public LinkStack() { top = null; nCount = 0; } public int GetLength() { return nCount; } public bool IsEmpty() { if ( (top == null) && (0 == nCount)) { return true; } return false; } public void Push(T item) { Node<T> p = new Node<T>(item); if ( top == null ) { top = p; } else { p.Next = top; top = p; } nCount++; } public T Pop() { if ( IsEmpty() ) { return default(T); } Node<T> p = top; top = top.Next; --nCount; return p.Data; } public T Peek() { if ( IsEmpty() ) { return default(T); } return top.Data; } }
棧的引用舉例
// 十進制數N轉換為八進制數 public static void Conversion(int n) { LinkStack<int> stack = new LinkStack<int>(); while ( n > 0 ) { stack.Push(n % 8); n = n >> 3; } while ( !stack.IsEmpty() ) { Console.WriteLine( "{0}",stack.Pop() ); } }
迷宮問題的應用
/* 隨機生成一個10*10的迷宮(可以用*表示起點,#表示終點,0代表不可以通過,1代表可以通過),假如[0,0] 為入口 [9,9] 為出口。 (1)在控制台上顯示該迷宮 (2)利用結構求解該迷宮是否能抵達出口(入口與出口是否聯通)。 (3)如能抵達出口,輸出從入口到出口的行走路徑。 */ // 我們首先創建一個Point類,來存放每個點的坐標,然后定義一個棧,來存放當前路徑所經過的點 class Point { public const int m = 10; public int x; public int y; public Point(int _x, int _y) { x = _x; y = _y; } // 走迷宮 public void GoPath( int[,] maze ) { Point start = new Point(1, 1);// 迷宮起始點的坐標 Point end = new Point(m-2, m - 2);// 迷宮終點的坐標 int x = 1;// 初始點橫坐標 int y = 1;// 初始點縱坐標 Stack<Point> path = new Stack<Point>();// 用棧來存儲路徑所通過點的坐標 path.Push(start);// 將迷宮入口點的坐標壓棧 do { bool flag = false; // 向右->下->左->上的順序探測是否有通路 if ( 0 == maze[x + 1, y] ) { maze[x + 1, y] = 2;// 有通過的路徑點 ,避免以后重復走 path.Push(new Point(x + 1, y));// 把該點保存 flag = true; } // bottom else if ( 0 == maze[x, y + 1] ) { maze[x, y + 1] = 2; path.Push(new Point(x, y + 1)); flag = true; } // left else if (0 == maze[x - 1, y]) { maze[x - 1, y] = 2; path.Push(new Point(x - 1, y)); flag = true; } // top else if ( 0 == maze[ x, y + 1 ]) { maze[x, y + 1] = 2; path.Push(new Point(x, y + 1)); flag = true; } /* 如果四周都沒有通路, 則將點從路徑中刪除,即彈出棧頂元素。 如果此時棧為空,則表明彈出的是入口點,即此迷宮無解。 否則后退一個點重新探測。 */ if (!flag) { path.Pop(); if ( 0 == path.Count ) { Console.WriteLine(" 沒有找到可以走出此迷宮的路徑 "); break; } } // 讀取棧頂元素並判斷其是否是出口 Point peek = path.Peek(); if (peek.x == end.x && peek.y == end.y ) { Console.WriteLine( "已經找到出口" + path ); break; } // 如果棧頂元素不是出口,則以該元素為起點繼續進行探測 start = peek; x = start.x; y = start.y; } while ( path.Count > 0 ); } }
// C#2.0提供了泛型的Stack<T>類,該類繼承 //了 IEnumerable<T>、ICollection 和 IEnumerable 接口。下面的程序說明了泛型 //Stack<T>類的主要方法,並對在我們自定義的棧類中沒有出現的成員方法進行了 //注釋,關於泛型Stack<T>類的更具體的信息,讀者可參考.NET Framework 的有 //關書籍。 public class Stack<T> : IEnumerable<T>, ICollection, IEnumerable { public Stack(); public Stack(int capacity); public int Count {get;} public void Clear(); //確定某元素是否在Stack<T>中, //如果在Stack<T>中找到item,則為true;否則為false。 public bool Contains(T item); //從指定數組索引開始將Stack<T>復制到現有一維Array中。 public void CopyTo(T[] array, int arrayIndex); //返回位於Stack<T>頂部的對象但不將其移除。 public T Peek(); public T Pop(); public void Push(T item); //將Stack<T>復制到新數組中。 public T[] ToArray(); //如果元素數小於當前容量的90%, //將容量設置為Stack<T>中的實際元素數。 public void TrimExcess(); }
好了暫時就寫這么多吧