链栈:采用链式存储的栈。
优点:便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。
带头结点和不带头结点的链栈的操作会有部分不同:
这里采用的是带头结点的操作:
#include <stdio.h>
#include <stdlib.h>
typedef int Elemtype;
typedef struct LStack
{
Elemtype data;
struct LStack * next;
} LStack, * LinkStack;
LinkStack top;
//初始化
LinkStack Init_LinkStack()
{
LinkStack top=(LStack * )malloc (sizeof( LStack));
if(top!=NULL)//申请空间成功
top->next=NULL;//设置栈顶指针为空
return top;
}
//判栈空
int LinkStack_Empty(LinkStack top)
{
if(top->next==NULL)//检查栈顶指针的值
{
return 1;//栈S为空,函数返回1
}
else
{
return 0;
}
}
//入栈
int Push(LinkStack top,int t,Elemtype x)
//插入数据元素x为新的栈顶元素
{
LStack * p;
int i=0;
p=(LStack * )malloc(sizeof(LStack));
if(p==NULL)
{
return 0;//申请结点空间失败,插入失败,函数返回0
}//链栈的所有操作是在单链表的表头进行的,所以栈顶一直在第一个结点,只用头插法建立
while(x!=1111) {
p->data=x;//设置新结点的数据域
p->next=top->next;//设置新结点的指针城
top->next=p;//设置头结点指针城指向新的栈顶元素
t++;
return 1;//插入成功,函数返回1
}
}
//求栈长
int len(LinkStack top)
{
int len = 0;
while(top->next!=NULL)
{
++len;
top=top->next;
}
return len;
}
//出栈
int Pop(LinkStack top, Elemtype *x)
{ LStack * p;
if(top->next==NULL)
{
return 0;
}
else
{ //法一
*x = top->next->data;
top->next = top->next->next;
//法二
// p=top->next;//将原栈顶数据元素弹出并赋给p
// *x=p->data;//将原栈顶数据元素的数据赋值给x
// top->next=p->next;//top指向链栈中的下一个数据元素
// free (p);//释放原栈顶数据元素所占的空间
return 1;
}
}
//栈顶元素
int Get_top(LinkStack top)
{
if(top->next)
{
return top->next->data;
}
return -1;
}
void printStack(LinkStack top)
{
LStack *p;
p = top->next;
while(p)
{
printf("%d\n",p->data);
p = p->next;
}
}
//主函数
int main()
{
int i,t,x,a[20];
int e;
LinkStack top=Init_LinkStack();//初始化栈
x=LinkStack_Empty(top);//判栈空结果赋值给X
if(x=0)
{
printf("栈为空\n");
}
printf("您想创建的栈的长度为:\n");
scanf("%d",&e);
printf("请依次输入%d个数,开始入栈:\n",e);
for(i=0;i<e;i++)
{
scanf("%d",&a[i]);
Push(top,t,a[i]);
x=Get_top(top);
if(x!=-1)
{
printf("当前栈顶元素为%d\n",x);
}
}
printf("入栈结束\n");
printf("栈长为%d\n",len(top));
printf("当前栈中元素:第一个元素为栈顶:\n");
printStack(top);
printf("\n开始出栈:\n");
for (i=0;i<e;i++)
{
Pop(top,&t);
printf("->%d",t);
}
printf("\n");
printf("出栈后栈长为%d\n",len(top));
}