数据结构的定义是相互之间有一种或多种关系的元素的集合。栈就是比较简单的一对一的数据结构,对于堆栈的理解,我们可以借鉴手枪子弹,后上进去的子弹先出来,即先进后出,后进先出的结构。栈有许多应用,比如逆序输出、符合计算机语言的逆波兰表达式等等等等。 stack栈:是一个后进先出的线性表,它要求只在表尾进行删除和插入操作。 注意: 1.栈元素必须后进先出。 2.栈的操作只能在这个线性表的表尾。 栈有两个基本操作: 栈的插入操作:push,进栈、压栈 栈的删除操作:pop,出栈、弹栈 下面先介绍栈的结构: 栈有两种存储形式、顺序存储和链式存储,我们这里先介绍顺序存储法。
typedef struct { char *base; //栈底 char *top; //栈顶 int stackSize; //栈的长度 }sqStack;结构体sqStack中只有三个元素,base、top指针,stackSize的int型变量: base指针:指向栈底 top指针 :指向栈顶 stackSize :栈当前长度 结构就是这样一个结构,很明显我们要将在这三个元素上进行各种操作,对于指针我们能做的也就是地址分配,对于int型变量,可以将它看成计数器的作用。
栈的创建就是一个分配空间的过程,创建N个空间,这N个空间组成一个栈的空间。我们使用initStack函数创建一个空栈,宏定义一个栈的长度,从base指针开始,分配了STACK_INIT_SIZE个空间给这个栈,之后将栈顶指向栈底,stackSize变量赋值为初始值。
#define STACK_INIT_SIZE 50 initStack(sqStack *s) { //构造出一个空栈 s -> base = (ElemType *)malloc(STACK_INIT_SIZE* sizeof(Elemtype)); if( !s -> base) //存储分配失败 exit(0); s->top = s->base; //最开始栈顶就是栈底 s->stack stackSize = STACK_INIT_SIZE; }压栈操作在栈顶进行,每次压入一个数据。压栈操作由push函数实现,在堆栈已满的情况下增加一个宏定义,栈满增加空间,在函数开始时进行一次判断。 如果:栈顶-栈底大于等于栈栈的最大容量,就要增加空间了,这里使用了一个realloc()函数,即在原有stackSize的原有基础上增加了STACKINCREMENT 个空间,同时要改变一下栈顶的位置了。 如果:栈当前不是满状态,则给栈顶赋值,top指针指向下一个地址。
#define STACKINCREMENT 10 push(sqStack *s,ElemType e) { //如果栈满,追加空间 if(s->top – s->base >= s->stackSize) { s->base = (ElemType *)realloc(s->base,(s->stackSize + STACKINCREMENT)*sizeof(ElemType)); if(!s->base) exit(0); s->top = s->base +s->stackSize; //设置栈顶 s->stackSize += STACKINCREMENT; //设置栈的最大容量 } *(s->top) = e; s->top++; }出栈操作也是从栈顶开始。pop函数先判断,如果栈顶等于栈底,说明栈已经空了,返回空;否则返回一个元素,因为栈顶是指向最上面元素的下一个,所以这里做一个前–操作。
Pop(sqStack *s,ElemType &e) //这里作引用e直接修改值 { if( s->top == s->base) //栈已空空如也 return; e = *--(s->top); //这里的是先--后取值 }清空一个栈比较简单,只要将一个栈的栈底赋值为栈顶。 销毁一个栈则需要将数据域空间全部释放:DestoryStack函数,顺序栈的销毁只需要将栈顶栈底置为NULL即可。
DestoryStack(sqStack *s) { s->base = s->top = NULL; s->stackSize = 0; }只需返回s.top - s.base。
int StackLen(sqStack s) { return(s.top – s.base); }