#include<stdio.h> #include<stdlib.h> //malloc和realloc函数的库 #define maxsize 100 //宏不需要加';' typedef struct { int data[maxsize]; int top; }myStack,*Stack;
顺序栈类似于顺序表,栈中的元素可以用一个一维数组来保存,同时也要有最大值;而且还要包括一个栈顶top指针,因为栈底指针可任意为一个端点,所以可省略。
//判空栈 int Empty(Stack L){ if(L->top==-1) return 1; //为空栈 else return 0; //不为空栈 }
判空栈需要注意的是:栈顶指针刚开始是为-1
栈满对于顺序栈来说就是等于maxsize,在此不多说。
int length(myStack *s) //计算栈中元素的个数 { printf("\n此时栈的长度为%d\n",s->top+1); }
顺序栈的长度=top指针+1的数。
//取栈顶元素 int get(myStack *s){ if(Empty(s)) printf("栈空!"); //栈空 else printf("栈顶元素为:%d\n",s->data[s->top]); //因为data存放在一维数组所以取的时候遵循数组的写法 }
//初始化栈 int Init(myStack *&s) { s=(myStack *)malloc(sizeof(myStack)); //定义空间结点 s->top=-1; //栈空:top==-1 return 1; }
//入栈 int push(myStack *&s, int e) //元素e入栈 { if(s -> top == maxsize - 1) return 0; else { s -> top++; //栈顶指针加一 s -> data[s -> top] = e;//新插入的元素进栈 return 1; } }
//出栈 void pop(Stack L){ int i=0 ; if(Empty(L)) printf("栈空!"); //栈空 while(i<=L->top){ //i<栈顶时,输出,栈顶-- printf("%d ",L->data[L->top]); L->data[L->top]=0; //将出栈的元素位置赋值0 L->top--; } }
这里根据自己思路写的,也能实现,将出栈的元素赋值为0,在遍历的时候以这个条件为基本在视觉效果较好的情况下遍历。
int main(){ myStack *s; //定义栈 if(Init(s)==1){ //初始化栈 printf("初始化成功!\n"); } printf("-----进行1-5的入栈:\n"); printf("入栈顺序为: ") ; for(int i=1;i<=5;i++){ printf("%d ",i); push(s,i); } length(s); //求栈长 get(s); //取栈顶元素 printf("-----进行1-5的出栈:\n"); printf("出栈顺序为: "); pop(s); //出栈 length(s); //求栈长 }
双向栈用于存储空间较大时,顺序栈无法满足,从而导致溢出或者空闲情况。
特性:栈底指针不变,栈顶指针动态变化;左右两个栈的最大空间均大于maxsize/2.
#include<stdio.h> #include<stdlib.h> #define maxsize 10 //宏不需要加';' typedef struct { int data[maxsize]; int left; //左栈top int right; //右栈top }DoubleStack,*Double;
左栈和右栈的起始地都是从有效空间后一位开始的,左栈从前往后是递增,右栈是从后往前是递增。
//初始化 int Init(Double &L){ L=(Double)malloc(sizeof(DoubleStack)); if(L==NULL) return -1; L->left=-1; //左栈有效位后一位:-1 L->right=maxsize; //右栈有效位后一位:maxsize return 1; }
入栈要存在一个status的判断,个人定义为1时是左栈,为2时是右栈。
//入栈 int push(Double &L,int status,int x){ //status=1代表左数,=2代表右树 if(L->left+1==L->right){ printf("栈满!"); return -1; } if(status==1){ L->left++; //左指针往后 L->data[L->left]=x; //赋值 }else if(status==2){ L->right--; //右指针往前 L->data[L->right]=x; //赋值 } }
出栈元素的值个人先将它输出在定义为0,在遍历时借用这个条件可以输出视觉感官较好的形式。
//出栈 int pop(Double &L,int status) { if(status==1){ if(L->left<0) { printf("左栈为空!\n"); return -1; }else{ printf("出%d ",L->data[L->left]); //输出要出栈的元素 L->data[L->left]=0; //将data[L->left]赋值0 L->left--; } }else if(status==2){ if(L->right>maxsize-1){ printf("右栈为空!\n"); return -1; }else{ printf("出%d ",L->data[L->right]); //输出要出栈的元素 L->data[L->right]=0; //将data[L->right]赋值0 L->right++; } } }
如果元素的值为0,则输出[]。
//遍历栈 void Print(Double &L) { int i,j; for(i=0;i<=maxsize-1;i++){ if(L->data[i]!=0){ //如果元素出栈则出栈函数赋值为0;输出[] printf("%d ",L->data[i]); }else{ printf("[]"); } } }
int main(){ DoubleStack *s; char L,R; if(Init(s)==1){ printf("初始化成功!\n"); } printf("进行1-5的入栈(左右同时):\n"); for(int i=1;i<=5;i++){ //for循环来输入栈 push(s,1,i); //1代表左栈 push(s,2,i); //2代表右栈 } printf("此时栈的元素为:"); Print(s); printf("\n进行一次左栈出栈:\n"); pop(s,1); printf("\n进行一次右栈出栈:\n"); pop(s,2); printf("\n此时栈的元素为:"); Print(s); }
在此声明:本文两个图是借用其他博主的图。