亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#數據結構與算法揭秘五 棧和隊列

2020-01-24 03:39:53
字體:
來源:轉載
供稿:網友

這節我們討論了兩種好玩的數據結構,棧和隊列。

老樣子,什么是棧, 所謂的棧是棧(Stack)是操作限定在表的尾端進行的線性表。表尾由于要進行插入、刪除等操作,所以,它具有特殊的含義,把表尾稱為棧頂(Top) ,另一端是固定的,叫棧底(Bottom) 。當棧中沒有數據元素時叫空棧(Empty Stack)。這個類似于送飯的飯盒子,上層放的是紅燒肉,中層放的水煮魚,下層放的雞腿。你要把這些菜取出來,這就引出來了棧的特點先進后出(First in last out)。   具體敘述,加下圖。

棧通常記為:S= (a1,a2,…,an),S是英文單詞stack的第 1 個字母。a1為棧底元素,an為棧頂元素。這n個數據元素按照a1,a2,…,an的順序依次入棧,而出棧的次序相反,an第一個出棧,a1最后一個出棧。所以,棧的操作是按照后進先出(Last In First Out,簡稱LIFO)或先進后出(First In Last Out,簡稱FILO)的原則進行的, 因此, 棧又稱為LIFO表或FILO表。 棧的操作示意圖如圖所示。

棧的形式化定義為:棧(Stack)簡記為 S,是一個二元組,顧定義為S = (D, R)
其中:D 是數據元素的有限集合;
R 是數據元素之間關系的有限集合。

棧的一些基本操作的概述:由于棧只能在棧頂進行操作, 所以棧不能在棧的任意一個元素處插入或刪除元素。因此,棧的操作是線性表操作的一個子集。棧的操作主要包括在棧頂插入元素和刪除元素、取棧頂元素和判斷棧是否為空等等方面的操作。

同樣,我們以 C#語言的泛型接口來表示棧,接口中的方法成員表示基本操作。為表示的方便與簡潔,把泛型棧接口取名為 IStack(實際上,在 C#中沒有泛型接口 IStack<T>, 泛型棧是從 IEnumerable<T>和 ICollection 等接口繼承而來,這一點與線性表有著本質的區別) 。

棧的接口定義源代碼如下所示。

public interface IStack<T> {

//初始條件:棧存在;操作結果:返回棧中數據元素的個數。

int GetLength(); //求棧的長度   偽代碼 index++

//初始條件:棧存在; 操作結果:如果棧為空返回 true,否則返回 false。偽代碼 if(top==null) return true;else return false;

bool IsEmpty(); //判斷棧是否為空

//初始條件:棧存在; 操作結果:使棧為空。偽代碼 top=null;

void Clear(); //清空操作

//初始條件:棧存在; 操作結果:將值為 item 的新的數據元素添加到棧頂,棧發生變化。偽代碼 top=item;index++;

void Push(T item); //入棧操作

//初始條件:棧存在且不為空; 操作結果:將棧頂元素從棧中取出,棧發生變化   偽代碼:return top;index--;

T Pop(); //出棧操作

//初始條件:棧表存在且不為空; 操作結果:返回棧頂元素的值,棧不發生變化。偽代碼 get top;

T GetTop(); //取棧頂元素
}

棧也分為兩種的形式,一種是順序棧,一種是鏈棧。

第一種 順序棧(Sequence Stack):

用一片連續的存儲空間來存儲棧中的數據元素,這樣的棧稱為順序棧(Sequence Stack)。類似于順序表,用一維數組來存放順序棧中的數據元素。棧頂指示器 top 設在數組下標為 0 的端,top 隨著插入和刪除而變化,當棧為空時,top=-1。下圖是順序棧的棧頂指示器 top與棧中數據元素的關系圖。

順序棧類 SeqStack<T>源代碼的實現如下所示。

public class SeqStack<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 SeqStack(int size)
{
data = new T[size];
maxsize = size;
top = -1;
}

//求棧的長度   用頭指針來加一
public int GetLength()
{
return top+1;
}

如圖所示:

//判斷順序棧是否為空

//就是判斷頭指針是否為-1 為就為空 不為就為假

