棧的鏈式儲存結構稱為鏈棧。鏈棧的節點類型與鏈式線性表的節點類型
定義相同,不同的是它是僅在表頭進行操作的單鏈表。鏈棧通常用不帶頭節
點的單鏈表來實現,棧頂指針就是鏈表的頭指針 ,如圖所示:
代碼如下:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 #define OK 1 5 #define ERROR 0 6 typedef int SElemType; 7 //棧的鏈式儲存結構 8 typedef struct SNode { 9 SElemType data; //數據域 10 struct SNode *next; //指針域 11 12 }SNODE, *PSNODE; 13 //棧頂節點 14 typedef struct 15 { 16 PSNODE top; //棧頂指針 17 int count; //棧的長度 18 19 }LinkStack; 20 21 //初始化棧頂節點 22 int Init_LS(LinkStack *s) { 23 s->top = (PSNODE)malloc(sizeof(SNODE)); 24 if (!s->top) 25 return ERROR; 26 27 s->top = NULL; 28 s->count = 0; 29 return OK; 30 } 31 //判斷棧是否為空 32 int Is_Empty(LinkStack *s) { 33 if (s->top == NULL) 34 { 35 printf("棧為空\n"); 36 return OK; 37 } 38 39 else { 40 printf("棧不為空\n"); 41 return ERROR; 42 } 43 } 44 //遍歷棧 45 int Traverse_LS(LinkStack *s) { 46 int i; 47 if (Is_Empty(s) == OK) return ERROR; 48 PSNODE p = s->top; 49 for(i=s->count;i>0;i--) 50 { 51 52 printf("%d ", p->data); 53 p = p->next; 54 } 55 printf("\n"); 56 return OK; 57 } 58 //鏈棧元素入棧 59 int Push_LS(LinkStack *s, SElemType e) { 60 61 PSNODE p = (PSNODE)malloc(sizeof(SNODE)); 62 if (!p) return ERROR; 63 p->data = e; 64 p->next = s->top; //新結點指向棧頂指針指向的地址 65 s->top = p; //更新棧頂指針 66 s->count++; // 節點增加1 67 68 return OK; 69 70 } 71 // 獲取棧頂元素 72 int GetTop(LinkStack *s, SElemType *e) { 73 if (Is_Empty(s) == OK) return ERROR; 74 *e = s->top->data; 75 return OK; 76 } 77 //鏈棧元素出棧 78 int Pop_LS(LinkStack *s, SElemType *e) { 79 if (Is_Empty(s) == OK) return ERROR; 80 81 PSNODE temp = s->top; 82 *e = temp->data; 83 s->top = temp->next; 84 s->count--; 85 free(temp); 86 return OK; 87 } 88 //銷毀棧 89 int Destroy_LS(LinkStack *s) { 90 PSNODE p,q=NULL; 91 if(Is_Empty(s)==OK) return ERROR; 92 p = s->top; 93 for (int i = s->count; i > 0; i--) 94 { 95 q = p->next; 96 free(p); 97 p = q; 98 } 99 s->count = 0; 100 return OK; 101 } 102 103 int main() { 104 LinkStack s,*ps; 105 SElemType a, *e; 106 e = (SElemType*)malloc(sizeof(SElemType)); 107 ps = &s; 108 Init_LS(ps); 109 int n; 110 Is_Empty(ps); 111 printf("請輸入入棧元素的個數:"); 112 scanf("%d", &n); 113 for(int i=0;i<n;i++) 114 { 115 scanf("%d", &a); 116 Push_LS(ps, a); 117 } 118 Traverse_LS(ps); 119 Pop_LS(ps, e); 120 printf("彈出的元素為%d\n", *e); 121 Traverse_LS(ps); 122 GetTop(ps, e); 123 printf("棧頂元素為%d\n", *e); 124 if(Destroy_LS(ps)==OK) printf("棧銷毀成功!"); 125 126 return 0; 127 }
我寫的這個鏈棧的代碼 稍微修改了一點 --把棧頂指針與count 組成一個結構體
count用來儲存鏈棧的長度。如果鏈棧的長度很長而且經常需要返回長度 一個一個
算的話顯得特別費時間;而使用count要方便的多 。
如果我們要把兩個鏈棧合並,必然需要其中一個的棧底地址
而且如果這個鏈棧很大,我們要從棧頂開始尋找棧底地址 很麻煩吧
但是我們在LinkStack 中增加一個 PSNODE bottom指針,在入棧函數中
根據count來給bottom賦值。這樣棧底地址就有了。
所以,數據結構的一些細節上的東西不是一成不變的,而是可以根據具體
的問題修改。