C#提供了棧和隊列,我們自己也可以嘗試簡單實現。
而且這可以作為一個很好的面試題,主要考察c#基礎、類的設計以及數據結構。根據不同的職位需求可以考察選擇不同的考察難度和角度。4年前我第一次參加面試並進現在的公司,職位基本是公司的最低崗位了。當時面的題目就是:實現一個棧。
簡單的實現如下(考慮到順序結構實現隊列比較麻煩,采用鏈式結構):
PS:感謝@LoveZmJ的提醒,下面的代碼有個bug,對Test有興趣的人可以先不要看評論,玩玩“大家來找茬”~~
首先是結點類的實現:
1 // 結點類 2 // 注意應該使用泛型 3 public class MyNode<T> 4 { 5 // 存儲的數據 6 public T Data 7 { 8 get { return _data; } 9 set { _data = value; } 10 } 11 12 // 指向下一個結點 13 public MyNode<T> next { get { return _next; } set { _next = value; } } 14 15 //構造函數,不提供無參版本 16 public MyNode(T data) 17 { 18 _data = data; 19 _next = null; 20 } 21 22 // 私有字段 23 private T _data; 24 private MyNode<T> _next; 25 }
然后抽象一個簡單的父類:
1 // 為棧和隊列提取一些通用的成員,抽象出一個父類,此處用接口還是抽象函數? 2 // 在C#中Stack和Queue繼承自兩個接口:IEnumerable<T>, ICollection 3 // 但是作為簡單的實現(特別是作為面試題答案),還是寫成抽象類比較好,原因有二: 4 // 1. 可以在抽象類中實現一些通用方法,子類只需要繼承就可以直接用,可以簡化代碼 5 // 2. 抽象出來的父類,和子類Stack、Queue可以看做“is-a”的關系。 6 // 當然也可以是非抽象的普通類,但是處於“不能實例化”的考慮,應該是抽象的 7 // 注意使用泛型 8 public abstract class AbstactList<T> 9 { 10 // 頭結點,其后才是第一個結點 11 // 注意應該是protected,對外是不可見的 12 protected MyNode<T> Header { get; set; } 13 // 尾結點,即是最后一個結點 14 protected MyNode<T> Tail { get; set; } 15 // 當前結點個數,注意是只讀屬性 16 public int NoteCount { get { return _noteCount; } } 17 18 // 構造函數,初始化頭結點和結點個數 19 public AbstactList() 20 { 21 // 注意此處default(T)的使用 22 Header = new MyNode<T>(default(T)); 23 Tail = Header; 24 _noteCount = 0; 25 } 26 27 // “出的操作”,對於棧和隊列都是一樣的,所以可以寫在父類里 28 // 注意應該從“頭”端出,時間復雜度為O(1) 29 // 如果從“尾”端出,則會造成時間復雜度為O(n) 30 protected T Out() 31 { 32 // 注意判空,只要一個條件就可以了,將所有的條件都寫在這里可以有利於在測試的時候檢測出bug 33 if (Header.next == null && _noteCount == 0 && NoteCount == 0 && IsEmpty()) 34 { 35 throw new InvalidOperationException("Is empty!"); 36 } 37 38 MyNode<T> outNode = Header.next; 39 Header.next = Header.next.next; 40 _noteCount--; 41 return outNode.Data; 42 } 43 44 // 判空 45 public bool IsEmpty() 46 { 47 return _noteCount == 0 ? true : false; 48 } 49 50 // 對於“出”的操作,棧和隊列是有區別的,所以申明成抽象方法 51 // 到子類中去具體實現 52 protected abstract void In(T NodeData); 53 54 // 子類中還要用到,所以是Protected 55 protected int _noteCount; 56 }
棧的具體實現:
1 // 棧的實現,繼承自抽象類 2 public class MyStack<T> : AbstactList<T> 3 { 4 // 實現“進”的方法,在“頭”端 5 // 由於實現抽象類方法的當前方法默認是虛的,所以無法設為private 6 protected override void In(T NodeData) 7 { 8 MyNode<T> Node = new MyNode<T>(NodeData); 9 Node.next = Header.next; 10 Header.next = Node; 11 _noteCount++; 12 } 13 14 // 進棧,只是將操作改個名字 15 public void Push(T NodeData) 16 { 17 In(NodeData); 18 } 19 20 // 出棧,只是將操作改個名字 21 public T Pop() 22 { 23 return Out(); 24 } 25 }
隊列的實現:
1 // 隊列的實現,繼承自抽象類 2 public class MyQueue<T> : AbstactList<T> 3 { 4 // 實現“進”的方法,在“尾”端 5 // 由於實現抽象類方法的當前方法默認是虛的,所以無法設為private 6 protected override void In(T NodeNode) 7 { 8 MyNode<T> Node = new MyNode<T>(NodeNode); 9 Tail.next = Node; 10 Tail = Node; 11 _noteCount++; 12 } 13 14 public void EnQue(T NodeData) 15 { 16 In(NodeData); 17 } 18 19 public T DeQue() 20 { 21 return Out(); 22 } 23 }
單元測試:

1 [TestClass] 2 public class UnitTest1 3 { 4 [TestMethod] 5 public void StackTest() 6 { 7 MyStack<char> charStack = new MyStack<char>(); 8 Assert.IsTrue(charStack.IsEmpty()); 9 charStack.Push('a'); 10 Assert.IsFalse(charStack.IsEmpty()); 11 charStack.Push('b'); 12 Assert.AreEqual(charStack.Pop(), 'b'); 13 charStack.Push('c'); 14 Assert.AreEqual(charStack.NoteCount,2); 15 Assert.AreEqual(charStack.Pop(), 'c'); 16 Assert.AreEqual(charStack.Pop(), 'a'); 17 Assert.IsTrue(charStack.IsEmpty()); 18 19 try 20 { 21 charStack.Pop(); 22 } 23 catch (Exception ex) 24 { 25 Assert.IsInstanceOfType(ex,typeof(InvalidOperationException)); 26 } 27 } 28 29 [TestMethod] 30 public void QueueTest() 31 { 32 MyQueue<int> intQueue = new MyQueue<int>(); 33 Assert.IsTrue(intQueue.IsEmpty()); 34 intQueue.EnQue(1); 35 intQueue.EnQue(2); 36 Assert.AreEqual(intQueue.DeQue(), 1); 37 intQueue.EnQue(3); 38 Assert.AreEqual(intQueue.NoteCount,2); 39 Assert.AreEqual(intQueue.DeQue(), 2); 40 Assert.AreEqual(intQueue.DeQue(), 3); 41 Assert.IsTrue(intQueue.IsEmpty()); 42 43 try 44 { 45 intQueue.DeQue(); 46 } 47 catch (Exception ex) 48 { 49 Assert.IsInstanceOfType(ex, typeof(InvalidOperationException)); 50 } 51 } 52 }
后記:
作為更高難度,還可以加一個要求:實現Sort方法。由於使用的泛型,因此這應該是一個通用的排序方法,有兩種方法可以實現:接口和委托,以后再寫。