一、顺序栈
后进先出
1、顺序栈是利用一组地址连续的存储单元依次存放自栈底到栈顶的数据元素
2、因为顺序栈使用中所需的最大容量无法估计,所以一般初始化设空栈时,不应该限定栈的最大容量。而应该为栈分配一个基本容量,然后在应用过程中,当栈的空间不够使用再不断扩大
所以可以设两个#define,一个是初始,一个是扩大
3、注意:top指针是指向最后一个元素的下一个位置(指为空)
1.顺序栈的存储结构
1.分配存储空间首地址 –base
2.最后一个元素位置 –top
3.存储容量 –stacksize
2.顺序栈压栈弹栈基本操作
#include <stdio.h>
#define STACK_INIT 100
#define ADD_STACK 10
typedef int SElem;
typedef struct {
SElem *base;
SElem *top;
int stack_size;
}SqStack;
int length=0;
SqStack stackinit(SqStack s)//初始化
{
s.base=(SElem *)malloc(STACK_INIT*sizeof(SElem));
if(!s.base)
printf("error");
s.top=s.base;
s.stack_size=STACK_INIT;
return s;
}
SqStack push_stack(int e,SqStack s)//压栈
{
int i;
if(s.top>s.stack_size)
s.base=(SElem *)realloc(s.base,(s.stack_size+ADD_STACK)*sizeof(SElem));
*s.top=e;//与下一行可以总合并成一句*s.top++=e
s.top++;
length++;
return s;
}
SqStack pop_stack(SqStack s)//弹栈
{
int e;
if(s.top==s.base)
printf("error");
else{
s.top--;//与下一行可以合并成一句e=*--s.top
e=*s.top;
length--;
}
printf("出栈值为%d",e);
return s;
}
int GetTop(SqStack s)//得到
{
int e;
if(s.top==s.base)
return 0;
else{
e=*(s.top-1);
return e;
}
}
void display(SqStack s)//输出
{
int i;
for(i=0;i<length;i++)
{
printf("%d ",s.base[i]);
}
}
int main()
{
SqStack s;
int n,i,a;
int get;
s=stackinit(s);
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d",&a);
*s.top=a;
s.top++;
length++;
}
s=push_stack(9,s);
display(s);
printf("\n");
s=pop_stack(s);
printf("\n");
printf("当前栈:");
display(s);
printf("\n得到栈顶元素\n");
get=GetTop(s);
printf("%d",get);
return 0;
}
3.小注意(GetTop和Pop的区别)
得到栈顶元素值和弹栈的区别
//得到元素值
int GetTop(SqStack s)//得到
{
int e;
if(s.top==s.base)
return 0;
else{
e=*(s.top-1);
return e;
}
}
//弹栈
SqStack pop_stack(SqStack s)//弹栈
{
int e;
if(s.top==s.base)
printf("error");
else{
s.top--;//与下一行可以合并成一句e=*--s.top
e=*s.top;
length--;
}
printf("出栈值为%d",e);
return s;
}
GetTop函数在取栈顶的值的时候不能移动s.top和s.base(例如s.top++等),因为移动的话就代表了插入或者删除,所以得s.top-1而不能自减或自增。区别就是这样
二、链栈
即栈的链式存储结构,是运算受限的单链表,其插入和删除操作仅限制在表头位置上进行,故链栈没必要附加头结点(加也是可以的),栈顶指针即为头指针
链栈就是不断往栈顶插入元素,这个栈如果看做横向的话,最左边为栈顶,所以栈顶的next后就是第二个元素。(刚开始一直想不到p->next=s->top;这句,后来一想,栈顶其实就是第一个元素呀,然后向栈顶也就是第一个元素之前插入新节点,没毛病!)
还要注意的是用了两个typedef,注意一个是定义节点,一个是定义链栈
#include <stdio.h>
#define ok 1
#define error 0
typedef struct LNode{//定义节点
int data;
struct LNode *next;
}Node,*StackLNode;
typedef struct{//定义链栈
StackLNode *top;
}*LinkStack;
int count=0;//计数器
LinkStack StackInit()
{
StackLNode s;
s=(StackLNode)malloc(sizeof(Node));
if(s!=NULL){
return s;
}else{
printf("error");
return NULL;
}
}
LinkStack Stack_Push(LinkStack s,int e)//s是指向链栈首地址,p是指向节点指针
{
StackLNode p;
p=(StackLNode)malloc(sizeof(Node));
if(p==NULL)
{
printf("error\n");
}
p->data=e;
p->next=s->top;
s->top=p;
count++;
return s;
}
LinkStack Stack_Pop(LinkStack s)
{
int e;
StackLNode p;
p=s->top;
e=p->data;
s->top=p->next;
printf("%d",e);
count--;
return s;
}
int main()
{
LinkStack s;
StackLNode p;
int i,a;
s=StackInit();
s=Stack_Push(s,1);
s=Stack_Push(s,2);
s=Stack_Push(s,3);
//printf("s");
p=s->top;
for(i=0;i<count;i++)
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
s=Stack_Pop(s);
printf("\n");
p=s->top;
for(i=0;i<count;i++)
{
printf("%d ",p->data);
p=p->next;
}
return 0;
}