public bool IsEmpty()
{
if (top == -1)
{
return true;
}
else
{
return false;
}
}

具體如下圖所示:

//判斷順序棧是否為滿 或最大尺寸相比較 相等 返回真 不相等返回假
public bool IsFull()
{
if (top == maxsize-1)
{
return true;
}
else
{
return false;
}
}

相應情況,一切盡在圖例中。

 

//入棧 將其放入頂部 top 加加
public void Push(T item)
{

//如果滿了 就不進行添加

if(IsFull())
{
Console.WriteLine("Stack is full");
return;
}
//進行加入到頂部
data[++top] = item;
}

具體情況,一切盡在圖例中

//出棧 進行出棧后 頭指針減減
public T Pop()
{
T tmp = default(T);
if (IsEmpty())
{

Console.WriteLine("Stack is empty");
return tmp;
}

tmp = data[top];
--top;
return tmp;

具體情況,一切盡在圖例中。

//獲取棧頂數據元素 把頭指針指向的元素進行彈出的操作
public T GetTop()
{

//如果是空 就返回一個默認值
if (IsEmpty())
{
Console.WriteLine("Stack is empty!");
return default(T);
}

return data[top];

具體情況,一切盡在圖例中:

}

 


}

}

這就是對順序棧的相應的介紹。

下面,我們就來到了另一種棧――鏈棧的介紹

什么是鏈棧了,所謂鏈棧是棧的另外一種存儲方式是鏈式存儲,這樣的棧稱為鏈棧(Linked Stack)。鏈棧通常用單鏈表來表示,它的實現是單鏈表的簡化。所以,鏈棧結點的結構與單鏈表結點的結構一樣,如圖所示。由于鏈棧的操作只是在一端進行,為了操作方便,把棧頂設在鏈表的頭部,并且不需要頭結點。

鏈棧結點類(Node<T>)源代碼的實現如下: 

public class Node<T>
{
private T data; //數據域
private Node<T> next; //引用域

//構造器
public Node(T val, Node<T> p)
{
data = val;
next = p;
}

//構造器

public Node(Node<T> p)
{
next = p;
}

//構造器
public Node(T val)
{
data = val;
next = null;
}

//構造器
public Node()
{
data = default(T);
next = null;
}

//數據域屬性
public T Data
{
get
{
return data;
}
set
{
data = value;
}
}

//引用域屬性
public Node<T> Next
{
get
{
return next;
}
set
{
next = value;
}
}

}

下圖是鏈棧示意圖。 

把鏈??醋饕粋€泛型類,類名為 LinkStack<T>。LinkStack<T>類中有一個字段 top表示棧頂指示器。由于棧只能訪問棧頂的數據元素,而鏈棧的棧頂指示器又不能指示棧的數據元素的個數。所以,求鏈棧的長度時,必須把棧中的數據元素一個個出棧, 每出棧一個數據元素, 計數器就增加 1, 但這樣會破壞棧的結構。為保留棧中的數據元素, 需把出棧的數據元素先壓入另外一個棧, 計算完長度后,再把數據元素壓入原來的棧。但這種算法的空間復雜度和時間復雜度都很高,所以, 以上兩種算法都不是理想的解決方法。 理想的解決方法是 LinkStack<T>類增設一個字段 num表示鏈棧中結點的個數。

