栈?什么是栈? 栈的概念
栈是一种受约束的线性表,即特殊的线性表。
栈又称为堆栈。
更详细的来讲:栈是一种限定性线性表,是将线性表的插入和删除运算限制在仅为表的一端进行。
栈是一种先入后出,后入先出的结构。
为了详细的表示栈,我找了个图。
在图中,里面的元素是依次按a1,a2,·····an放入的,当出栈是an先出来,a1最后出来,达到了先入后出,先出后入的目的。
栈的基本操作
栈只能在一段(即栈顶,top)进行插入和删除操作。
表的另一端叫做栈底。
当栈中没有元素叫做空栈。
插入数据叫入栈(push)。
栈的插入操作称为进栈或入栈。
删除数据叫出栈(pop)。
栈的删除操作称为出栈或退栈。
一个很容易想到的想法是把栈用数组来进行实现。这样就引入了我们要介绍的栈的第一种结构:顺序栈
## 顺序栈
顺序栈的概念:用一组地址连续的存储空间依次存放从栈底到栈顶的数据元素,同时由于栈要在栈顶插入和删除元素,要必须要在栈顶设置一个位置指针top(栈顶指针)来动态的指示栈顶元素在顺序栈中的位置。
栈的顺序存储结构一般由一个一维数组和一个记录栈顶元素位置的变量组成。
顺序栈的结构
# define maxsize 100
typedef struct stack
{
element data[maxsize];
int top;
}stack,*pstack;
顺序栈的基本操作
1.初始化
void initstack(pstack s)
{
s->top=-1;
}
数组下标是从0开始的,top最初要指向-1.
2.入栈
void push(pstack s,element x)
{
if(s->top==maxsize-1)\\进栈要判断栈满
{
printf("栈满\n");
return;
}
else
{
s->data[++(s->top)]=x;
return;
}
}
3.出栈
element pop(pstack s)
{
if(s->top==-1)\\出栈要判断是否栈空
{
printf("栈空\n");
return ERROR;
}
else
{
return s->data[(s->top)--];
}
}
双端栈
双端栈是指用一个数组实现两个栈,将数组两端当做栈底,从两端往中间放元素,要求最大的利用数组空间。利用了栈“栈底位置不变,而栈顶位置动态变化”的特性。
两端分别设置两个栈顶指针top1和top2。指向左右填充部分最后一个元素。
由于左右可能填充的数量不一样,则判断栈满的条件是(假设左边top1,右边top2)top2-top1=1 。(即两个栈顶指针相遇)
双端栈的结构
# define maxsize 100
typedef struct stack
{
element data[maxsize];
int top1;
int top2;
}stack,*pstack;
1.初始化
void initstack(pstack s)
{
s->top1=-1;
s->top2=maxsize;
}
数组下标是0到maxsize,则最初两栈顶指针指向-1和maxsize(表示栈是空的)。
2.进栈
void push(pstack s,element x,int a)
{
if(s->top2-s->top1==1)\\两位置指针相遇则栈满
{
printf("栈满\n");
return;
}
if(a==1)
{
s->data[++(s->top1)]=x;
}
else if(a==2)
{
s->data[--(s->top2)]=x;
}
}
3.出栈
element pop(pstack s,int a)
{
if(a==1)\\确定是对左边进行出栈
{
if(s->top1==-1)
{
printf("栈空");
return ERROE;
}
else
{
return s->data[(s->top1)--];
}
}
else if(a==2)\\确定是对右边进行出栈
{
if(s->top2==maxsize)
{
printf("栈空");
return ERROE;
}
else
{
return s->data[(s->top2)++];
}
}
}
对于栈可以用数组来存储,同样对于栈我们也可以用单向链表来存储。
##链栈
栈的链式存储结构实际上就是一个单链表,叫链栈。插入和删除操作只能在链栈的栈顶操作。
对于一个单项链表是有两头的,如果对于链表的头作为栈顶插入和删除是方便的,对于链表的尾作为栈顶插入是方便的,但删除后你就把整个链表丢失了,你无法通过该节点访问上一个节点。
因此对于链栈,链表的头作为链栈的栈顶。
链栈的结构
typedef struct stack
{
element data;
struct stack *next;
}stack,*pstack;
1.构建一个栈的头结点(不带元素)
pstack creatstack()
{
pstack s;
s=(pstack)malloc(sizeof(stack));
s->next=NULL;
return s;
}
2.入栈(单链表的头插法)
void push(element x,pstack s)
{\由于不像数组一样有一定的内存空间,入栈时一直可调用内存空间不需要判断栈满
pstack p=(pstack)malloc(sizeof(stack));
p->data=x;
p->next=s->next;
s->next=p;
}
3.出栈(删除并返回栈顶元素)
element pop(pstack s)
{
pstack p;
element a;
if(s->next==NULL)
{
printf("栈空");
return NULL;
}
else
{
p=s->next;
s->next=p->next;
a=p->data;
free(p);
return a;
}
}