一、栈的定义
栈:是只允许在一端进行插入或删除操作的线性表。首先栈是一种线性表,但限定这种线性表只能在某一端进行插入和删除操作。
栈的示意图:
栈顶(Top): 线性表允许进行插入删除的那一端。
栈底(Bottom): 固定的,不允许进行插入和删除的另一端。
空栈: 不含任何元素的空表。
进栈(压栈或入栈): 栈的插入操作
出栈(弹栈): 栈的删除操作
二、栈的顺序存储结构
2.1顺序栈的实现
采用顺序存储的栈称为顺序栈,它利用一组地址连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针 (top) 指示当前栈顶元素的位置。
栈的顺序结构定义:
#define MaxSize 20 typedef struct { ElemType data[MaxSize]; //存放栈中元素 int top; //栈顶指针 }SqStack;
顺序栈基本操作:
#include<stdio.h> #define MaxSize 20 typedef int ElemType; typedef struct { ElemType data[MaxSize]; //存放栈中元素 int top; //栈顶指针 }SqStack; void InitStack(SqStack *S); //初始化 bool Push(SqStack *S,ElemType e); //进栈 bool Pop(SqStack *S,ElemType *e); //出栈 bool StackEmpty(SqStack S); //判断栈空 bool GetTop(SqStack S,ElemType *e); //获取栈顶元素 int StackLength(SqStack S); //获取栈长度 void PrintStack(SqStack S); //打印栈所有元素 int main() { SqStack S; ElemType e; int len; InitStack(&S); Push(&S,1); Push(&S,2); Push(&S,3); Push(&S,4); Push(&S,5); printf("栈的元素为:"); PrintStack(S); Pop(&S,&e); printf("出栈的元素为:%d\n",e); GetTop(S,&e); printf("栈顶的元素为:%d\n",e); len = StackLength(S); printf("栈的长度为:%d\n",len); return 0; } void InitStack(SqStack *S) { S->top = -1; //初始化栈顶指针 } bool StackEmpty(SqStack S) { if(S.top == -1) return true; else return false; } bool Push(SqStack *S,ElemType e) { if(S->top == MaxSize -1) //栈满,报错 return false; S->data[++S->top] = e; //指针先加1,再入栈 return true; } bool Pop(SqStack *S,ElemType *e) { if(S->top == -1) //栈空,报错 return false; *e = S->data[S->top--]; //先将要删除的元素赋值给e,然后再对指针减 1 return true; } bool GetTop(SqStack S,ElemType *e) { if(S.top == -1) return false; *e = S.data[S.top]; return true; } int StackLength(SqStack S) { return S.top+1; } void PrintStack(SqStack S) { int i = 0; while(i <= S.top) printf("%d ",S.data[i++]); printf("\n"); }
三、栈的链式存储
3.1链栈的实现
采用链式存储的栈称为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。这里规定链栈没有头结点,Lhead 指向栈顶元素(因为已经有了栈顶在头部,头结点就失去了意义了)
链栈的结构代码:
typedef struct StackNode { SElemType data; struct StackNode *next; }StackNode,*LinkStackPtr; typedef struct { LinkStackPtr top; int count; }LinkStack;
3.2栈的完整代码:
#include<stdio.h> #include<malloc.h> typedef int ElemType; /* 链栈结构 */ typedef struct StackNode { ElemType data; struct StackNode *next; }StackNode,*LinkStackPtr; typedef struct Stack { LinkStackPtr top; int count; }LinkStack; int InitStack(LinkStack *S) { S->top = (LinkStackPtr)malloc(sizeof(StackNode)); if(!S->top) return 0; S->top = NULL; S->count = 0; return 1; } int ClearStack(LinkStack *S) { LinkStackPtr p,q; p=S->top; while(p) { q=p; p=p->next; free(q); } S->count=0; return 1; } bool StackEmpty(LinkStack S) { if (S.count==0) return true; else return false; } int StackLength(LinkStack S) { return S.count; } bool GetTop(LinkStack S,ElemType *e) { if (S.top==NULL) return false; else *e=S.top->data; return true; } /* 插入元素e为新的栈顶元素 */ bool Push(LinkStack *S,ElemType e) { LinkStackPtr s=(LinkStackPtr)malloc(sizeof(StackNode)); s->data=e; s->next=S->top; /* 把当前的栈顶元素赋值给新结点的直接后继,见图中① */ S->top=s; /* 将新的结点s赋值给栈顶指针,见图中② */ S->count++; return true; } /* 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR */ bool Pop(LinkStack *S,ElemType *e) { LinkStackPtr p; if(StackEmpty(*S)) return false; *e=S->top->data; p=S->top; /* 将栈顶结点赋值给p,见图中③ */ S->top=S->top->next; /* 使得栈顶指针下移一位,指向后一结点,见图中④ */ free(p); /* 释放结点p */ S->count--; return true; } void PrintStack(LinkStack S) { LinkStackPtr p; p=S.top; while(p) { printf("%d ",p->data); p=p->next; } printf("\n"); } int main() { LinkStack S; ElemType e; int len; InitStack(&S); Push(&S,1); Push(&S,2); Push(&S,3); Push(&S,4); Push(&S,5); printf("栈的元素为:"); PrintStack(S); Pop(&S,&e); printf("出栈的元素为:%d\n",e); GetTop(S,&e); printf("栈顶的元素为:%d\n",e); len = StackLength(S); printf("栈的长度为:%d\n",len); return 0; }