导读
本篇文章将会对顺序栈进行简单介绍,包括其类型定义和基本功能实现(入栈、出栈、取栈顶......)部分函数写的时候还发现了一些问题,在对应部分也有补充探究,同时,文章将会包含完整的C代码以及相关效果的测试图,可以直接复制,并进行自行测试。
顺序栈
顺序栈,即栈的顺序存储结构是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top指示栈顶元素在顺序栈中的位置。通常top==0代表空栈。非空栈中的栈顶指针始终在栈顶元素的下一个位置上。
给出顺序栈的定义:
typedef struct{
int *base;//在栈构造之前和销毁之后,base的值为NULL
int *top;//栈顶指针
int stacksize;//当前已经分配的存储空间
}SqStack,*SqStackPtr;
为了方便到时候去更新空间,在此进行宏定义
#define STACK_INIT_SIZE 100//初始分配量
#define STACKINCREMENT 10//存储空间分配增量
下面写出相关函数的定义:
1.初始化栈:用malloc给栈底指针S->base分配大小为STACK_INIT_SIZE的内存,然后让栈顶指针和栈底指针相同。
SqStackPtr InitStack(void){
SqStackPtr S;
S=(SqStackPtr)malloc(sizeof(SqStack));
S->base=(int *)malloc(sizeof(int)*STACK_INIT_SIZE);
if(!S->base)exit(OVERFLOW);
S->top=S->base;
S->stacksize=STACK_INIT_SIZE;
return OK;
}
2.销毁栈和清除栈:前者会让栈完全消失,后者只会让栈里面的数据消失
先给出对应的函数,然后说一下在写销毁函数的过程中发现的问题:
Status DestroyStack(SqStackPtr S)
{
free(S->base);
free(S);
return OK;
}
Status ClearStack(SqStackPtr S)
{
S->top=S->base;
return OK;
}
发现了什么问题呢?
就是销毁函数里,应该free掉谁?为什么不直接free(S),实际上这个跟链表是一样的道理,在链表的销毁函数中,不能直接free掉头指针L,因为free只能销毁指针所指向的内容,而不能销毁指针所指向的内容当中的指针部分指向的内容。
如果仅仅free(S),栈依然存在
为了验证这个想法,我们可以设置一个int *类型的指针S1,指向S->base,在释放掉S之后,发现,依然可以通过解引用,获取S1原来栈里面保存的元素。(本人已经测试过)
3.判空函数和求长函数(超简单)
Status StackEmpty(SqStackPtr S)
{
if(S->base==S->top) return TRUE;
else return FALSE;
}
int StackLength(SqStackPtr S)
{
return S->top-S->base;
}
4.入栈、出栈、取栈顶、遍历栈(核心操作)
注意1:
入栈的时候,可能会发生栈满的情况,此时我们要用realloc进行扩充,但不要忘记去更新S->top!
注意2:
入栈的时候 ++写右边,是先赋值在让栈顶指针上移,出栈的时候 --写左边,是先下移再把元素赋值给e
Status GetTop(SqStackPtr S,int *e)
{
if(StackEmpty(S)) return ERROR;
*e=*(S->top-1);
return OK;
}
Status Push(SqStackPtr S,int e)
{
if(StackLength(S)==S->stacksize)
{
S->base=(int *)realloc(S->base,(S->stacksize+STACKINCREMENT)*sizeof(int));
if(!S->base) return OVERFLOW;
S->top=S->base+S->stacksize;//容易漏掉!!!!
S->stacksize+=STACKINCREMENT;
}
*S->top++=e;
return OK;
}
Status Pop(SqStackPtr S,int *e)
{
if(StackEmpty(S)) return ERROR;
*e=*--S->top;
return OK;
}
void StackTraverse(SqStackPtr S)
{
if(StackEmpty(S))
{
printf("栈空了!\n");
return ;
}
int *p=(S->top-1);
while(p!=S->base)
{
printf("%d ",*p);
p--;
}
printf("%d\n",*p);
return;
}
下面给出测试图:
主函数设置为:
int main()
{
SqStackPtr S;
S=InitStack();
StackTraverse(S);
Push(S,1);
Push(S,2);
Push(S,3);
StackTraverse(S);
int e;
Pop(S,&e);
StackTraverse(S);
return 0;
}