數據結構:順序棧的實現
1、快速開始
棧是一種遵循元素后進(Push)先出(Pop)規則的線性表,即最后加入的元素最先出來,它的實現可以用數組或者鏈表。
它的特點如下:
- 后入先出,先入后出。
- 除了頭尾節點之外,每一個元素有一個前驅,有一個后繼。
2、實現棧
我們已經說過了,棧是一種線性表,故其底層是基於數組或者鏈表的。那么,我們的重點是維護一種規則,即后進先出。
我們始終要有一個變量L來記錄最后一個元素的位置:
- 當壓入時,將新元素插入到L位置之后,然后更新L,即L+1.
- 當彈出時,將L位置元素進行刪除,然后更新L,即L-1。
也正是因為,我們使用的是線性表,正好可以利用其尺寸來表示L,即線性表的大小可以表示最后一個元素的位置。
2.1、棧的實現
class MyStack { private List<Integer> data; // 存儲元素 public MyStack() { data = new ArrayList<>(); } /**插入一個元素到棧中. */ public void push(int x) { data.add(x); } /**檢查是否為空 */ public boolean isEmpty() { return data.isEmpty(); } /**到達棧頂. */ public int top() { return data.get(data.size() - 1); } /** 刪除一個元素. 操作成功返回true. */ public boolean pop() { if (isEmpty()) { return false; } data.remove(data.size() - 1); return true; } };
3、C語言版本實現
3.1、對棧的結構定義:
typedef struct { int *base; int *top; int stacksize; }SqStack;
說明:
1.base表示棧底指針,在判斷出棧、初始化和重新分配空間的時候需要用到。
2.top表示棧頂指針,是棧最關鍵和核心的組成,入棧時top向上移動,出棧時top向下移動。
3.此處的stacksize並不表示當前的棧中的元素數量,而是表示棧的容量,也就是能裝多少個元素。
3.2、初始化棧:
int initStack(SqSatck *S) { S->base=(int*)malloc(100*sizeof(int)); if(!S) return 0; //0代表操作失敗 S->top=S->base; stacksize=100; return 1; //1代表操作完成 }
說明:
1.順序棧初始化無非就是給棧分配連續的內存空間,base是棧底指針,在上面提到過,它用來指示一段連續的內存空間的首地址,也就是用來初始化。
2.分配空間不意味着一定會有那么多空間,所以判斷也不可缺少。
3.分配空間后,base和top的地址應該一致,此時top還沒有移動。
3.3、壓棧
int push(SqStack * S,int elem) { if(S->top-S->base>=S->stacksize) { S->base=(SElemType *) realloc(S->base,(S->stacksize+10)*sizeof(SElemType)); //10代表增量,你可以使用宏定義,方便后續修改。 if(!S->base) return 0; S->top=S->base+S->stacksize; S->stacksize+=10 } *S->top++=elem; return 1; }
說明:
1.壓棧是棧的核心操作,關鍵步驟無非是*S->top++=elem;但是在進行此步操作時,一定要判斷棧是否超出容量。
2.如果棧超出容量,則要在進行原空間的基礎上重新分配空間,realloc是關鍵的命令。
realloc
原型:extern void *realloc(void *mem_address, unsigned int newsize);
用法:#include <stdlib.h> 有些編譯器需要#include <alloc.h>
功能:改變mem_address所指內存區域的大小為newsize長度。
說明:如果重新分配成功則返回指向被分配內存的指針,否則返回空指針NULL。
當內存不再使用時,應使用free()函數將內存塊釋放。
3.分配空間以后,在修改stacksize之前,top應該保持在容量頂端,S->top=S->base+S->stacksize;
2.4出棧
int pop(SqStack *q) { if(S->top==S->base) return 0; return *S->--top;; }
說明:
1.出棧是簡單操作,其實這里並沒有完美的實現這個效果,你應該考慮到如果在擴容后又迅速減小,會造成大量的空間浪費。
2.5遍歷棧
int printfStack(SqStack *S) { int *p=S->base; puts("輸出棧"); for(p;p!=S->top;p++) { printf("***%d",*p); } }