鏈棧類 LinkStack<T>的實現說明如下所示。
public class LinkStack<T> : IStack<T> {
private Node<T> top; //棧頂指示器
private int num; //棧中結點的個數

//棧頂指示器屬性
public Node<T> Top
{
get
{
return top;
}
set
{
top = value;
}
}

//元素個數屬性 進行了計數 
public int Num
{
get
{
return num;
}
set
{
num = value;
}
}

//構造器 進行了函數的初始化
public LinkStack()
{
top = null;
num = 0;
}

//求鏈棧的長度   返回計算的復雜度  此算法的復雜度是O(1)
public int GetLength()
{
return num;
}

//清空鏈棧 進行清空的操作 此算法的復雜度是O(1)
public void Clear()
{
top = null;
num = 0;
}

//判斷鏈棧是否為空   判斷 計數的變量和頭指針是否是空  返回為真  否則 為假  此算法的復雜度是O(n)
public bool IsEmpty()
{
if ((top == null) && (num == 0))
{
return true;
}
else
{
return false;
}
}

//入棧 進行棧內 入棧的操作
public void Push(T item)
{
Node<T> q = new Node<T>(item);

if (top == null)
{
top = q;
}
else

{
q.Next = top;
top = q;
}

++num;
}

//出棧 進行出棧的操作 頭指針相減。此算法的復雜度為1
public T Pop()
{
if (IsEmpty())
{
Console.WriteLine("Stack is empty!");
return default(T);
}

Node<T> p = top;
top = top.Next;
--num;

return p.Data;
}

//獲取棧頂結點的值  返回頭指針的值 此算法的復雜度為一。
public T GetTop()
{
if (IsEmpty())
{
Console.WriteLine("Stack is empty!");
return default(T);
}
return top.Data;
}

 

}

這就是鏈棧的介紹的。還介紹一個棧的明顯的應用,這就是簡易萬能計算器的應用。

我們都知道在使用算符優先文法時必須使用兩個基本棧,數棧(operand stack)和運算符棧(operator stack),來完成計算工作,然而單單使用這兩個棧有一定的局限性,因此在設計時,我引入了第三個棧(op stack),下面我們就來分析一下。

在使用兩個棧時,如果遇到表達式 2-3*/6#,會發生什么呢?

步驟號
數字棧
運算符棧
當前輸入
剩余字符串
說明
1
#
 
2-3*/6#
 
2
#
2
-3*/6#
 
3
2
#
-
3*/6#
 
4
2
# -
3
*/6#
 
5
2 3
# -
*
/6#
 
6
2 3
# - *
/
6#
*>/,運算2*3,-</,push(/)
7
6
# - /
6
#
 
8
6 6
# - /
#
 
/>#,運算6/6,
->#,試圖運算,由于缺少數符,報錯,錯誤定位在減號
9
# -
 
 
 

此時,錯誤信息為:在minus附近可能存在錯誤。但實際上問題出在*或/號附近,這種報錯的定位結果是不能令人滿意的。

于是讓我們看看如果引入第三個棧作符號棧會如何?符號棧的功能是保存所有分析過程中的符號,包括數符和運算符兩種。

步驟號
數字棧
運算符棧
符號棧
當前輸入
剩余字符串
說明
1
#
#
 
2-3*/6#
 
2
#
#
2
-3*/6#
 
3
2
#
# 2
-
3*/6#
 
4
2
# -
# 2 - 
3
*/6#
 
