C語言示例代碼講解棧與隊列
上文詳細的講解瞭順序表與鏈表的實現,相信大傢在順序表與鏈表的指基礎上,很容易就能學會站和隊列,廢話不多說,我們馬上開始!
棧
棧的定義
棧是一種線性表,但限定這種線性表隻能在某一端進行插入和刪除操作
假設棧 【s = (a1,a2,……,an) 】,a1為棧底元素,an為棧頂元素。由於棧隻能在棧頂進行插入和刪除操作,所以進棧次序依次為【a1,a2,……,an】,出棧次序為【an,……,a2,a1】
由此可見:棧的操作特性可以明顯地概括為後進先出
棧類似於線性表,它也有兩種對應的存儲方式分別為順序棧和鏈棧。
順序棧
順序棧的定義
Q:什麼是順序棧?
A:采用順序存儲的棧成為順序棧。它利用一組地址連續的存儲單位存放自棧底到棧頂的數據元素,同時附設一個指針(top)來指示當前棧頂的位置。
棧的順序存儲類型可描述為
#define MaxSize 100 //定義棧中元素的最大個數 typedef struct { SElemtype *base; //棧底指針 SElemtype *top; //棧頂指針 int stacksize //棧可用的最大容量 }SqStack;
順序棧的初始化
Q:什麼是順序棧的初始化?
A:順序棧的初始化操作就是為順序棧動態分配一個最大容量為 MaxSize 的數組空間。
實現原理
- 為順序棧動態分配一個最大容量為MAXSIZE的數組
- 棧頂指針top初始為base,表示棧為空
- stacksize置為棧的最大容量MaxSize
💬 代碼演示
Status InitStack(SqStack &S) {//構造一個空棧S S. base=new SElemType[MaxSize]; //為順序棧動態分配一個最大容量為MAxsini if(!S. base) exit(OVERFLOW); //存儲分配失敗 S. top=S. base; //top初始為base,空棧 S. stacksize=MaxSize; //stacksize置為棧的最大容量MaxSize return OK; }
順序棧的入棧
Q:什麼是順序棧的入棧?
A:入棧操作是將新元素進入棧
🔺實現原理
- 判斷棧是否滿瞭,若滿瞭返回ERROR
- 將新元素壓入棧,棧頂指針加1
💬 代碼演示
Status Push(SqStack &S,SElemType e) {//插入元素e為新的棧頂元素 if(S.top-S.base==S:stacksize) return ERROR;//棧滿 *S. top++=e; //元素e壓入棧頂,棧頂指針加1 return OK; }
順序棧的出棧
Q:什麼是順序棧的出棧?
A:出棧操作是將棧頂元素刪除
🔺實現原理
- 判斷棧是否空,若空則返回ERROR
- 棧頂指針減1,棧頂元素出棧
💬 代碼演示
Status Pop(SqStack &S,SElemType &e) (//刪除S的棧頂元素,用e返回其值 if(S.top==S.base) return ERROR;//棧頂 指針減1,將棧頂元素賦給e //棧頂指針減1,將棧頂元素賦給e e=*--S.top; return OK; )
取順序棧的棧頂元素
Q:如何取順序棧的棧頂元素?
A:當棧非空時,此操作返回當前棧頂元素的值,棧頂指針保持不變。
🔺實現原理
- 判斷棧是否空
- 返回棧頂元素的值,棧頂指針不變
💬 代碼演示
SElemType GetTop (SqStack S) {//返回s的棧頂元素,不修改棧頂指針 if(S.top!=S.base) //棧非空 return*(S.top-1); //返回棧頂元素的值,棧頂指針不變 )
鏈棧
采用鏈式存儲的棧稱為鏈棧。鏈棧的優點是便於多個棧共享存儲空間和提高其效率,且不存在棧滿上溢的情況。通常采用單鏈表實現。
棧的順序存儲類型可描述為
typedef struct Linknode { ElemType data; //數據域 struct Linknode *next; //指針域 } *LiStack;
采用鏈式存儲,便於結點的插入與刪除。鏈棧的操作與鏈表類似,入棧和出棧的操作都在鏈表的表頭進行。
隊列
隊列的定義
隊列是一種線性表,但限定這種線性表隻能在表的一端進行插入,在另一端進行刪除。允許刪除的一端為隊頭,又稱為隊首,允許插入的一端為隊尾
隊列與生活中的排隊一樣,最早排隊的最先離開,隊列的操作特性可以明顯地概括為先進先出
隊列有兩種存儲表示,分別為順序表示與鏈式表示
隊列的順序表達與實現
隊列順序存儲結構
和順序棧相類似,在隊列的順序存儲結構中,除瞭用一組地址連續的存儲單元依次列頭到隊列尾的元素之外。還需附設兩個整型變量【front】和【rear】分別指示隊列頭元素及隊間的位置(後面分別稱為頭指針和尾指針)。
隊列的順序存儲結構表示如下:
#define MAXSIZE 100 //隊列容量 typedef struct { ElemType *base; //存儲空間 int front,rear; //隊首,隊尾 }SqQueue ;
假溢出
圖(1)所示為隊列的初始狀況。此時有【front == rear == 0】 成立。該條件可以作為隊列判空的條件。
但是【rear == MAXSIZE】不能作為隊列滿的條件。為什麼呢?
圖(4)隊列中隻有一個元素,仍滿足該條件。這時入隊出現上溢出。但是這種溢出並不是真正的溢出,在隊列中依然存在可以存放元素的空位置,所以是一種假溢出。
如何解決循環鏈表的這一缺點呢?
循環隊列
Q:什麼是循環隊列?
A:將順序隊列臆造成一個環狀的空間,即把存儲隊列元素的表從邏輯上視為一個環,稱為循環隊列。
循環隊列的初始化
Q:什麼是循環隊列的初始化?
A:循環隊列的初始化就是動態分配一個預定義大小為 MAXSIZE 的數組空間
🔺實現原理
- 為隊列動態分配一個最大容量為MAXSIZE的數組空間
- base指向數組空間的首地址
- 頭指針與尾指針置為零,表示隊列為空
💬 代碼演示
Status InitQueue ( SqQueue &Q ) { Q.base=new ElemType[MAXSIZE]; if(!Q.base) return OVERFLOW; Q.front=Q.rear=0; return OK; }
循環隊列的入隊
Q:什麼是循環隊列的入隊?
A:入隊操作是指在隊尾插入一個新的元素
🔺實現原理
- 判斷隊列是否滿
- 滿瞭返回ERROR
- 將新元素插入隊尾
- 隊尾指針加一
💬 代碼演示
Status EnQueue(SqQueue &Q,ElemType e) { if((Q.rear+1)%MAXSIZE==Q.front) //判滿 return ERROR; Q.base[Q.rear]=e; Q.rear=(Q.rear+1)%MAXSIZE; return OK; }
循環隊列的出隊
Q:什麼是循環隊列的出隊?
A:出隊操作是刪除隊頭元素
🔺實現原理
- 判斷隊列是否為空
- 為空返回ERROR
- 保留隊頭元素
- 隊頭指針加一
💬 代碼演示
Status DeQueue(SqQueue &Q, ElemType &e) { if( Q.rear==Q.front ) return ERROR; //判空 e = Q.base[Q.front]; Q.front = (Q.front+1)%MAXSIZE; return OK; }
鏈隊列
Q:什麼是鏈隊列?
A:隊列的鏈式表示稱為鏈隊列。它實際上是一個同時帶有隊頭指針和隊尾指針的單鏈表,頭指針指向對頭結點,尾指針指向隊尾結點。
隊列的鏈式存儲如圖:
隊列的鏈式存儲類型可描述為:
typedef struct Qnode { ElemType data; struct QNode * next; }Qnode,*QueuePtr; //結點 typedef struct { QueuePtr front; QueuePtr rear; }LinkQueue; //鏈隊
鏈棧的初始化
Q:什麼是鏈隊列的初始化?
A:鏈棧的初始化操作就是構建一個隻有頭結點的空隊。
🔺實現原理
- 生成新結點作為頭結點
- 隊頭指針和隊尾指針指向該結點
- 頭指針的指針域置空
💬 代碼演示
Status InitQueue(LinkQueue &Q) { Q.front=Q.rear=new QNode; p->next=NULL; return OK; }
鏈棧的入隊
🔺實現原理
- 為入隊元素分配結點空間,用指針p指向
- 將新結點數據域置為e
- 將新結點插入到隊尾
- 修改隊尾指針為p
💬 代碼演示
Status EnQueue(LinkQueue &Q,ElemType e) { p=new QNode; //為入隊元素分配結點空間,用指針p指向 p->data=e; //將新結點數據域置為e p->next=NULL; Q.rear->next=p; //將新結點插入到隊尾 Q.rear=p; //修改隊尾指針為p return OK; }
鏈棧的出隊
🔺實現原理
- 判斷是否為空,為空返回ERROR
- 保留頭元素空間,以備釋放
- 修改頭指針的指針域,指向下一結點
- 判斷出隊元素是否是最後一個元素,若是,將隊尾指針重新賦值,指向頭結點
- 釋放原隊頭元素的空間
💬 代碼演示
Status DeQueue(LinkQueue &Q,ElemType &e) { if(Q.front==Q.rear) //若隊列為空,返回ERROR return ERROR; QNode *p=Q.front->next; //保留頭元素空間,以備釋放 Q.front->next=p->next; //修改頭指針的指針域,指向下一結點 if(Q.rear==p) //判斷出隊元素是否是最後一個元素,若是,將隊尾指針重新賦值,指向頭結點 Q.rear=Q.front; delete p; //釋放原隊頭元素的空間 return OK; }
到此這篇關於C語言示例代碼講解棧與隊列的文章就介紹到這瞭,更多相關C語言棧與隊列內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!