栈(stack)是一种只能在一端进行插入和删除操作的线性表。表中允许进行插入和删除操作的一端称为栈顶。栈顶的当前位置是动态的,由一个称为栈顶指针的位置指示器指示。表的另一端称为栈底。不含数据元素的栈称为空栈。栈的插入操作称为压栈或进栈,栈的删除操作称为退栈或出栈。栈的主要特点是“后进先出(last in first out,LIFO)”。
1、 顺序栈
假定栈的元素个数不超过MaxSize,所有的元素都具有同一数据类型ElemType。采用栈指针s建立和使用顺序栈。在由s指向的顺序栈中,栈空的条件是s->top=-1;栈满的条件是s->top=MaxSize-1;元素e进栈操作是先将栈顶指针加1,然后将元素e放入栈顶指针处;出栈操作是先将栈顶指针处的元素取出,然后将栈顶指针减1。
顺序栈的基本运算实现代码如下:
#include<stdio.h>
#include<stdlib.h>
#define MaxSize 50
typedef int ElemType;
typedef struct
{
ElemType data[MaxSize];
int top; //栈顶指针
}SqStack; //顺序栈
void InitStack(SqStack *&s) //初始化顺序栈
{
s=(SqStack *)malloc(sizeof(SqStack));
s->top=-1;
}
void DestoryStack(SqStack *&s) //销毁顺序栈
{
free(s);
}
bool StackEmpty(SqStack *s) //判断是否为空栈
{
return (s->top==-1);
}
bool Push(SqStack *&s, ElemType e) //压栈
{
if(s->top==MaxSize-1) //栈满,栈上溢出
return false;
s->top++;
s->data[s->top]=e;
return true;
}
bool Pop(SqStack *&s, ElemType &e) //出栈,注意要使用&e
{
if(-1==s->top) //栈空,栈下溢出
return false;
e=s->data[s->top];
s->top--;
return true;
}
bool GetTop(SqStack *s, ElemType &e)
{
if(-1==s->top)
return false;
e=s->data[s->top];
return true;
}
int main()
{
...;
return 0;
}
2、 链栈
采用链式存储的栈称为链栈,本文采用单链表实现。链栈的优点是不存在栈满上溢的情况。规定栈的所有操作都在单链表的表头进行,头结点为*s,第一个数据结点是栈顶结点,最后一个结点是栈底结点。
在以*s为头结点的链栈中,栈空的条件是s->next==NULL;由于只有在内存溢出时才会出现栈满,而通常不考虑内存溢出的情况,所以在链栈中可以认为不存在栈满的情况;结点*p进栈的操作是在头结点*s之后插入*p结点;出栈的操作是取出头结点之后的结点的data值并剔除该结点。
链栈的基本运算实现代码如下:
#include<stdio.h>
#include<stdlib.h>
typedef int ElemType;
typedef struct linknode
{
ElemType data;
struct linknode *next;
}LiStack;
void InitStack(LiStack *&s) //初始化栈
{
s=(LiStack *)malloc(sizeof(LiStack));
s->next=NULL;
}
void DestoryStack(LiStack *&s) //销毁栈
{
LiStack *p=s,*q=s->next;
while(q!=NULL)
{
free(p);
p=q;
q=q->next;
}
free(p);
}
bool StackEmpty(LiStack *s) //判断是否空栈
{
return (s->next==NULL);
}
void Push(LiStack *&s, ElemType e) //压栈(头插法)
{
LiStack *p;
p=(LiStack *)malloc(sizeof(LiStack));
p->data=e;
p->next=s->next;
s->next=p;
}
bool Pop(LiStack *&s, ElemType &e) //出栈
{
LiStack *p=s->next;
if(p==NULL)
return false;
e=p->data;
s->next=p->next;
free(p);
return true;
}
bool GetTop(LiStack *s, ElemType &e) //取栈顶元素
{
if(s->next==NULL)
return false;
e=s->next->data;
return true;
}
int main()
{
...;
return 0;
}
几个注意点:
1、 函数的形参采用指针+引用的格式,可以改变实参的值;
2、 代码在VC6.0下实现,后缀名使用.cpp可以排除一些错误,如false和true的未定义,引用符号&的使用等;
3、 栈的应用:逆序输出、语法检查、数制转换、递归等。
Monday, July 28, 2014