当前位置:   article > 正文

使用C语言实现链栈(带头结点和不带头结点)_带头结点的链栈

带头结点的链栈

目录

1.链栈

2.链栈的相关操作

(1)数据结构定义

(2)初始化和销毁

(3)入栈

(4)出栈

(5)主函数

(6)测试


1.链栈

链栈和单链表是差不多的,只是规定了入栈和出栈只能在表头一端进行(栈顶)。

注:链栈相比于顺序栈(动态)来说会比较方便的是不用担心插入节点是否出现空间满的问题,但是链栈中的节点之间不是连续的存储关系,逻辑上是连续的,但是在内存中的存储是分布散开的。

注:以上是带头结点的链栈。其实在实际中我们更多的时候是会关注的是栈的实际应用,而不是仅仅关注的是栈本身的简单实现,所以学会了栈的基本操作之后,学会将栈应用到实际中非常的重要,也是对自己的挑战。

使用C语言实现顺序栈

使用栈将十进制转换为八进制

使用栈判断括号是否匹配

使用栈判断回文字符串

使用C语言实现单链表(带头结点)

2.链栈的相关操作

(1)数据结构定义

  1. #include<stdlib.h>
  2. #include<stdio.h>
  3. #define MAXSIZE 10
  4. typedef int ElemType;
  5. typedef struct Linknode {
  6. ElemType data;
  7. struct Linknode*next;
  8. }*LiStack;
  9. //菜单栏
  10. void MenuSqStack(){
  11. printf("----------1.入栈元素--------\n");
  12. printf("----------2.获取栈顶元素----\n");
  13. printf("----------3.弹出栈顶元素----\n");
  14. printf("----------4.重新初始化------\n");
  15. printf("----------5.退出操作--------\n");
  16. }

(2)初始化和销毁

首先是带头结点:

  1. //初始化
  2. void InitLiStack(LiStack&s){
  3. s=(Linknode*)malloc(sizeof(Linknode));
  4. if(s==NULL){
  5. printf("内存分配失败!\n");
  6. return ;
  7. }
  8. s->next=NULL;
  9. printf("空间申请成功!\n");
  10. }
  11. //销毁
  12. void DestryLiStack(LiStack&s){
  13. Linknode*p=s->next;
  14. while(p!=NULL){
  15. Linknode*r=p;
  16. p->next=r->next;
  17. free(r);
  18. }
  19. free(s);
  20. printf("销毁成功!\n");
  21. }

不带头结点:

  1. //初始化
  2. void InitLiStack(LiStack&s){
  3. s=NULL;
  4. printf("申请空间成功!\n");
  5. }
  6. //销毁
  7. void DestryLiStack(LiStack&s){
  8. Linknode*p=s;
  9. while(p->next!=NULL){
  10. Linknode*r=p;
  11. p=r->next;
  12. free(r);
  13. }
  14. //最后一个节点特殊处理
  15. free(p);
  16. printf("销毁成功!\n");
  17. }

(3)入栈

带头结点:

  1. //入栈
  2. void PushLiStack(LiStack&s,ElemType e){
  3. Linknode*r=(Linknode*)malloc(sizeof(Linknode));
  4. r->data=e;
  5. r->next=s->next;
  6. s->next=r;
  7. printf("插入节点成功!\n");
  8. }

不带头结点:

相比于带头点的链栈来说相对较复杂,因为开始的时候s==NULL,所以首选需要将插入的第一个节点做特殊的处理。

  1. //入栈
  2. void PushLiStack(LiStack&s,ElemType e){
  3. //如果开始没有节点,特殊处理
  4. if(s==NULL){
  5. Linknode*r=(Linknode*)malloc(sizeof(Linknode));
  6. r->data=e;
  7. r->next=NULL;
  8. s=r;
  9. printf("插入节点成功!\n");
  10. return ;
  11. }
  12. Linknode*r=(Linknode*)malloc(sizeof(Linknode));
  13. //首先将头结点的值修改为要插入的值e,将r->data=s->data,最后直接在头结点后面插入节点 r即可
  14. r->data=s->data;
  15. s->data=e;
  16. r->next=s->next;
  17. s->next=r;
  18. printf("插入节点成功!\n");
  19. }

(4)出栈

带头结点:

  1. //出栈
  2. void PopLiStack(LiStack&s,ElemType&e){
  3. if(s->next==NULL){
  4. printf("栈空!\n");
  5. return;
  6. }
  7. Linknode*p=s->next;
  8. e=p->data;
  9. s->next=p->next;
  10. free(p);
  11. printf("出栈成功!\n");
  12. }
  13. //获取栈顶节点
  14. Linknode*GetElem(LiStack&s,ElemType&e){
  15. if(s->next==NULL){
  16. printf("栈空!\n");
  17. return NULL;
  18. }
  19. Linknode*p=s->next;
  20. e=p->data;
  21. }

不带头结点:

删除的操作其实不一定像我这样写,我只是做了一个最后一个节点的特殊处理。

  1. //出栈
  2. void PopLiStack(LiStack&s,ElemType&e){
  3. if(s==NULL){
  4. printf("栈空!\n");
  5. return;
  6. }
  7. //只有一个节点的时候特殊处理
  8. if(s->next==NULL){
  9. e=s->data;
  10. free(s);
  11. return ;
  12. }
  13. Linknode*p=s;
  14. e=p->data;
  15. s->next=p->next;
  16. free(p);
  17. printf("出栈成功!\n");
  18. }
  19. //获取栈顶节点
  20. Linknode*GetElem(LiStack&s,ElemType&e){
  21. if(s==NULL){
  22. printf("栈空!\n");
  23. return NULL;
  24. }
  25. Linknode*p=s;
  26. e=p->data;
  27. }

(5)主函数

主函数对于带头结点和不带头结点都是一样的。

  1. int main() {
  2. LiStack s;
  3. ElemType e;
  4. InitLiStack(s);
  5. while(1){
  6. int flag=0;
  7. bool popFlag=false;
  8. Linknode*p;
  9. MenuSqStack();
  10. printf("请输入操作: ");
  11. scanf("%d",&flag);
  12. switch(flag){
  13. case 1:
  14. printf("请输入元素(-1_end): ");
  15. scanf("%d",&e);
  16. while(e!=-1){
  17. PushLiStack(s,e);
  18. printf("请输入元素(-1_end): ");
  19. scanf("%d",&e);
  20. }
  21. break;
  22. case 2:
  23. p=GetElem(s,e);
  24. if(p!=NULL){
  25. printf("栈顶元素 = %d\n",e);
  26. }
  27. break;
  28. case 3:
  29. PopLiStack(s,e);
  30. printf("弹出栈顶元素 = %d\n",e);
  31. break;
  32. case 4:
  33. //首先要销毁之后再重新申请
  34. DestryLiStack(s);
  35. InitLiStack(s);
  36. break;
  37. default:
  38. DestryLiStack(s);
  39. printf("结束操作\n");
  40. }
  41. if(flag==5){
  42. break;
  43. }
  44. }
  45. return 0;
  46. }

(6)测试

首先是带头结点的测试;

不带头结点的测试:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/444090
推荐阅读
相关标签
  

闽ICP备14008679号