栈的操作算法实现.docx
《栈的操作算法实现.docx》由会员分享,可在线阅读,更多相关《栈的操作算法实现.docx(9页珍藏版)》请在冰点文库上搜索。
栈的操作算法实现
一顺序栈的实现
#definemaxsize6/*顺序栈的容量*/
typedefstruct
{ElementTypedata[maxsize];
inttop;
}SqStackTp;
顺序栈被定义为一个结构类型,它有两个域data和top。
data为一个一维数组,用于存储栈中元素,DataType为栈元素的数据类型(有待设定)。
top为int型,它的取值范围为0..sqstack_maxsize-1。
top=0表示栈空,top=sqstack_maxsize-1表示栈满。
对于图3-2顺序栈sqstack_maxsize应为6。
下面讨论栈的基本运算在顺序栈上的实现。
1.初始化:
初始化运算是将栈顶初始化为0;
intInitStack(SqStackTp*sq)
{sq->top=-1;return
(1);}
2.进栈:
进栈的主要操作是:
①栈顶下标加1;②将入栈元素放入到新的栈顶下标所指的位置上。
算法如下:
intPush(SqStackTp*sq,ElementTypex) /*若栈未满,将元素x入栈sq中;否则提示出错信息*/
{if(sq->top==maxsize-1) {printf("栈满");return(0);}
else {sq->top++;sq->data[sq->top]=x;return
(1);}
}
3.退栈:
退栈先要将栈顶元素取出,由参数返回,并将栈顶减1。
intPop(SqStackTp*sq,ElementType*x);
{if(sq->top==-1){printf("下溢");return(0);}
else{*x=sq->data[sq->top];sq->top--;return
(1);}
};
4.判栈空:
intEmptyStack(SqStackTp*sq) /*若栈空返回1;否则返回0*/
{ if(sq->top==-1)return
(1) elsereturn(0);
}
5.读栈顶元素:
intGetTop(SqStackTp*sq,ElementType*x) /*取栈顶元素,栈顶元素通过参数返回*/
{if(sq->top==-1)return(0);
else{*x=sq->data[sq->top];return
(1);}
}
6.顺序栈应用举例(进栈与出栈)
#include"stdio.h"
#defineElementTypechar
#definemaxsize40
typedefstruct
{ElementTypedata[maxsize];
inttop;
}SqStackTp;
intInitStack(SqStackTp*sq)
{sq->top=-1;return
(1);}
intPush(SqStackTp*sq,ElementTypex)
{if(sq->top==maxsize-1) {printf("栈满");return(0);}
else {sq->top++;sq->data[sq->top]=x;return
(1);}
}
intPop(SqStackTp*sq,ElementType*x)
{if(sq->top==-1){printf("下溢");return(0);}
else{*x=sq->data[sq->top];sq->top--;return
(1);}
}
intEmptyStack(SqStackTp*sq)
{if(sq->top==-1)return
(1); elsereturn(0);
}
/*主函数*/
voidmain()
{SqStackTpsq;
typedefchElementType;
InitStack(&sq);
for(ch='A';ch<='A'+12;ch++)
{Push(&sq,ch);printf("%c",ch);}
printf("\n");
while(!
EmptyStack(&sq))
{Pop(&sq,&ch);printf("%c",ch);}
printf("\n");
}
运行结果:
ABCDEFGHIJKLM
MLKJIHGFEDCBA
二链栈的实现
链栈类型定义如下:
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