• <栈和队列及模拟实现>——《Data Structure in C Train》


    目录

    详细实现链接:

    <栈(动态版)>《数据结构(C语言版)》

    <队列(链式)>《数据结构(C语言版)》

    1.分析实现功能、感受栈和队列的实现结构:

    1.1栈的实现结构方式:​

    1.2 队列的实现方式:

    2.完整源码:

    2.1栈的模拟实现: 

    Stack.h:

    Stack.c:

    Test.c:

    2.2 队列的模拟实现:

    Queue.h:

    Queue.c:

    Test.c:

     3.判断括号匹配程序:

    后记:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                           ——By 作者:新晓·故知


    详细实现链接:

    <栈(动态版)>《数据结构(C语言版)》

    <队列(链式)>《数据结构(C语言版)》


    1.分析实现功能、感受栈和队列的实现结构:

    1.1栈的实现结构方式:

    数组实现栈的结构:

    相当于顺序表的尾插、尾删,用尾作栈顶,非常合适!从CPU预加载命中角度分析,数组实现的性能更好一些!

    缺点:空间不够时需要增容。

    单向链表实现栈的结构:

    用头结点作栈底,这样使得入栈和出栈效率都是O(1)。

    双向链表实现栈的结构:

    用尾作栈顶。

    1.2 队列的实现方式:

    数组实现队列的结构:

    不适合,队头出数据需要挪动数据

    单链表实现队列的结构:

    无需使用带头结点的单链表即可完成,带头结点是为了减少二级指针的使用。

    tail是移动的,方便尾部操作直接找到。head方便头部操作直接找到。

     

    数据结构的设计比较灵活,正所谓:“树挪死,人挪活”。在学习中,不要一味地“守死”,而要学会“变活。”

    2.完整源码:

    2.1栈的模拟实现: 

    Stack.h:

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef char STDataType;
    7. typedef struct Stack
    8. {
    9. STDataType* a; //通过数组实现栈的结构
    10. int top;
    11. int capacity;
    12. }ST;
    13. //初始化
    14. void StackInit(ST* ps);
    15. //释放内存、销毁空间
    16. void StackDestory(ST* ps);
    17. // 入栈
    18. void StackPush(ST* ps, STDataType x);
    19. // 出栈
    20. void StackPop(ST* ps);
    21. //取栈顶数据
    22. STDataType StackTop(ST* ps);
    23. //栈的大小
    24. int StackSize(ST* ps);
    25. //判空
    26. bool StackEmpty(ST* ps);

    Stack.c:

    1. #include"Stack.h"
    2. //初始化
    3. void StackInit(ST* ps)
    4. {
    5. assert(ps);
    6. ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
    7. if (ps->a == NULL)
    8. {
    9. printf("malloc fail!\n");
    10. exit(-1);
    11. }
    12. ps->capacity = 4;
    13. ps->top = 0; //这使得top最终指向的是栈顶的后一个位置。若top=-1,则最终指向的是栈顶。
    14. }
    15. //释放内存、销毁空间
    16. void StackDestory(ST* ps)
    17. {
    18. assert(ps);
    19. free(ps->a);
    20. ps->a = NULL;
    21. ps->top = ps->capacity = 0;
    22. }
    23. // 入栈
    24. void StackPush(ST* ps, STDataType x)
    25. {
    26. assert(ps);
    27. // 满了->增容
    28. if (ps->top == ps->capacity)
    29. {
    30. STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));
    31. if (tmp == NULL)
    32. {
    33. printf("realloc fail!\n");
    34. exit(-1);
    35. }
    36. else
    37. {
    38. ps->a = tmp;
    39. ps->capacity *= 2;
    40. }
    41. }
    42. ps->a[ps->top] = x;
    43. ps->top++;
    44. }
    45. // 出栈
    46. void StackPop(ST* ps)
    47. {
    48. assert(ps);
    49. // 栈空了,再调用Pop,就会直接中止程序报错
    50. assert(ps->top > 0);
    51. //ps->a[ps->top - 1] = 0; //置为0只考虑了int型等,若为char、double等就不适用了。
    52. ps->top--;
    53. }
    54. //取栈顶数据
    55. STDataType StackTop(ST* ps)
    56. {
    57. assert(ps);
    58. // 栈空了,再调用Top,就会直接中止程序报错
    59. assert(ps->top > 0);
    60. return ps->a[ps->top - 1];
    61. }
    62. //求栈大小
    63. int StackSize(ST* ps)
    64. {
    65. assert(ps);
    66. return ps->top;
    67. }
    68. //判空
    69. bool StackEmpty(ST* ps)
    70. {
    71. assert(ps);
    72. return ps->top == 0;
    73. }
    74. //判断括号是否匹配算法
    75. bool isValid(char* s) {
    76. ST st;
    77. StackInit(&st);
    78. while (*s != '\0')
    79. {
    80. switch (*s)
    81. {
    82. case '{':
    83. case '[':
    84. case '(':
    85. {
    86. StackPush(&st, *s);
    87. ++s;
    88. break;
    89. }
    90. case '}':
    91. case ']':
    92. case ')':
    93. {
    94. if (StackEmpty(&st))
    95. {
    96. StackDestory(&st);
    97. return false;
    98. }
    99. char top = StackTop(&st);
    100. StackPop(&st);
    101. // 不匹配
    102. if ((*s == '}' && top != '{')
    103. || (*s == ']' && top != '[')
    104. || (*s == ')' && top != '('))
    105. {
    106. StackDestory(&st);
    107. return false;
    108. }
    109. else // 匹配
    110. {
    111. ++s;
    112. }
    113. break;
    114. }
    115. default:
    116. break;
    117. }
    118. }
    119. bool ret = StackEmpty(&st);
    120. StackDestory(&st);
    121. return ret;
    122. }

    Test.c:

    1. #include"Stack.h"
    2. int main()
    3. {
    4. ST st;
    5. StackInit(&st);
    6. StackPush(&st, 9);
    7. StackPush(&st, 5);
    8. StackPush(&st, 2);
    9. StackPush(&st, 7);
    10. printf("%d \n", StackEmpty(&st));
    11. printf("%d \n", StackSize(&st));
    12. while (!StackEmpty(&st))
    13. {
    14. printf("%d ", StackTop(&st));
    15. StackPop(&st);
    16. }
    17. printf("\n");
    18. StackDestory(&st);
    19. return 0;
    20. }

    2.2 队列的模拟实现:

    Queue.h:

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. #include
    6. typedef int QDataType;
    7. typedef struct QueueNode
    8. {
    9. struct QueueNode* next;
    10. QDataType data;
    11. }QNode;
    12. typedef struct Queue
    13. {
    14. QNode* head;
    15. QNode* tail;
    16. }Queue;
    17. //初始化
    18. void QueueInit(Queue* pq);
    19. //销毁
    20. void QueueDestory(Queue* pq);
    21. // 队尾入
    22. void QueuePush(Queue* pq, QDataType x);
    23. // 队头出
    24. void QueuePop(Queue* pq);
    25. //取队列头元素
    26. QDataType QueueFront(Queue* pq);
    27. //取队列尾元素
    28. QDataType QueueBack(Queue* pq);
    29. //队列大小
    30. int QueueSize(Queue* pq);
    31. //队列判空
    32. bool QueueEmpty(Queue* pq);

    Queue.c:

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

    Test.c:

    1. #include"Queue.h"
    2. void TestQueue()
    3. {
    4. Queue q;
    5. QueueInit(&q);
    6. QueuePush(&q, 1);
    7. QueuePush(&q, 2);
    8. printf("%d ", QueueFront(&q));
    9. QueuePop(&q);
    10. printf("%d ", QueueFront(&q));
    11. QueuePop(&q);
    12. QueuePush(&q, 3);
    13. QueuePush(&q, 4);
    14. while (!QueueEmpty(&q))
    15. {
    16. printf("%d ", QueueFront(&q));
    17. QueuePop(&q);
    18. }
    19. printf("\n");
    20. QueueDestory(&q);
    21. }
    22. int main()
    23. {
    24. TestQueue();
    25. return 0;
    26. }

     3.判断括号匹配程序:

    1. #include
    2. #include
    3. #include
    4. #include
    5. ///
    6. //声明
    7. typedef char STDataType;
    8. typedef struct Stack
    9. {
    10. STDataType* a;
    11. int top;
    12. int capacity;
    13. }ST;
    14. //
    15. //定义
    16. //初始化
    17. void StackInit(ST* ps)
    18. {
    19. assert(ps);
    20. ps->a = (STDataType*)malloc(sizeof(STDataType) * 4);
    21. if (ps->a == NULL)
    22. {
    23. printf("malloc fail\n");
    24. exit(-1);
    25. }
    26. ps->capacity = 4;
    27. ps->top = 0;
    28. }
    29. //销毁
    30. void StackDestory(ST* ps)
    31. {
    32. assert(ps);
    33. free(ps->a);
    34. ps->a = NULL;
    35. ps->top = ps->capacity = 0;
    36. }
    37. // 入栈
    38. void StackPush(ST* ps, STDataType x)
    39. {
    40. assert(ps);
    41. // 满了-》增容
    42. if (ps->top == ps->capacity)
    43. {
    44. STDataType* tmp = (STDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(STDataType));
    45. if (tmp == NULL)
    46. {
    47. printf("realloc fail\n");
    48. exit(-1);
    49. }
    50. else
    51. {
    52. ps->a = tmp;
    53. ps->capacity *= 2;
    54. }
    55. }
    56. ps->a[ps->top] = x;
    57. ps->top++;
    58. }
    59. // 出栈
    60. void StackPop(ST* ps)
    61. {
    62. assert(ps);
    63. // 栈空了,调用Pop,直接中止程序报错
    64. assert(ps->top > 0);
    65. //ps->a[ps->top - 1] = 0;
    66. ps->top--;
    67. }
    68. //去栈顶元素
    69. STDataType StackTop(ST* ps)
    70. {
    71. assert(ps);
    72. // 栈空了,调用Top,直接中止程序报错
    73. assert(ps->top > 0);
    74. return ps->a[ps->top - 1];
    75. }
    76. //求栈的的大小
    77. int StackSize(ST* ps)
    78. {
    79. assert(ps);
    80. return ps->top;
    81. }
    82. //判空
    83. bool StackEmpty(ST* ps)
    84. {
    85. assert(ps);
    86. return ps->top == 0;
    87. }
    88. //判断括号是否匹配
    89. bool isValid(char* s) {
    90. ST st;
    91. StackInit(&st);
    92. while (*s != '\0')
    93. {
    94. switch (*s)
    95. {
    96. case '{':
    97. case '[':
    98. case '(':
    99. {
    100. StackPush(&st, *s);
    101. ++s;
    102. break;
    103. }
    104. case '}':
    105. case ']':
    106. case ')':
    107. {
    108. if (StackEmpty(&st))
    109. {
    110. StackDestory(&st);
    111. return false;
    112. }
    113. char top = StackTop(&st);
    114. StackPop(&st);
    115. // 不匹配
    116. if ((*s == '}' && top != '{')
    117. || (*s == ']' && top != '[')
    118. || (*s == ')' && top != '('))
    119. {
    120. StackDestory(&st);
    121. return false;
    122. }
    123. else // 匹配
    124. {
    125. ++s;
    126. }
    127. break;
    128. }
    129. default:
    130. break;
    131. }
    132. }
    133. bool ret = StackEmpty(&st);
    134. StackDestory(&st);
    135. return ret;
    136. }
    137. int main()
    138. {
    139. //int ret = isValid("[[[");
    140. //int ret = isValid("[][");
    141. int ret = isValid("[]");
    142. if (ret == 0)
    143. {
    144. printf("不匹配!\n" );
    145. }
    146. else
    147. {
    148. printf("匹配!\n");
    149. }
    150. return 0;
    151. }

    后记:
    ●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                           ——By 作者:新晓·故知

  • 相关阅读:
    图的初识·遍历
    [shell] 判断字符串是否包含子字符串方法([[ 、=~、##、%%)
    InfluxDB 1.8 性能测试
    NFT-数字藏品之库里为何花116万买一个NFT头像?回顾NFT头像的“发迹史”或许能找到答案
    【c/c++】cpp对c的函数增强
    Vulhub靶场-KIOPTRIX: LEVEL 1.1
    Qt编写物联网管理平台50-超强跨平台
    linux自动更新oray ddns
    小程序 自定义弹框 阻止后面页面滚动
    【Springboot】Vue3-Springboot引入JWT实现登录校验以及常见的错误解决方案
  • 原文地址:https://blog.csdn.net/m0_57859086/article/details/126595683