棧的鏈式存儲結構及應用(C、Java代碼)
阿新 • • 發佈:2019-01-23
ops bubuko gif one get image ++ 我們 溢出
鏈式存儲結構最大的好處就是沒有空間的限制,可以通過指針指向將結點像以鏈的形式把結點鏈接,我們熟悉的線性表就有鏈式存儲結構。
當然,棧同樣有鏈式存儲結構,棧的鏈式存儲結構,簡稱鏈棧。
從圖片可以看到,和單鏈表很像,擁有一個頭指針top,又稱作棧頂指針,所以此時就不再需要單鏈表裏面的頭結點了。
對於鏈棧來說,基本不存在棧滿的情況,除非計算機內存已經沒有了可使用的空間,如果真的存在,那麽計算機系統已經面臨著即將死機崩潰的情況,而不是這個鏈棧是否溢出的問題了。
對於空棧來說,鏈表的定義是頭指針指向NULL,而鏈棧是top=NULL
鏈棧的結構定義:
1 /*鏈棧的定義需要用到兩個結構體 */
2 typedef struct StackNode{ //單鏈表節點類型
3 int data;
4 StackNode* next;
5
6 }StrackNode;
7 typedef struct StackNode *LinkStackPtr;
8
9 typedef struct { //棧
10
11 LinkStackPtr top; //棧底指針
12 int count;
13
14 }LinkStact;
進棧操作
/*入棧*/
void PushStack(LinkStact *s,int e){ //這邊棧應該傳地址
LinkStackPtr a =(StackNode*)malloc(sizeof(StackNode)); //新的節點
a->data = e;
a->next = s->top; //把當前的棧頂元素賦值給新結點的直接後繼
s->top =a; /* 將新的結點s賦值給棧頂指針 */
s->count++;
}
這裏重新回憶一下參數傳參的兩種方式:傳值、傳地址。
傳值:傳值無非就是實參拷貝傳遞給形參,單向傳遞(實參->形參),二者中間做了一個拷貝動作,即兩者的實際地址不同了,所以對任何一方的操作都不會影響到另一方。
傳地址:形參和實參是同一個變量,即使用相同的內存空間,二者有相同的地址,修改任意一方都將相互影響。
出棧操作
/*出棧,並返回棧頂元素*/
int PopStack(LinkStact *s){
int top;
LinkStackPtr p;
p = s->top; /* 將棧頂結點賦值給p */
if(p ==NULL)
return -1;
top = p->data;
s->top=s->top->next; /* 使得棧頂指針下移一位,指向後一結點,即指向新的棧頂 */
free(p); //釋放內存
s->count--; //長度減一
return top;
}
使用棧時確記要記得給棧初始化
1 /*初始化一個空棧*/
2 int InitStack(LinkStact *s){
3 s->top = (StackNode *)malloc(sizeof(StackNode));
4 if(!s->top)
5 return 0;
6 s->top=NULL;
7 s->count=0;
8 return 1;
9 }
遍歷棧操作
1 /*遍歷棧*/
2 void StackTraverse(LinkStact s){
3 LinkStackPtr p;
4 p=s.top; //指針指向棧頂
5 while(p) //當棧不為空時
6 {
7 printf("%d ",p->data);
8 p =p->next;
9 }
10 }
清空棧操作
1 /*清空棧*/
2 void ClearStack(LinkStact *s){
3
4 LinkStackPtr p,q;
5 p = s->top; //取棧頂
6 while(p){
7 q=p;
8 p=p->next;
9 free(q);
10 }
11 s->count=0;
12 }
其他的操作見代碼:
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 /*鏈棧的定義需要用到兩個結構體*/ 5 typedef struct StackNode{ //單鏈表節點類型 6 int data; 7 StackNode* next; 8 9 }StrackNode; 10 typedef struct StackNode *LinkStackPtr; 11 12 typedef struct { //棧 13 14 LinkStackPtr top; //棧底指針 15 int count; 16 17 }LinkStact; 18 19 /*初始化一個空棧*/ 20 int InitStack(LinkStact *s){ 21 s->top = (StackNode *)malloc(sizeof(StackNode)); 22 if(!s->top) 23 return 0; 24 s->top=NULL; 25 s->count=0; 26 return 1; 27 } 28 29 /*清空棧*/ 30 void ClearStack(LinkStact *s){ 31 32 LinkStackPtr p,q; 33 p = s->top; //取棧頂 34 while(p){ 35 q=p; 36 p=p->next; 37 free(q); 38 } 39 s->count=0; 40 } 41 42 /*判斷是否為空棧,為空返回0,否則返回1*/ 43 int StackEmpty(LinkStact *s){ 44 if(s->count==0) 45 return 1; 46 else 47 return 0; 48 } 49 50 /*入棧*/ 51 void PushStack(LinkStact *s,int e){ //這邊棧應該傳地址 52 53 LinkStackPtr a =(StackNode*)malloc(sizeof(StackNode)); //新的節點 54 a->data = e; 55 a->next = s->top; //把當前的棧頂元素賦值給新結點的直接後繼 56 s->top =a; /* 將新的結點s賦值給棧頂指針 */ 57 s->count++; 58 } 59 60 /*出棧,並返回棧頂元素*/ 61 int PopStack(LinkStact *s){ 62 int top; 63 LinkStackPtr p; 64 p = s->top; /* 將棧頂結點賦值給p */ 65 if(p ==NULL) 66 return -1; 67 top = p->data; 68 s->top=s->top->next; /* 使得棧頂指針下移一位,指向後一結點,即指向新的棧頂 */ 69 free(p); //釋放內存 70 s->count--; //長度減一 71 72 return top; 73 } 74 75 /*返回棧的長度*/ 76 int StackLength(LinkStact s){ 77 return s.count; 78 } 79 80 /*若棧不為空,則返回棧頂元素*/ 81 int GetTop(LinkStact s){ 82 if(s.count == NULL) 83 return 0; 84 else 85 return s.top->data; 86 } 87 88 /*遍歷棧*/ 89 void StackTraverse(LinkStact s){ 90 LinkStackPtr p; 91 p=s.top; //指針指向棧頂 92 while(p) //當棧不為空時 93 { 94 printf("%d ",p->data); 95 p =p->next; 96 } 97 } 98 99 int main(){ 100 LinkStact s; 101 printf("進棧10個數據\n"); 102 if(InitStack(&s)==1){ 103 for(int i=1;i<=10;i++) 104 PushStack(&s,i); 105 } 106 StackTraverse(s); //遍歷棧 107 printf("\n"); 108 109 printf("進棧後長度:%d\n",StackLength(s)); 110 111 printf("出棧,取棧頂元素,棧頂元素是 :%d",GetTop(s)); 112 printf("\n"); 113 114 printf("棧是否為空? 1:0:%d\n",StackEmpty(&s)); 115 116 printf("出棧一個元素:%d\n",PopStack(&s)); 117 118 StackTraverse(s); 119 120 121 return 0; 122 }View Code
另外附上Java代碼
棧的鏈式存儲結構及應用(C、Java代碼)