標籤:
3.1 比較線性表、棧和隊列這三種資料結構的相同點和不同點。
棧(Stack)是限定只能在表的一端進行插入和刪除操作的線性表。
隊列(Queue)是限定只能在表的一端進行插入和在另一端進行刪除操作的線性表。
從"資料結構"的角度看,它們都是線性結構,即資料元素之間的關係相同。但它們是完全不同的資料類型。除了它們各自的基本操作集不同外,主要區別是對插入和刪除操作的"限定"。
棧和隊列是在程式設計中被廣泛使用的兩種線性資料結構,它們的特點在於基本操作的特殊性,棧必須按"後進先出"的規則進行操作,而隊列必須按"先進先出"的規則進行操作。和線性表相比,它們的插入和刪除操作受更多的約束和限定,故又稱為限定性的線性表結構。
3.2 如果進棧的元素序列為1,2,3,4,則可能得到的出棧序列有多少種?寫出全部的可能序列。
首先這是個卡特蘭數,有2n個人排成一隊進入劇場。入場費5元。其中只有n個人有一張5元鈔票,另外n人只有10元鈔票,劇院無其它鈔票可找零,問有多少中方法使得只要有10元的人買票,售票處就有5元的鈔票找零?(將持5元者到達視作將5元入棧,持10元者到達視作使棧中某5元出棧)。
對於這個例子,劇院要想總有零錢可找,那麼目前進入劇院的人數中,揣著10元鈔票的人數必須少於等於揣著5元鈔票的,不然肯定在某個人那出現沒零錢找的情況。
現在回到正題上來對於一個給定入棧序列,怎麼求它的出棧序列呢?
我們可以把入棧記為1,出棧記為0.那麼首碼子序列中1的個數必須大於等於0的個數,即入棧次數要大於等於出棧次數,如1 1 0 1 0 0,它的任意首碼序列中1的個數是大於等於0的個數的。
我們來看個例子:對於1 2 3這個入棧序列,1 1 0 1 0 0就是一個入棧出棧序列,第一個1代表元素1入棧,然後第二個1代表元素2入棧,然後第三個是0,代表出棧,即元素2出棧,然後第四個是1,代表元素3入棧,然後第五個是0,代表出棧,即元素3出棧,然後第六個是0,代表元素1出棧。最後1 1 0 1 0 0就代表了出棧序列2 3 1。
那麼現在的問題就轉換為如何求出所有合格0 1序列了。其實這和以下問題相同:給定括弧對數,輸出所有符合要求的序列。如2對括弧,輸出有()()或者(())兩種。1可以看成‘(‘,0可以看成‘)’。
卡特蘭數
首先是卡特蘭數的定義:令h(0)=1,h(1)=1,catalan數滿足遞推式:
h(n)= h(0)*h(n-1)+h(1)*h(n-2) + … + h(n-1)h(0) (n>=2)。
可以根據上面的遞推公式,寫出遞迴的計算方案。
public static int Catalan(int n) { int nCount = 0; if ( n < 0 ) { return 0; } if ( 0 == n || 1 == n ) { return 1; } for (int i = 0; i < n; ++i ) { nCount += Catalan(i) * Catalan(n - i - 1); } return nCount; }
3.3 如果進棧的元素序列為A,B,C,D,E,F,能否得到D,C,E,F,A,B和A,C,E,D,B,F的出棧序列?並說明為什麼不能得到或如何得到。
D,C,E,F,A,B 不能得到,把A 和B的位置換一下可以
A,C,E,D,B,F 可以。A進棧A出棧 B進,C進,C出,D進E進,E出,D出,B出,F進F出
3.4 寫出例題3-3中的precede函數和Operate函數。
3.5 寫一演算法將一順序棧的元素依次取出,並列印元素值。
將棧的元素倒置唄,我們考慮將棧元素彈出後放入另一個棧,然後輸出
// 寫一演算法將一順序棧的元素依次取出,並列印元素值。 public static void ReverseStack(int _n) { if ( _n < 0 ) { return; } SeqStack<int> stack = new SeqStack<int>(_n); SeqStack<int> revStack = new SeqStack<int>(_n); for (int i = 0; i < _n; ++i) { stack.Push(i+1); } for (int i = 0; i < _n; ++i ) { revStack.Push(stack.Pop()); } for (int i = 0; i < _n; ++i) { Console.WriteLine("棧的元素依次為" + revStack.Pop()); } }
3.6 在順序隊列中,什麼叫真溢出?什麼叫假溢出?為什麼順序隊列通常都採用迴圈順序隊列結構?
當有資料元素入隊時,隊尾指標rear加1,當有資料元素出隊時,隊頭指標front加1。當front=rear時,表示隊列為空白,隊尾指標rear到達數組的上限處而front為-1時,隊列為滿。
如再有一個資料元素入隊就會出現溢出。但事實上隊列中並未滿,還有空閑空間,把這種現象稱為“假溢出”。這是由於隊列“隊尾入隊頭出”的操作原則造成的。解決假溢出的方法是將順序隊列看成是首尾相接的迴圈結構,頭尾指標的關係不變,這種隊列叫迴圈順序隊列。
//求迴圈順序隊列的長度public int GetLength() { return (rear-front+maxsize) % maxsize; } //清空迴圈順序隊列public void Clear() { front = rear = -1; } //判斷迴圈順序隊列是否為空白public bool IsEmpty() { if (front == rear) { return true; } else { return false; } } //判斷迴圈順序隊列是否為滿public bool IsFull() { if ((rear + 1) % maxsize==front) { return true; } else { return false; } } View Code
3.7 寫一演算法將一鏈隊列的元素依次取出,並列印元素值。
public static void PrintLinkQueue(int _n) { LinkQueue<int> queue = new LinkQueue<int>(); for (int i = 0; i < _n; ++i) { queue.Enqueue(i + 1); Console.WriteLine("隊列的元素依次為" + queue.Dqueue()); } }
3.8 將例題3-4用鏈隊列和順序隊列實現,並能處理輸入的字元不是大小寫
英文字元的情況。
好了就寫到這裡,至於優先順序的問題,以後有時間再說
c#棧和隊列習題