scanf("%d",&x);
top=PushStack(top,x);}
printf("进栈已完成!
\n");
printf("\n输出栈为:
");
Print();
break;
case'3':
printf("\n操作之前的输出栈为:
");
Print();
top=PopStack(top);
printf("\n操作过后的输出栈为:
");
Print();
break;
case'4':
printf("\n输出栈为:
");
Print();
if(top!
=NULL)
printf("\n栈顶元素是:
%d\n",GetStackTop(top));
else
printf("\n栈是空的,没有元素!
");
break;
case'5':
break;
default:
printf("\n输入的字符不对,请重新输入!
");
break;
}
getchar();
}while(m!
='5');
}
链栈类型定义如下:
typedefstructnode
{ElementTypedata;
structnode*next;
}node;
node*LStackTp;
下面讨论栈的基本运算在链栈上的实现。
1.初始化:
栈初始化的作用是设置一个空栈。
而一个空的链栈可以用栈顶指针为NULL来表示。
voidInitStack(LStackTp*ls)
{ *ls=NULL;
}
2.进栈:
进栈算法的基本步骤包括:
①申请一个新结点,并将x的值送入该结点的data域;
②将该结点链入栈中使之成为新的栈顶结点。
voidPush(LStackTp*ls,ElementTypex)
{LStackTpp;
p=/*申请一个新结点*/
p->data=(LStackTp)malloc(sizeof(node));x; /*元素的值填入新结点的data域*/
p->next=*ls;/*原栈顶链入新结点的next域*/
*ls=p; /*新结点成为新的栈顶*/
}
3.退栈:
退栈算法的基本步骤包括:
①栈顶结点的data域的值由参数返回,并取下栈顶结点,让它的下一个结点成为新的栈顶;
②将取出的栈顶结点空间释放。
intPop(LStackTp*ls,ElementType*x)
/*栈顶元素通过参数返回,它的直接后继成为新的栈顶*/
{LStackTpp;
if((*ls)!
=NULL)
{p=*ls; *x=p->data;/*栈顶元素通过参数返回*/
*ls=p->next;/*原栈顶的下一个结点成为新的栈顶*/
free(p); /*释放原栈顶结点空间*/
return1;}
elsereturn0;
}
4.判栈空:
intEmptyStack(LStackTp*ls)/*若栈为空则返回值1,否则返回值0*/
{ if(*ls==NULL)return
(1);elsereturn(0);}
5.读栈顶元素:
intGetTop(LStackTp*ls,ElementType*x)/*取栈顶元素*/
{if((*ls)!
=NULL){*x=(*ls)->data;return1;}elsereturn0; }
6.链栈应用举例(进栈与出栈)
1) #include"stdio.h"
#defineElementTypechar
#definesizesizeof(node)
typedefstruct
{ElementTypedata;
structnode*next;
}node;
node*LStackTp;
voidInitStack(LStackTp*ls)
{ *ls=NULL;
}
voidPush(LStackTp*ls,ElementTypex)
{LStackTpp;
p=(LStackTp)malloc(size);
p->data=x;
p->next=*ls;
*ls=p;
}
intPop(LStackTp*ls,ElementType*x)
{LStackTpp;
if((*ls)!
=NULL)
{p=*ls;*x=p->data;*ls=(*ls)->next;
free(p);return
(1);
}elsereturn(0);
}
intEmptyStack(LStackTpls)
{
if(ls==NULL)return
(1);
elsereturn(0);
}
voidmain()
{LStackTpls;
ElementTypech;
InitStack(ls);
for(ch='A';ch<='A'+12;ch++)
{Push(&ls,ch);printf("%c",ls->data);}
printf("\n");
while(!
EmptyStack(ls))
{Pop(&ls,&ch);printf("%c",ch);}
printf("\n");
}
运行结果:
ABCDEFGHIJKLM
MLKJIHGFEDCBA
2)写一个算法,借助栈将一个带头结点的单链表倒置。
head
─
→
头
─
→
a1
─
→
a2
─
→......
→
an
NULL
分析:
这里可利用栈的特征,先沿着链表从头至尾扫描一遍,将链表的每个结点的data域的值依次进栈,然后再沿着链表从头至尾扫描一遍,同时栈中元素依次出栈,并填入到链表的每个结点的data域中。
算法如下:
voidreverse_list(LkListTp*head)
{LStackTpls,p;
ElementTypex;
InitStack(&ls);/*初始化链栈*/
p=(*head)->next;
while(p!
=NULL)
{Push(&ls,p->data);p=p->next;}
p=(*head)->next;
while(!
EmptyStack(ls))
{Pop(&ls,&x);p->data=x;p=p->next;}
}
实现程序如下:
(用链栈实现单链表倒置)
#include"stdio.h"
#defineElementTypechar
#definesizesizeof(node)
typedefstruct {
ElementTypedata;
structnode*next;
}node;
node*LkListTp;
voidInitStack(LStackTp*ls)
{*ls=NULL;}
voidPush(LStackTp*ls,ElementTypex)
{LStackTpq;
q=(LStackTp)malloc(size);/*申请一个新结点*/
q->data=x;/*元素的值填入新结点的data域*/
q->next=*ls;/*原栈顶链入新结点的next域*/
*ls=q;/*新结点成为新的栈顶*/
}
intPop(LStackTp*ls,ElementType*x)
/*栈顶元素通过参数返回,它的直接后继成为新的栈顶*/
{LStackTpp;
if((*ls)!
=NULL)
{p=*ls;*x=p->data;
*ls=(*ls)->next;/*原栈顶的下一个结点成为新的栈顶*/
free(p);/*释放原栈顶结点空间*/
return
(1);
}elsereturn(0);
}
intEmptyStack(LStackTpls)/*若栈为空则返回值1,否则返回值0*/
{
if(ls==NULL)return
(1);
elsereturn(0);
}
voidreverse_list(LkListTp*head)
{LStackTpls,p;
ElementTypex;
InitStack(&ls);/*初始化链栈*/
p=(*head)->next;
while(p!
=NULL)
{Push(&ls,p->data);p=p->next;}
p=(*head)->next;
while(!
EmptyStack(ls))
{Pop(&ls,&x);p->data=x;p=p->next;}
}
LkListTpcreate_lklist2()
/*直接建表算法。
p是一个pointer类型的变量,用来指示链入位置*/
{
LkListTpp,q,s,head;
ElementTypex;
head=(LkListTp)malloc(size);/*生成头结点*/
p=head;/*尾指针置初值*/
scanf("%c",&x);/*读入第一个元素*/
while(x!
='?
')/*输入的不是结束标志时继续链入*/
{
q=(LkListTp)malloc(size);q->data=x;/*生成一个新结点*/
p->next=q;/*新结点链入*/
p=q;/*修改尾指针指向新的表尾*/
scanf("%c",&x);/*读入下一个元素*/
}
p->next=NULL;return(head);/*置尾结点标志*/
}
voidmain()
{
LkListTpp,q,head;
ElementTypex;
printf("\ninputLkList:
");
head=create_lklist2();
reverse_list(&head);
printf("\noutputLkList:
");
p=head->next;
while(p!
=NULL)
{printf("%c",p->data);p=p->next;}
printf("\n");
}
运行结果:
inputLkList:
ABCDEFG?
outputLkList:
GFEDCBA