http://blog.csdn.net/fisherwan/article/details/20055179

首先要感谢这位大牛的一篇博客,地址如下:http://blog.csdn.net/hguisu/article/details/7674195

当然还有网上一些其他的资料,今天自己写了一下链式栈和链式队列的程序。其中在释放内存的时候遇到了些许问题,通过调,找出了原因,在这里我与大家分享一下。

(1)链式栈的相关代码块

Stack.h 头文件——定义了节点结构和链式栈结构,以及基本操作函数的声明部分

[cpp] view plain copy
  1. #ifndef _STACK_H_H
  2. #define _STACK_H_H
  3. typedef struct Node
  4. {
  5. int data;
  6. struct Node *pNext;
  7. }NODE, *pNODE;
  8. typedef struct Stack
  9. {
  10. pNODE top;
  11. }STACK, *pSTACK;
  12. //栈初始化
  13. void InitStack(pSTACK stack);
  14. //入栈
  15. void PushStack(pSTACK stack, int data);
  16. //出栈
  17. void PopStack(pSTACK stack, int *data);
  18. //判断栈是否为空
  19. int IsEmptyStack(pSTACK stack);
  20. //获得栈顶元素
  21. int GetTopStack(pSTACK stack);
  22. //释放内存
  23. void FreeMemory(pSTACK stack);
  24. #endif

Stack.cpp 源文件——定义链式栈的基本操作函数的定义

说明:一开始对栈初始化,但是这个栈是没有头节点的,直接定义了一个指针(top)刚开始指向NULL。

入栈的时候就是让top指针始终指向栈顶元素,入栈的节点的指针指向top指针,这样不断的进行入栈操作,节点不断增加,但是top指针一直是指针最后插入的节点。

出栈的时候就是从top指针指向的节点还是释放,然后让top指针指向被释放节点的下一个节点,这样节点不断释放,top指针不断向下移动。

所以,栈就成了一个“先进后出”的结构。

[cpp] view plain copy
  1. #include "Stack.h"
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. //栈初始化
  5. void InitStack(pSTACK stack)
  6. {
  7. stack->top = NULL;
  8. }
  9. //入栈
  10. void PushStack(pSTACK stack, int data)
  11. {
  12. pNODE p_new = (pNODE)malloc(sizeof(NODE));
  13. if (NULL == p_new)
  14. {
  15. printf("内存分配失败!\n");
  16. exit(EXIT_FAILURE);
  17. }
  18. p_new->data = data;
  19. p_new->pNext = stack->top; //这里要注意
  20. stack->top = p_new;
  21. }
  22. //出栈
  23. void PopStack(pSTACK stack, int *data)
  24. {
  25. pNODE p_delete = stack->top;
  26. if (IsEmptyStack(stack))
  27. exit(EXIT_FAILURE);
  28. *data = p_delete->data;
  29. stack->top = p_delete->pNext;
  30. free(p_delete);
  31. p_delete = NULL;
  32. }
  33. //判断栈是否为空
  34. int IsEmptyStack(pSTACK stack)
  35. {
  36. if (stack->top == NULL)
  37. return 1;
  38. else
  39. return 0;
  40. }
  41. //获得栈顶元素
  42. int GetTopStack(pSTACK stack)
  43. {
  44. int data;
  45. if (stack->top == NULL)
  46. exit(EXIT_FAILURE);
  47. data = stack->top->data;
  48. return data;
  49. }
  50. //释放内存
  51. void FreeMemory(pSTACK stack)
  52. {
  53. pNODE p_delete = NULL;
  54. while (stack->top != NULL)
  55. {
  56. p_delete = stack->top;
  57. stack->top = p_delete->pNext;
  58. free(p_delete);
  59. p_delete = NULL;
  60. }
  61. }

main.cpp  测试程序——通过简单的交互界面测试函数的功能

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include "Stack.h"
  3. int main(void)
  4. {
  5. int number, i, data, flag;
  6. STACK s;
  7. InitStack(&s);
  8. printf("请输入入栈个数:");
  9. scanf("%d", &number);
  10. for (i=1; i<number+1; i++)
  11. {
  12. printf("请输入第%d个栈点元素值:", i);
  13. scanf("%d", &data);
  14. PushStack(&s, data);
  15. }
  16. PopStack(&s ,&data);
  17. printf("出栈的元素值为:%d\n", data);
  18. data = GetTopStack(&s);
  19. printf("当前栈顶元素值为:%d\n", data);
  20. FreeMemory(&s);
  21. flag = IsEmptyStack(&s);
  22. if (flag)
  23. printf("内存释放成功!\n");
  24. else
  25. printf("内存释放失败!\n");
  26. return 0;
  27. }

(2)链式队列的相关代码

Queue.h 头文件——定义了节点结构和队列结构,以及链式队列的基本操作函数的声明

