前言:雖然c++裏面有現成的stack可以用,但是我覺得學習數據結構,用底層語言來實現是很有必要的!
**
簡單的解釋一下;
堆棧就是一種具有特定規則的線性表
先進後出(看圖就很直觀了)
舉個栗子
往一個紙箱裏面塞書
先進去的就到了紙箱底部
後進去的在頂上
要想取出後面的書則要先取出頂上的書
鏈式表
創建結點
typedef struct SNode* PtrToSNode;
struct SNode {
ElementType Data;
PtrToSNode Next;
};
創建棧頭(也就是最頂部)
注意是頂部!!!不是底部;
至於爲什麼
當然是爲了插入和刪除的方便啊
棧頭是不存值的 請類比一下頭指針
typedef PtrToSNode Stack;
Stack CreateStack()
{ /* 構建一個堆棧的頭結點,返回該結點指針 */
Stack S;
S = (Stack)malloc(sizeof(struct SNode));
S->Next = NULL;
return S;
}
判斷是否爲空
即判斷棧頂的下一個有沒有對象
bool IsEmpty(Stack S)
{ /* 判斷堆棧S是否爲空,若是返回true;否則返回false */
return (S->Next == NULL);
}
入棧
先申請一部分空間
將X賦值給新空間的data部分
然後讓棧頭指向它。
bool Push(Stack S, ElementType X)
{ /* 將元素X壓入堆棧S */
PtrToSNode TmpCell;
TmpCell = (PtrToSNode)malloc(sizeof(struct SNode));
TmpCell->Data = X;
TmpCell->Next = S->Next;
S->Next = TmpCell;
return true;
}
出棧
和入棧差不多啦
先判斷堆棧是不是空的,是空的肯定就不能出棧了啊。
然後聲明定義一個指針,讓它指向棧頭指向的結點(爲了釋放內存)
同時聲明定義一個元素,將出棧的值賦值給它(爲了return 出去)
然後直接讓棧頭指向下一個結點就好了;
然後把內存釋放掉。
ElementType Pop(Stack S)
{ /* 刪除並返回堆棧S的棧頂元素 */
PtrToSNode FirstCell;
ElementType TopElem;
if (IsEmpty(S)) {
printf("堆棧空");
return ERROR;
}
else {
FirstCell = S->Next;
TopElem = FirstCell->Data;
S->Next = FirstCell->Next;
free(FirstCell);
return TopElem;
}
}
順序表
個人觀點:順序結構存儲編碼容易,但是不能動態申請內存,你需要先知道這個棧有多大,要開多大的數組。
創建
typedef int Position;
struct SNode {
ElementType* Data; /* 存儲元素的數組 */
Position Top; /* 棧頂指針 */
int MaxSize; /* 堆棧最大容量 */
};
棧頭
typedef struct SNode* Stack;
Stack CreateStack(int MaxSize)
{
Stack S = (Stack)malloc(sizeof(struct SNode));
S->Data = (ElementType*)malloc(MaxSize * sizeof(ElementType));
S->Top = -1;
S->MaxSize = MaxSize;
return S;
}
堆棧是否已滿
滿了就塞不進了啊
bool IsFull(Stack S)
{
return (S->Top == S->MaxSize - 1);
}
入棧
bool Push(Stack S, ElementType X)
{
if (IsFull(S)) {
printf("堆棧滿");
return false;
}
else {
S->Data[++(S->Top)] = X;
return true;
}
}
是否爲空
bool IsEmpty(Stack S)
{
return (S->Top == -1);
}
出棧
ElementType Pop(Stack S)
{
if (IsEmpty(S)) {
printf("堆棧空");
return ERROR; /* ERROR是ElementType的特殊值,標誌錯誤 */
}
else
return (S->Data[(S->Top)--]);
}