赞
踩
目录
链栈和单链表是差不多的,只是规定了入栈和出栈只能在表头一端进行(栈顶)。
注:链栈相比于顺序栈(动态)来说会比较方便的是不用担心插入节点是否出现空间满的问题,但是链栈中的节点之间不是连续的存储关系,逻辑上是连续的,但是在内存中的存储是分布散开的。
注:以上是带头结点的链栈。其实在实际中我们更多的时候是会关注的是栈的实际应用,而不是仅仅关注的是栈本身的简单实现,所以学会了栈的基本操作之后,学会将栈应用到实际中非常的重要,也是对自己的挑战。
- #include<stdlib.h>
- #include<stdio.h>
-
- #define MAXSIZE 10
-
- typedef int ElemType;
-
- typedef struct Linknode {
- ElemType data;
- struct Linknode*next;
- }*LiStack;
-
- //菜单栏
- void MenuSqStack(){
- printf("----------1.入栈元素--------\n");
- printf("----------2.获取栈顶元素----\n");
- printf("----------3.弹出栈顶元素----\n");
- printf("----------4.重新初始化------\n");
- printf("----------5.退出操作--------\n");
- }
首先是带头结点:
- //初始化
- void InitLiStack(LiStack&s){
- s=(Linknode*)malloc(sizeof(Linknode));
- if(s==NULL){
- printf("内存分配失败!\n");
- return ;
- }
- s->next=NULL;
- printf("空间申请成功!\n");
- }
- //销毁
- void DestryLiStack(LiStack&s){
- Linknode*p=s->next;
- while(p!=NULL){
- Linknode*r=p;
- p->next=r->next;
- free(r);
- }
- free(s);
- printf("销毁成功!\n");
- }
- //初始化
- void InitLiStack(LiStack&s){
- s=NULL;
- printf("申请空间成功!\n");
- }
- //销毁
- void DestryLiStack(LiStack&s){
- Linknode*p=s;
- while(p->next!=NULL){
- Linknode*r=p;
- p=r->next;
- free(r);
- }
- //最后一个节点特殊处理
- free(p);
- printf("销毁成功!\n");
- }
带头结点:
- //入栈
- void PushLiStack(LiStack&s,ElemType e){
- Linknode*r=(Linknode*)malloc(sizeof(Linknode));
- r->data=e;
- r->next=s->next;
- s->next=r;
- printf("插入节点成功!\n");
- }
相比于带头点的链栈来说相对较复杂,因为开始的时候s==NULL,所以首选需要将插入的第一个节点做特殊的处理。
- //入栈
- void PushLiStack(LiStack&s,ElemType e){
- //如果开始没有节点,特殊处理
- if(s==NULL){
- Linknode*r=(Linknode*)malloc(sizeof(Linknode));
- r->data=e;
- r->next=NULL;
- s=r;
- printf("插入节点成功!\n");
- return ;
- }
- Linknode*r=(Linknode*)malloc(sizeof(Linknode));
- //首先将头结点的值修改为要插入的值e,将r->data=s->data,最后直接在头结点后面插入节点 r即可
- r->data=s->data;
- s->data=e;
- r->next=s->next;
- s->next=r;
- printf("插入节点成功!\n");
- }
带头结点:
- //出栈
- void PopLiStack(LiStack&s,ElemType&e){
- if(s->next==NULL){
- printf("栈空!\n");
- return;
- }
- Linknode*p=s->next;
- e=p->data;
- s->next=p->next;
- free(p);
- printf("出栈成功!\n");
- }
-
- //获取栈顶节点
- Linknode*GetElem(LiStack&s,ElemType&e){
- if(s->next==NULL){
- printf("栈空!\n");
- return NULL;
- }
- Linknode*p=s->next;
- e=p->data;
- }
删除的操作其实不一定像我这样写,我只是做了一个最后一个节点的特殊处理。
- //出栈
- void PopLiStack(LiStack&s,ElemType&e){
- if(s==NULL){
- printf("栈空!\n");
- return;
- }
- //只有一个节点的时候特殊处理
- if(s->next==NULL){
- e=s->data;
- free(s);
- return ;
- }
- Linknode*p=s;
- e=p->data;
- s->next=p->next;
- free(p);
- printf("出栈成功!\n");
- }
-
- //获取栈顶节点
- Linknode*GetElem(LiStack&s,ElemType&e){
- if(s==NULL){
- printf("栈空!\n");
- return NULL;
- }
- Linknode*p=s;
- e=p->data;
- }
主函数对于带头结点和不带头结点都是一样的。
- int main() {
- LiStack s;
- ElemType e;
- InitLiStack(s);
- while(1){
- int flag=0;
- bool popFlag=false;
- Linknode*p;
- MenuSqStack();
- printf("请输入操作: ");
- scanf("%d",&flag);
- switch(flag){
- case 1:
- printf("请输入元素(-1_end): ");
- scanf("%d",&e);
- while(e!=-1){
- PushLiStack(s,e);
- printf("请输入元素(-1_end): ");
- scanf("%d",&e);
- }
- break;
- case 2:
- p=GetElem(s,e);
- if(p!=NULL){
- printf("栈顶元素 = %d\n",e);
- }
- break;
- case 3:
- PopLiStack(s,e);
- printf("弹出栈顶元素 = %d\n",e);
- break;
- case 4:
- //首先要销毁之后再重新申请
- DestryLiStack(s);
- InitLiStack(s);
- break;
- default:
- DestryLiStack(s);
- printf("结束操作\n");
- }
- if(flag==5){
- break;
- }
- }
- return 0;
- }
不带头结点的测试:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。