C语言数据结构——栈
什么是栈?
栈是限定仅在表的一端进行操作的线性表。其插入和删除仅能在表的一端进行。就像一个开口的瓶子,装载与拿出仅能在瓶口操作。固定不变的一端称为栈底,而插入、删除的那端称为栈顶,由于栈是单口进行操作,所以其新插入的元素只能放到栈顶,要删除的元素也一定是栈顶的元素,即最后入栈的元素一定先出栈。
栈的顺序存储
#include<stdio.h>
#include<malloc.h>
#define MAXSIZE 10
typedef struct
{
int data[MAXSIZE];
int top;
}SeqStack;
// 栈初始化
void Init_SeqStack(SeqStack **s)
{
// 开辟一块空间,并将该空间的地址赋给s
*s=(SeqStack*)malloc(sizeof(SeqStack));
(*s)->top=-1;
}
// 判栈为空
int Empty_SeqStack(SeqStack *s)
{
if(s->top==-1)
return 1;
else
return 0;
}
// 入栈
void Push_Stack(SeqStack *s,int x)
{
if(s->top==MAXSIZE-1)
printf("Stack is full!\n");
else
{
s->top++;
s->data[s->top]=x;
}
}
// 出栈
void Pop_SeqStack(SeqStack *s,int *x)
{
if(s->top==-1)
printf("栈为空!\n");
else
{
*x=s->data[s->top];
s->top--;
}
}
// 取栈顶元素
void Top_SeqStack(SeqStack *s,int *x)
{
if(s->top==-1)
printf("栈为空!\n");
else
{
*x=s->data[s->top];
printf("出栈成功!\n");
}
}
// 输出
void Output_SeqStack(SeqStack *s)
{
SeqStack *w;
int i;
printf("栈中的元素有:");
for(i=s->top;i>=0;i--)
printf("%d ",s->data[i]);
printf("\n");
}
void Menu()
{
puts("****************");
puts("1.初始化");
puts("2.判断栈为空");
puts("3.入栈");
puts("4.输出栈中元素");
puts("5.出栈");
puts("6.取栈顶元素");
puts("****************\n");
printf("Your choice is:");
}
// 主函数
int main()
{
SeqStack *s;
int x,e=-1,i;
while(e==-1)
{
Menu();
scanf("%d",&i);
puts("");
switch(i)
{
case 1:
Init_SeqStack(&s);
printf("初始化完成!\n");
break;
case 2:
printf("%d\n",Empty_SeqStack(s));
break;
case 3:
printf("请输入需要入栈的数据:");
scanf("%d",&x);
Push_Stack(s,x);
break;
case 4:
Output_SeqStack(s);
break;
case 5:
Pop_SeqStack(s,&x);
break;
case 6:
Top_SeqStack(s,&x);
printf("栈顶元素为:%d\n",x);
break;
case 0:
e=0;
break;
default:printf("选择有误,请重新选择 \n");
}
}
return 0;
}
栈的链式存储
#include<stdio.h>
#include<malloc.h>
/* 链栈后入先出,故采用头插法 */
typedef struct node
{
int data;
struct node *next;
}StackNode;
// 置空栈
void Init_LinkStack(StackNode **s)
{
*s=NULL; //此处只是将指针置空,避免产生指针悬挂
}
// 判断栈是否为空
int Empty_LinkStack(StackNode *s)
{
if(s==NULL)
return 1;
else
return 0;
}
// 入栈
void Push_LinkStack(StackNode **top,int x)
{
StackNode *p;
// 开辟一块空间,并将空间地址赋给p
p=(StackNode*)malloc(sizeof(StackNode));
// 给结点中的数据部分赋值
p->data=x;
// 使p指向top,如果p是第一个结点的话,p->next为NULL;
// 若p不是第一个结点,p->next为栈顶元素的地址,即p指向栈顶元素,p为新的栈顶元素
p->next=*top;
// 将新的栈顶元素的地址赋给top,使top依然指向栈顶元素
*top=p;
printf("入栈成功!\n");
}
// 出栈
void Pop_LinkStack(StackNode **top,int *x)
{
StackNode *p;
if(*top==NULL)
printf("栈为空!\n");
else
{
*x=(*top)->data;
p=*top; // 指向栈顶元素
printf("出栈的元素为:%d\n",p->data);
*top=(*top)->next;
free(p);
}
}
// 输出栈中元素
void Output_LineStack(StackNode *s)
{
StackNode *w;
w=s;
printf("栈中元素有:");
while((w->next)!=NULL)
{
printf("%d ",w->data);
w=w->next;
}
/*
这里输出是最后一个结点会被省去,原因是当w指向最后一个元素的前一个元
素时,会输出这个元素,接下来,会将最后一个元素的地址赋给w,再次进行
循环前的判定时,w->next=NULL,不会再执行循环,所以最后一个元素不会
再输出,这里只要自己加个就好
*/
printf("%d",w->data);
puts("");
}
void Menu()
{
puts("****************");
puts("1.初始化");
puts("2.判断栈为空");
puts("3.入栈");
puts("4.输出");
puts("5.出栈");
puts("****************\n");
printf("Your choice is:");
}
int main()
{
StackNode *s;
int i,e=-1,x;
while(e==-1)
{
Menu();
scanf("%d",&i);
puts("");
switch(i)
{
case 1:
Init_LinkStack(&s);
printf("初始化完成!\n");
break;
case 2:
printf("%d\n",Empty_LinkStack(s));
break;
case 3:
printf("请输入需要入栈的数据:");
scanf("%d",&x);
Push_LinkStack(&s,x);
break;
case 4:
Output_LineStack(s);
break;
case 5:
Pop_LinkStack(&s,&x);
break;
case 0:
e=0;
break;
default:printf("选择有误,请重新选择 \n");
}
}
return 0;
}