[cpp] view plain copy
  1. #ifndef _QUEUE_H_H
  2. #define _QUEUE_H_H
  3. typedef struct Node
  4. {
  5. int data;
  6. struct Node *pNext;
  7. }NODE, *pNODE;
  8. typedef struct Queue
  9. {
  10. pNODE front;
  11. pNODE rear;
  12. }QUEUE, *pQUEUE;
  13. //初始化队列
  14. void InitQueue(pQUEUE queue);
  15. //入队列
  16. void EnQueue(pQUEUE queue, int data);
  17. //出队列
  18. void DeQueue(pQUEUE queue, int *data);
  19. //判断队列是否为空
  20. int IsEmptyQueue(pQUEUE queue);
  21. //获得队头元素值
  22. int GetFrontQueue(pQUEUE queue);
  23. //释放内存
  24. void FreeMemory(pQUEUE queue);
  25. #endif

Queue.cpp 源文件——定义了基本操作函数的定义

说明:一开始对链式队列进行初始化,这里就创建了一个节点(但是记得后面释放内存的时候这里也要释放),创建了这个节点是为了方便后面的操作,这样一开始队列的头指针和尾指针都指向了这个节点,但是此时的队列是空的,就像循环链表里头节点不参与运行是一样的道理。

入队列的时候就是进入的节点排在初始化时创建的节点后面,然后尾指针指针指着新进入的节点,但是头指针不动,节点不断进入队列,尾指针不断向后移动,保持尾指针一直指着刚进入的节点。

出队列的时候就是让头指针指向的节点的指针指向要释放节点的下一个节点,节点不断出队列,这里头指针实质上并没有移动,但是它指向的节点的指针一直在变化,一直保持者指向要释放节点的下一个节点,但是这里要注意,就是当队列中只剩下一个节点的时候(这里不包含初始化创建的那个节点),释放了这个节点以后尾指针成了野指针,那么这个时候就要让尾指针和头指针指向同一位置,那么这样判断队列是否为空的时候就是空了。

[cpp] view plain copy
  1. //链式队列代码
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include "Queue.h"
  5. //初始化队列
  6. void InitQueue(pQUEUE queue)
  7. {
  8. queue->front = (pNODE)malloc(sizeof(NODE));
  9. queue->front->data = 0;
  10. queue->front->pNext = NULL;
  11. if (NULL == queue->front)
  12. {
  13. printf("内存分配失败!\n");
  14. exit(EXIT_FAILURE);
  15. }
  16. queue->rear = queue->front;
  17. }
  18. //入队列
  19. void EnQueue(pQUEUE queue, int data)
  20. {
  21. pNODE p_new = (pNODE)malloc(sizeof(QUEUE));
  22. if (NULL == p_new)
  23. {
  24. printf("内存分配失败!\n");
  25. exit(EXIT_FAILURE);
  26. }
  27. p_new->data = data;
  28. p_new->pNext = NULL;
  29. queue->rear->pNext = p_new;
  30. queue->rear = p_new;
  31. }
  32. //出队列
  33. void DeQueue(pQUEUE queue, int *data)
  34. {
  35. if (IsEmptyQueue(queue))
  36. exit(EXIT_FAILURE);
  37. pNODE p_delete = queue->front->pNext;
  38. *data = p_delete->data;
  39. queue->front->pNext = p_delete->pNext;
  40. if (p_delete->pNext == NULL)
  41. queue->rear = queue->front;
  42. free(p_delete);
  43. p_delete = NULL;
  44. }
  45. //判断队列是否为空
  46. int IsEmptyQueue(pQUEUE queue)
  47. {
  48. if (queue->front == queue->rear)
  49. return 1;
  50. else
  51. return 0;
  52. }
  53. //获得队头元素值
  54. int GetFrontQueue(pQUEUE queue)
  55. {
  56. int data;
  57. if (IsEmptyQueue(queue))
  58. exit(EXIT_FAILURE);
  59. data = queue->front->data;
  60. return data;
  61. }
  62. //释放内存
  63. void FreeMemory(pQUEUE queue)
  64. {
  65. pNODE p_delete = NULL;
  66. while (queue->front != NULL)
  67. {
  68. p_delete = queue->front;
  69. queue->front = p_delete->pNext;
  70. if (p_delete->pNext == NULL) //如果到达最后一个节点时,队尾指针为NULL
  71. queue->rear = NULL;
  72. free(p_delete);
  73. p_delete = NULL;
  74. }
  75. }

main.cpp 测试程序——简单的交互界面测试函数功能

[cpp] view plain copy
  1. #include <stdio.h>
  2. #include "Queue.h"
  3. int main(void)
  4. {
  5. int number, i, data, flag;
  6. QUEUE q;
  7. InitQueue(&q);
  8. flag = IsEmptyQueue(&q);
  9. if (flag)
  10. printf("初始化成功!\n");
  11. printf("请输入入队列个数:");
  12. scanf("%d", &number);
  13. for (i=1; i<number+1; i++)
  14. {
  15. printf("请输入第%d个队点元素值:", i);
  16. scanf("%d", &data);
  17. EnQueue(&q, data);
  18. }
  19. DeQueue(&q ,&data);
  20. printf("出队列的元素值为:%d\n", data);
  21. data = GetFrontQueue(&q);
  22. printf("当前栈顶元素值为:%d\n", data);
  23. FreeMemory(&q);
  24. if (q.front == NULL && q.rear == NULL)
  25. printf("内存释放成功!\n");
  26. else
  27. printf("内存释放失败!\n");
  28. return 0;
  29. }

