栈和队列是两种非常重要的数据结构。栈是一种先进后出的数据结构,而队列是一种先进先出的数据结构。从它们的特点来看,栈和队列是针锋相对的,但它们却是相互联系的。比如后面要介绍到的“用两个栈实现队列”以及“用队列实现栈”。下面用这幅图再来认识一下栈和队列这两种数据结构的特点。
接着我们来设计一个栈的结构,并用代码实现入栈、出栈、判栈满、栈空以及获得栈顶元素等。
typedef int ElemType;//类型重定义
#define STACK_INIT 10//初始分配栈空间的大小
#define APPEND_STACK 5//栈满时给栈扩容的大小
typedef struct stack
{
ElemType *base;//栈底指针
int top;//记录栈顶
int stacksize;//当前栈空间大小
}Seqstack,*pSeqstack;
在对栈进行操作的时候首先需要判空,因为对一个空栈进行操作是没有任何意义的,所以判空这一步是必不可少的。
static void DeterPointIsNull(pSeqstack stack)
{
assert(stack!=NULL);//断言,需要引用头文件#include <assert.h>
if(stack==NULL)
{
printf("stack is null,error!");
exit(0);
}
}
由于我们给栈的初始空间分配的大小是固定的,所以当栈存储数据满时,需要对栈进行扩容。
static void AppendSize(pSeqstack stack)
{
ElemType *s=(ElemType*)malloc(sizeof(ElemType)*
(APPEND_STACK+stack->stacksize));//开辟一块新的内存
assert(s!=NULL);//断言这块内存不为空
for(int i=0;i<stack->stacksize;i++)
{
s[i]=stack->base[i];//将栈里面的数据放到新开辟的空间中
}
free(stack->base);//释放掉原来的栈空间
stack->base=s;//让两个指针指向同一块内存
stack->stacksize+=APPEND_STACK;//栈空间变大
}
接下来我们对栈进行初始化。
void InitSeqstack(pSeqstack stack)
{
DeterPointIsNull(stack);//判断栈是否为空
stack->base=(ElemType*)malloc(sizeof(ElemType)*STACK_INIT);
assert(stack->base!=NULL);
stack->top=0;
stack->stacksize=STACK_INIT;
}
除此之外我们还需要对栈里面是否还有元素进行判断。我们有一个栈顶变量top,所以只要判断top的值是否为0,就可以知道栈里面是否还有元素存在。
int EmptyStack(pSeqstack stack)
{
DeterPointIsNull(stack);
if(stack->top==0)
{
return 1;
}
return 0;
}
入栈代码如下:
int Pushstack(pSeqstack stack,ElemType val)
{
DeterPointIsNull(stack);
if(stack->top==stack->stacksize)//栈空间不足
{
AppendSize(stack);//扩容
}
stack->base[stack->top++]=val;
return 1;
}
获得栈顶元素操作:
int GetTop(pSeqstack stack,ElemType *val)
{
DeterPointIsNull(stack);
if(EmptyStack(stack))//如果栈为空
{
return 0;//返回0
}
*val=stack->base[stack->top-1];//用val返回栈顶元素
return 1;
}
出栈操作如下:
int PopStack(pSeqstack stack,ElemType *val)
{
DeterPointIsNull(stack);
if(!GetTop(stack,val))//如果没有栈顶元素
{
return 0;//则不需要出栈
}
stack->top--;//栈顶标记--
return 1;
}
对栈的操作完成以后,我们需要释放栈空间,销毁栈:
void Destroystack(pSeqstack stack)
{
DeterPointIsNull(stack);
free(stack->base);
stack->base=NULL;
stack->top=stack->stacksize=0;
}
主函数测试:
int main()
{
Seqstack st;
int val;
InitSeqstack(&st);
for(int i=1;i<=5;i++)
{
Pushstack(&st,i);
}
for(int i=0;i<st.top;i++)
{
printf("%d ",st.base[i]);
}
printf("\n");
PopStack(&st,&val);
for(int i=0;i<st.top;i++)
{
printf("%d ",st.base[i]);
}
printf("\n");
Destroystack(&st);
for(int i=0;i<st.top;i++)
{
printf("%d ",st.base[i]);
}
printf("\n");
return 0;
}
运行结果:
队列的相关代码见下一篇《数据结构 &栈和队列(二)》