栈:
从数据结构上来看,栈也是线性表,但是是操作受限的线性表。
栈是限定仅在表尾进行插入或删除操作的线性表。
对栈来说,表尾端称为栈顶,表头端称为栈底。
栈是后进先出的线性表。
栈的基本操作:在栈顶插入删除,初始化,判空,取栈顶元素等
栈也有两种存储方法,一种是顺序栈,用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素。另一种是链栈。这里先整理顺序栈。
顺序栈的实现及操作:
1.定义一个栈
顺序栈的定义完全可以用顺序表的定义,不过这里由于经常要用到栈顶,所以就增加一个top指针,指向栈顶元素的下一个位置。由于当前已存的元素个数length可以由栈顶指针减栈底指针求出,所以,这里就省去length,只保留一个初始化定义时给定的最大存储元素个数stacksize,当使用栈时空间不够,可以再进行扩大。
top指针方便之处,就在于,插入的时候插到top指向的位置上,然后top指针自增。出栈的时候把top指针自减,然后把top指针指向位置的元素取出即可。
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
typedef struct
{
SElemType_Sq *base;
SElemType_Sq *top;
int stacksize;
}SqStack;
2.构造一个空栈
base称为栈底指针,top称为栈顶指针。构造空栈,top指针和base指针指向同一位置,此时栈里面没有元素(length=0)。其他的和构造一个空顺序表一样。
Status InitStack_Sq(SqStack &S)
{
S.base = (SElemType_Sq *)malloc(STACK_INIT_SIZE*sizeof(SElemType_Sq));
if(!S.base)
exit(OVERFLOW);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
3.取栈顶元素
这里取栈顶元素,我们先判断栈是否为空,如果不为空,取栈顶元素。栈顶元素再top指针的上一个位置,也就是S.top - 1(这里可以类比数组,a+1也就是指向a[1]的指针),那么取出的话把地址的值给e即可。注意这里仅仅是取出,不能改变栈顶指针,不能S.top–。
Status GetTop_Sq(SqStack S, SElemType_Sq &e)
{
if(S.top==S.base)
return ERROR;
e = *(S.top - 1);
return OK;
}
4.插入元素e
之前说了,S.top-S.base就是length当前已存的元素个数,那么如果length=最大存储元素个数stacksize,那么再插入元素的时候就空间不够了,所以这里需要再增加一段新的空间,能够再多存STACKINCREMENT个元素。弄完之后我们的top指针应该指向栈顶元素的下一个位置,此时已经有stacksize个元素了,也就是说,top指针指向S.base + S.stacksize这个位置。(不理解可以类比数组a+stacksize就是&a[stacksize],而a时下标为0开始存元素的,也就是说现在a+stacksize指向的时第stacksize+1个元素的位置)
然后修改完top指针后,stacksize也更新为S.stacksize + STACKINCREMENT。
此时我们先把e赋值到top指针指向的位置,然后top指针指向栈顶元素的下一个位置,自己加一即可。
Status Push_Sq(SqStack &S, SElemType_Sq e)
{
if(S.top-S.base>=S.stacksize)
{
S.base = (SElemType_Sq *)realloc(S.base, (S.stacksize+STACKINCREMENT)*sizeof(SElemType_Sq));
if(!S.base)
exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top = e;
S.top++;
return OK;
}
5.删除栈顶元素,返回其值
出栈的时候把top指针自减,然后把top指针指向位置的元素取出即可。
Status Pop_Sq(SqStack &S, SElemType_Sq &e)
{
if(S.top==S.base)
return ERROR;
S.top--;
e = *(S.top);
return OK;
}
6.清空栈,销毁栈
清空栈,意味着top指针和base指针指向同一位置。
但是销毁栈,top指针和base指针指向null而且stacksize等于0。
Status DestroyStack_Sq(SqStack &S)
{
S.base = NULL;
S.top = NULL;
S.stacksize = 0;
return OK;
}
Status ClearStack_Sq(SqStack &S)
{
S.top = S.base;
return OK;
}
栈的操作实例及代码:
代码:
#include<cstdio>
#include<cstdlib>
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define UNDERFLOW -3
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int SElemType_Sq;
typedef struct
{
SElemType_Sq *base;
SElemType_Sq *top;
int stacksize;
}SqStack;
Status InitStack_Sq(SqStack &S)
{
S.base = (SElemType_Sq *)malloc(STACK_INIT_SIZE*sizeof(SElemType_Sq));
if(!S.base)
exit(OVERFLOW);
S.top = S.base;
S.stacksize = STACK_INIT_SIZE;
return OK;
}
Status GetTop_Sq(SqStack S, SElemType_Sq &e)
{
if(S.top==S.base)
return ERROR;
e = *(S.top - 1);
return OK;
}
Status Push_Sq(SqStack &S, SElemType_Sq e)
{
if(S.top-S.base>=S.stacksize)
{
S.base = (SElemType_Sq *)realloc(S.base, (S.stacksize+STACKINCREMENT)*sizeof(SElemType_Sq));
if(!S.base)
exit(OVERFLOW);
S.top = S.base + S.stacksize;
S.stacksize += STACKINCREMENT;
}
*S.top = e;
S.top++;
return OK;
}
Status Pop_Sq(SqStack &S, SElemType_Sq &e)
{
if(S.top==S.base)
return ERROR;
S.top--;
e = *S.top;
return OK;
}
void PrintElem(SElemType_Sq e)
{
printf("%d ", e);
}
Status StackTraverse_Sq(SqStack S, void(Visit)(SElemType_Sq))
{
SElemType_Sq *p = S.base;
while(p<S.top)
Visit(*p++);
printf("\n");
return OK;
}
Status StackEmpty_Sq(SqStack S)
{
if(S.top==S.base)
return TRUE;
else
return FALSE;
}
int main(){
SqStack S;
int i;
SElemType_Sq e;
printf("初始化顺序栈 S ...\n");
InitStack_Sq(S);
printf("\n");
StackEmpty_Sq(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
printf("\n");
for(i=1; i<=6; i++)
{
printf("将 \"%2d\" 压入栈 S \n", 2*i);
Push_Sq(S, 2*i);
}
printf("\n");
printf(" S 中的元素为:S = ");
StackTraverse_Sq(S, PrintElem);
printf("\n");
Pop_Sq(S, e);
printf("栈顶元素 \"%d\" 出栈...\n", e);
printf(" S 中的元素为:S = ");
StackTraverse_Sq(S, PrintElem);
printf("\n");
GetTop_Sq(S, e);
printf("栈顶元素的值为 \"%d\" \n", e);
printf("\n");
}
运行结果:
初始化顺序栈 S …
S 为空!!
将 " 2" 压入栈 S
将 " 4" 压入栈 S
将 " 6" 压入栈 S
将 " 8" 压入栈 S
将 “10” 压入栈 S
将 “12” 压入栈 S
S 中的元素为:S = 2 4 6 8 10 12
栈顶元素 “12” 出栈…
S 中的元素为:S = 2 4 6 8 10
栈顶元素的值为 “10”