• 数据结构入门————栈和队列(C语言/零基础/小白/新手+模拟实现+例题讲解)


    目录

    1.栈的概念

       ​编辑

    2.栈的作用

            1.函数递归

            2.表达式求值

    3.栈的模拟实现

    Stack.h

    Stack.c

    4.队列的概念

    5.队列的模拟实现

     Queue.h

    Queue.c

    6.例题

            1.一个栈的初始状态为空。现将元素1、2、3、4、5、A、B、C、D、E依次入栈,然后再依次出栈,则元素出栈的顺序是(B )。

            2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C)

            3.以下( B)不是队列的基本运算?


    1.栈的概念

            栈:是一种特殊的线性表,只允许固定的一端进行插入和删除操作。进行插入和删除的一端叫做栈顶,另一端叫做栈顶。栈中的数据元素遵守后进先出原则LIFO(Lats In Fast Out)。

            压栈:栈的插入操作,也叫入栈/进栈,压栈操作在栈顶进行的。

            出栈:栈的删除操作,也叫弹栈,出栈操作也是在栈底进行的。

       

    2.栈的作用

            1.函数递归

            2.表达式求值

            这里知识简单罗列出栈的简单应用,大家可以去B站上看相关视频,会比文章学起来更加轻松。

    21_2.2.4 堆栈应用_表达式求值_哔哩哔哩_bilibili

    第05周11--3.4栈和递归_哔哩哔哩_bilibili

    3.栈的模拟实现

            栈的实现可以是链式栈,也可以是顺序栈,相对而言顺序结构的实现更优一些,所以本文是基于顺序栈来实现的。

    Stack.h

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int STDataType;
    7. typedef struct Stack
    8. {
    9. STDataType* a;
    10. int top;
    11. int capacity;
    12. }ST;
    13. //初始化
    14. void StackInit(ST* pst);
    15. //销毁
    16. void StackDestroy(ST* pst);
    17. //添加
    18. void StackPush(ST* pst, STDataType x);
    19. //删除
    20. void StackPop(ST* pst);
    21. //top值
    22. STDataType StackTop(ST* pst);
    23. //有效元素个数
    24. int StackSize(ST* pst);
    25. //判断是否为空
    26. bool StackEmpty(ST* pst);

    Stack.c

    1. #include "Stack.h"
    2. //初始化
    3. void StackInit(ST* pst)
    4. {
    5. assert(pst);
    6. pst->a = NULL;
    7. pst->top = 0;
    8. pst->capacity = 0;
    9. }
    10. //销毁
    11. void StackDestroy(ST* pst)
    12. {
    13. assert(pst);
    14. free(pst->a);
    15. pst->a = NULL;
    16. pst->capacity = 0;
    17. pst->top = 0;
    18. }
    19. //添加
    20. void StackPush(ST* pst, STDataType x)
    21. {
    22. assert(pst);
    23. if (pst->top == pst->capacity)
    24. {
    25. int newcapacity = pst->capacity == 0 ? 4 : 2 * pst->capacity;
    26. STDataType* temp = (STDataType*)realloc(pst->a, sizeof(STDataType) * newcapacity);
    27. if (temp == NULL)
    28. {
    29. perror("realloc");
    30. return;
    31. }
    32. pst->a = temp;
    33. pst->capacity = newcapacity;
    34. }
    35. pst->a[pst->top] = x;
    36. pst->top++;
    37. }
    38. //删除
    39. void StackPop(ST* pst)
    40. {
    41. assert(pst);
    42. assert(pst->top > 0);
    43. pst->top--;
    44. }
    45. //top值
    46. STDataType StackTop(ST* pst)
    47. {
    48. assert(pst);
    49. assert(pst->top > 0);
    50. return pst->a[pst->top - 1];
    51. }
    52. //有效元素个数
    53. int StackSize(ST* pst)
    54. {
    55. assert(pst);
    56. return pst->top;
    57. }
    58. //判断是否为空
    59. bool StackEmpty(ST* pst)
    60. {
    61. assert(pst);
    62. return pst->top == 0;
    63. }

    4.队列的概念

            队列:也是一种特殊的线性表,要求只能一端进行插入操作,另一端进行删除操作,遵循先入先出原则FIFO(First In First Out)。

            入队列:进行插入的一端叫做队头。

            出队列:进行删除的一端叫队尾。

    5.队列的模拟实现

            队列的实现也可以基于链式结构或顺序结构,但是用链式结构效率更高,使用顺序结构,进行插入操作效率较低。本文基于链式结构实现队列。

     Queue.h

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int QNDataType;
    7. typedef struct QueueNode
    8. {
    9. QNDataType data;
    10. struct QueueNode* next;
    11. }QNode;
    12. typedef struct Queue
    13. {
    14. QNode* phead;
    15. QNode* ptail;
    16. int size;
    17. }Queue;
    18. //初始化
    19. void QueueInit(Queue* pq);
    20. //插入
    21. void QueuePush(Queue* pq, QNDataType x);
    22. //删除
    23. void QueuePop(Queue* pq);
    24. //获取头部元素
    25. QNDataType QueueFront(Queue* pq);
    26. //获取尾部元素
    27. QNDataType QueueBack(Queue* pq);
    28. //元素个数
    29. int QueueSize(Queue* pq);
    30. //判断是否为空
    31. bool QueueEmpty(Queue* pq);
    32. //销毁
    33. void QueueDestroy(Queue* pq);

    Queue.c

    1. #include "Queue.h"
    2. //初始化
    3. void QueueInit(Queue* pq)
    4. {
    5. assert(pq);
    6. pq->phead = NULL;
    7. pq->ptail = NULL;
    8. pq->size = 0;
    9. }
    10. //插入
    11. void QueuePush(Queue* pq, QNDataType x)
    12. {
    13. assert(pq);
    14. QNode* newnode = (QNode*)malloc(sizeof(QNode));
    15. if (newnode == NULL)
    16. {
    17. perror("mallloc");
    18. return;
    19. }
    20. newnode->data = x;
    21. newnode->next = NULL;
    22. if (pq->ptail == NULL)
    23. {
    24. pq->ptail = pq->phead = newnode;
    25. }
    26. else
    27. {
    28. pq->ptail->next = newnode;
    29. pq->ptail = newnode;
    30. }
    31. pq->size++;
    32. }
    33. //删除
    34. void QueuePop(Queue* pq)
    35. {
    36. assert(pq);
    37. assert(pq->phead);
    38. QNode* del = pq->phead;
    39. pq->phead = pq->phead->next;
    40. free(del);
    41. del = NULL;
    42. pq->size--;
    43. if (pq->phead == NULL)
    44. {
    45. pq->ptail = NULL;
    46. }
    47. }
    48. //获取头部元素
    49. QNDataType QueueFront(Queue* pq)
    50. {
    51. assert(pq);
    52. assert(pq->phead);
    53. return pq->phead->data;
    54. }
    55. //获取尾部元素
    56. QNDataType QueueBack(Queue* pq)
    57. {
    58. assert(pq);
    59. assert(pq->phead);
    60. return pq->ptail->data;
    61. }
    62. //元素个数
    63. int QueueSize(Queue* pq)
    64. {
    65. assert(pq);
    66. return pq->size;
    67. }
    68. //判断是否为空
    69. bool QueueEmpty(Queue* pq)
    70. {
    71. assert(pq);
    72. return pq->phead == NULL;
    73. }
    74. //销毁
    75. void QueueDestroy(Queue* pq)
    76. {
    77. assert(pq);
    78. /*while (!QueueEmpty(pq))
    79. {
    80. QueuePop(pq);
    81. }*/
    82. QNode* cur = pq->phead;
    83. while (cur)
    84. {
    85. QNode* next = cur->next;
    86. free(cur);
    87. cur = next;
    88. }
    89. pq->phead = pq->ptail = NULL;
    90. pq->size = 0;
    91. }

    6.例题

            1.一个栈的初始状态为空。现将元素12345ABCDE依次入栈,然后再依次出栈,则元素出栈的顺序是(B )。

    A 12345ABCDE

    B EDCBA54321

    C ABCDE12345

    D 54321EDCBA
    解析:如果你认真阅读并实现本文以上代码,这道题对你一定非常加单,12345ABCDE依次进栈,再依次出栈,顺序一定是B选项

         

            2.若进栈序列为 1,2,3,4 ,进栈过程中可以出栈,则下列不可能的一个出栈序列是(C

    A 1,4,3,2

    B 2,3,4,1

    C 3,1,4,2

    D 3,4,2,1

    解析:这道题是对上面那道题的一点小小升级,结题方法就是依次试试,经过验证,对于C选项,如果1想出栈,那么2,4必须先出栈。

            3.以下( B)不是队列的基本运算?

    A 从队尾插入一个新元素

    B 从队列中删除第i个元素

    C 判断一个队列是否为空

    D 读取队头元素的值

    解析:这道就是一个非常经典的概念题,把握好概念,队列只能一端进行插入,另一端进行删除,不支持随机访问,想要访问i节点,必须把i之前的节点出队列。

  • 相关阅读:
    迷你无人车 Gazebo 仿真
    c语言通信之网络通信
    Shell判断:模式匹配:case(二)
    Spring事务和事务传播机制
    Python自学笔记6-列表有哪些常用操作
    WebSecurityConfigurerAdapter过时的替代方式
    learning to rank 学习排名系统综述
    鸿蒙 harmonyos 线程 并发 总结 async promise Taskpool woker(二)多线程并发 Taskpool
    API自动化(三)
    JavaScript字符串③
  • 原文地址:https://blog.csdn.net/jupangMZ/article/details/134384717