5
2 3
# -
# 2 亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
在线电影欧美日韩一区二区私密| 午夜精品三级视频福利| 欧美日韩国产精品专区| 久久久久一本一区二区青青蜜月| 欧美电影免费观看电视剧大全| 日韩精品中文字幕在线| 国产国产精品人在线视| 91在线播放国产| 欧美激情精品久久久久久大尺度| 日韩欧美主播在线| 国产午夜精品全部视频播放| 日韩电影中文 亚洲精品乱码| 国产精品一区二区三| 国产精品高清在线| 日韩免费看的电影电视剧大全| 亚洲国产精彩中文乱码av在线播放| 这里只有视频精品| 日韩在线观看高清| 精品亚洲夜色av98在线观看| 亚洲精品电影网| 日韩大片免费观看视频播放| 91精品国产高清久久久久久| 久久久久久久色| 中文字幕亚洲国产| 中文字幕欧美日韩精品| 在线观看91久久久久久| 日韩在线中文字幕| 国产欧美久久一区二区| 精品香蕉一区二区三区| 国产精品视频久久| 国产精品永久免费| 欧美成人黄色小视频| 亚洲精品一区二三区不卡| 日本高清不卡在线| 中文字幕日韩免费视频| 欧美激情一区二区三区在线视频观看| 国产91精品最新在线播放| 一区二区三区视频观看| 美日韩精品免费观看视频| 国内免费精品永久在线视频| 日韩在线激情视频| 韩国一区二区电影| 91久久精品国产91久久| 亚洲精品影视在线观看| 伊人男人综合视频网| 亚洲在线一区二区| 最近的2019中文字幕免费一页| 国内精品久久久久影院优| 日韩亚洲精品视频| 国产乱人伦真实精品视频| 97在线观看视频国产| 97超级碰在线看视频免费在线看| 久久人人爽亚洲精品天堂| 欧美日韩爱爱视频| 亚洲一区二区三区毛片| 日韩精品视频三区| 国产日产久久高清欧美一区| 91精品国产一区| 黑人巨大精品欧美一区二区三区| 亚洲精品99久久久久| 理论片在线不卡免费观看| 91国产一区在线| 久久天堂av综合合色| 欧美精品激情视频| 国产成人中文字幕| 中文字幕日韩在线观看| 久久久久久国产精品久久| 亚洲精品国产品国语在线| 精品美女久久久久久免费| 欧美精品日韩三级| 一本一本久久a久久精品牛牛影视| 亚洲高清免费观看高清完整版| 精品动漫一区二区三区| 日韩av免费在线看| 九九热r在线视频精品| 色狠狠av一区二区三区香蕉蜜桃| 精品国产乱码久久久久酒店| 国产suv精品一区二区| 精品日韩美女的视频高清| 欧美国产日韩在线| 亚洲午夜精品久久久久久久久久久久| 国内精品国产三级国产在线专| 欧美日韩中文字幕综合视频| 亚洲国内高清视频| 日韩av快播网址| 亚洲精品视频在线播放| 国产一级揄自揄精品视频| 亚洲免费中文字幕| 91久久久久久久| 国产人妖伪娘一区91| 久久免费视频这里只有精品| 亚洲精品一区二区在线| 国产精品永久免费观看| 欧美日韩福利在线观看| 日韩国产欧美区| 亚洲欧美在线一区| 在线免费观看羞羞视频一区二区| 久久精品亚洲94久久精品| 高清欧美电影在线| 日韩中文字幕第一页| 日韩在线视频线视频免费网站| 日韩视频免费中文字幕| 国产+人+亚洲| 亚洲精品97久久| 精品久久久久久久久久| 欧美成人精品一区二区| 久久久久在线观看| 国产精品永久免费| 日韩精品中文字幕在线观看| 色偷偷9999www| 久久久免费电影| 日韩欧美在线视频观看| 久久全球大尺度高清视频| 国产亚洲aⅴaaaaaa毛片| 色妞在线综合亚洲欧美| 亚洲xxxxx| 国产精品视频一| 欧美日韩电影在线观看| 国产精品久久久久免费a∨大胸| 91久久精品国产91久久| 亚洲最大成人在线| 日本人成精品视频在线| 91久久久久久国产精品| 欧美国产日本在线| 奇门遁甲1982国语版免费观看高清| 亚洲最新av网址| 日本高清不卡在线| 在线观看国产精品日韩av| 51久久精品夜色国产麻豆| 8x海外华人永久免费日韩内陆视频| 精品视频在线播放| 亚洲18私人小影院| 亚洲国产日韩欧美综合久久| 亚洲欧美变态国产另类| 亚洲国产日韩精品在线| 国产91|九色| 日韩av一区在线观看| 久久久久日韩精品久久久男男| 国产剧情日韩欧美| 亚洲精品中文字| 欧美激情综合色| 国产精品91久久久| 最新69国产成人精品视频免费| 亚洲毛片一区二区| 日韩中文字幕精品| 亚洲一区二区三区777| 538国产精品一区二区免费视频| 欧美成人免费播放| 久久久久久97| 成人激情视频免费在线| 亚洲欧美日韩高清| 欧美福利小视频| 国产69久久精品成人| 久久久久久高潮国产精品视| 成人av资源在线播放| 51ⅴ精品国产91久久久久久| 国产精品91在线| 国产成人精品久久二区二区91| 久久久久久久av| 久热在线中文字幕色999舞| 97超碰国产精品女人人人爽| 91精品国产一区| 91精品久久久久久久久久久久久| 国产成人aa精品一区在线播放|