(C语言版)栈和队列(一)——实现链式栈和链式队列的基本操作以及遇到的问题相关推荐

  1. 数据结构 - 队列简介 及 1个简单的c语言链式队列代码实现

    1. 队列的定义 所谓队列(queue)就是一种能实现"先进先出"的一种线性存储结构. 跟栈有点类似,  例如栈只有1个出入口, 任何元素进入或者离开栈都必须经过同1个出入口(栈顶 ...

  2. c语言建立队列(顺序队列、循化队列和链式队列)

    c语言建立队列 一.顺序队列 队列的顺序存储结构 顺序队列的讨论 "下溢"现象 "真上溢"现象 "假上溢"现象 二.如何解决"假上 ...

  3. 数据结构(八) -- C语言版 -- 栈和队列 - 队列的设计与实现

    我让你知道我有啥 零.读前说明 一.队列的概述 二.队列的操作 三.队列的两种存储结构的模型概述 四.顺序存储结构的队列及实现 4.1.顺序存储结构的传统队列简易实现与测试 4.2.顺序存储结构的队列 ...

  4. 数据结构——链式队列解析(C语言版)

    摘自:数据结构学习--链式队列解析(C语言版) 作者:正弦定理 发布时间:2020-11-26 21:07:08 网址:https://blog.csdn.net/chinesekobe/articl ...

  5. 刁肥宅手笔:纯C语言实现链式队列的相关操作

    先上图,以图服人: 图一 程序运行截图1 图二 程序运行截图2 上代码: 头文件LinkQueue.h: /*LinkQueue.h*/#ifndef LINKQUEUE_H_INCLUDED #de ...

  6. (c语言数据结构)用链式队列的方式实现输入12345,输出12345操作——期末数据结构程序设计

    用链式队列的方式实现输入12345,输出12345操作 文章目录 用链式队列的方式实现输入12345,输出12345操作 1.队列的定义 2.队列的初始化 3.判空操作 4.入队操作 5.出队操作 6 ...

  7. 【数据结构】链式队列的实现(C语言)

    队列的链式存储称为链式队列.链式队列就是一个特殊的单链表,对于这种特殊的单链表,它的插入和删除操作规定在单链表的不同端进行.链式队列的队首和队尾指针分别用front和rear表示. 链式队列要掌握以下 ...

  8. c语言队列(顺序队列,循环队列,链式队列)

    顺序队列 1.初始化: front=-1; rear=-1; 2.判空条件 font=rear; 3.队列已满条件 rear=max-1; 代码: #include<stdio.h> #i ...

  9. c语言定义链式队列用菜单,数据结构之---C语言实现链式队列

    //链式队列的存储 //杨鑫 #include #include typedef int QElemType; //定义节点 typedef struct QNode { QElemType data ...

最新文章

  1. iis7 文件服务器搭建,iis7 ftp服务器搭建
  2. 田志刚:人跟人差距怎么那么大呢?
  3. Mantis使用说明
  4. Flutter实战之(Clubhouse App)
  5. bitnamigitlab_Bitnami Gitlab 修改端口
  6. LeetCode 553. 最优除法(数学)
  7. java动态数据国际化_基于 AOP 的动态数据国际化框架的设计与实现
  8. 融合智能将成时代方舟?中科创达技术大会向未来答疑
  9. 好看的android动画效果
  10. python处理工资_python的工资
  11. 2022最新个人所得税计算(附代码)
  12. SVG 绘制可交互的中国地图
  13. 【Unity3D自学记录】Unity3D游戏开发之自由视角状态下的角色控制(一)
  14. python plot画图函数_详解pandas.DataFrame.plot() 画图函数
  15. 图片提取文字很神奇?试试三步实现OCR!
  16. GD2016noip获奖名单
  17. 搭建jpress个人博客
  18. 17.12.2B组总结
  19. 地铁框架保护的原理_地铁直流系统中框架保护原理及处理程序
  20. 腾讯云企业邮箱设置别名

热门文章

  1. 【转载】关于 Google Chrome 中的全屏模式和 APP 模式
  2. 穆里尼奥:与范加尔风格不同,转变需要时间
  3. 浅谈块级元素和内联元素的嵌套规则
  4. 建立apk定时自动打包系统第三篇——代码自动更新、APP自动打包系统
  5. 【7】jQuery学习——入门jQuery选择器之过滤选择器-可见性过滤选择器
  6. 评价viper4android,ViPer4android. FX顶级音效!
  7. blue html中转换,Vue/Vue中Html和Markdown互相转换/README.md · bluemoon/LearningNotes - Gitee.com...
  8. android studio闪退代码不报错_代码不报错,不代表真的没错
  9. mysql中distinct关键字,MySQL关键字Distinct的详细介绍
  10. linux里hba状态_Windows和Linux系统查看HBA卡wwn号的方法 | 系统之家官网