当前位置:   article > 正文

数据结构 —— 栈 与 队列

数据结构 —— 栈 与 队列

1.栈

1.1栈的结构和概念

栈(Stack)是一种特殊的线性数据结构,它遵循后进先出(LIFO,Last In First Out)的原则。栈只允许在一端插入和删除数据,这一端被称为栈顶(top),另一端被称为栈底(bottom)。

就像弹匣一样,先压进去的子弹会最后被发射,最后压进去的子弹反而最先被发射

1.2栈的实现 (数组)

栈的基本功能:

  1. push(元素):将元素压入栈顶。
  2.  pop():从栈顶删除元素,并返回该元素。如果栈为空,则此操作可能会导致错误。
  3. peek() 或 top():返回栈顶元素,但不删除它。
  4. Empty():检查栈是否为空。
  5. size():返回栈中元素的数量。

Stack.h

  1. #pragma once
  2. // 支持动态增长的栈
  3. #include<stdio.h>
  4. #include<stdlib.h>
  5. #include<stdbool.h>
  6. #include<assert.h>
  7. typedef int STDataType;
  8. typedef struct Stack
  9. {
  10. STDataType* _a;
  11. int _top; // 栈顶
  12. int _capacity; // 容量
  13. }Stack;
  14. // 初始化栈
  15. void StackInit(Stack* ps);
  16. // 入栈
  17. void StackPush(Stack* ps, STDataType data);
  18. // 出栈
  19. void StackPop(Stack* ps);
  20. // 获取栈顶元素
  21. STDataType StackTop(Stack* ps);
  22. // 获取栈中有效元素个数
  23. int StackSize(Stack* ps);
  24. // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
  25. int StackEmpty(Stack* ps);
  26. // 销毁栈
  27. void StackDestroy(Stack* ps);

Stack.c

  1. #include"Stack.h"
  2. // 初始化栈
  3. void StackInit(Stack* ps) {
  4. assert(ps);
  5. ps->_a = NULL;
  6. ps->_capacity = 0;
  7. ps->_top = 0;
  8. }
  9. // 入栈
  10. void StackPush(Stack* ps, STDataType data) {
  11. assert(ps);
  12. //扩容
  13. if (ps->_top == ps->_capacity)
  14. {
  15. int newcapacity = ps->_capacity == 0 ? 2 : ps->_capacity * 2;
  16. STDataType* newa = (STDataType*)realloc(ps->_a,newcapacity * sizeof(STDataType));
  17. if (newa == NULL)
  18. {
  19. perror("realloc");
  20. return;
  21. }
  22. ps->_capacity = newcapacity;
  23. ps->_a = newa;
  24. }
  25. ps->_a[ps->_top] = data;
  26. ps->_top++;
  27. }
  28. // 出栈
  29. void StackPop(Stack* ps) {
  30. assert(ps);
  31. assert(ps->_top > 0);
  32. ps->_top--;
  33. }
  34. // 获取栈顶元素
  35. STDataType StackTop(Stack* ps) {
  36. assert(ps);
  37. assert(ps->_top > 0);
  38. return ps->_a[ps->_top - 1];
  39. }
  40. // 获取栈中有效元素个数
  41. int StackSize(Stack* ps) {
  42. assert(ps);
  43. return ps->_top;
  44. }
  45. // 检测栈是否为空,如果为空返回非零结果,如果不为空返回0
  46. int StackEmpty(Stack* ps) {
  47. assert(ps);
  48. return ps->_top == 0;//为空就是真,返回非0
  49. }
  50. // 销毁栈
  51. void StackDestroy(Stack* ps) {
  52. assert(ps);
  53. ps->_top = 0;
  54. ps->_capacity = 0;
  55. free(ps->_a);
  56. ps->_a = NULL;
  57. }

2.队列(单链表)

2.1队列的概念和结构

队列(Queue)是一种特殊的线性表,它遵循先进先出(FIFO)的原则,即最早进入队列的元素将最先从队列中移除。队列只允许在表的前端(front)进行删除操作,称为出队,而在表的后端(rear)进行插入操作,称为入队。

  先进先出,后进后出

2.2队列的实现(链表)

  1. 入队(Push):在队列的尾部添加一个元素。

  2. 出队(Pop):从队列的头部移除一个元素,并返回该元素。

  3. 判断队列是否为空(Empty):检查队列是否不包含任何元素。

  4. 获取队列大小(Size):返回队列中当前元素的数量。

  5. 查看队头元素(Front):返回队列头部的元素,但不从队列中移除它。

  6. 查看队尾元素(Back):返回队列尾部的元素,但不从队列中移除它

Queue.h

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<assert.h>
  4. #include<stdbool.h>
  5. typedef int QDataType;
  6. // 链式结构:表示队列
  7. typedef struct QListNode
  8. {
  9. struct QListNode* _next;
  10. QDataType _data;
  11. }QNode;
  12. // 队列的结构
  13. typedef struct Queue
  14. {
  15. QNode* _front;
  16. QNode* _rear;
  17. int size;
  18. }Queue;
  19. // 初始化队列
  20. void QueueInit(Queue* q);
  21. // 队尾入队列
  22. void QueuePush(Queue* q, QDataType data);
  23. // 队头出队列
  24. void QueuePop(Queue* q);
  25. // 获取队列头部元素
  26. QDataType QueueFront(Queue* q);
  27. // 获取队列队尾元素
  28. QDataType QueueBack(Queue* q);
  29. // 获取队列中有效元素个数
  30. int QueueSize(Queue* q);
  31. // 检测队列是否为空,如果为空返回非零结果,如果非空返回0
  32. int QueueEmpty(Queue* q);
  33. // 销毁队列
  34. void QueueDestroy(Queue* q);

Queue.c 

 

  1. #include"Queue.h"
  2. // 初始化队列
  3. void QueueInit(Queue* q) {
  4. assert(q);
  5. q->size = 0;
  6. q->_front = NULL;
  7. q->_rear = NULL;
  8. }
  9. // 队尾入队列
  10. void QueuePush(Queue* q, QDataType data) {
  11. assert(q);
  12. QNode* newnode = (QNode*)malloc(sizeof(QNode));
  13. if (newnode == NULL)
  14. {
  15. perror("QueuePush()::malloc()");
  16. return;
  17. }
  18. newnode->_data = data;
  19. newnode->_next = NULL;
  20. //队列为NULL
  21. if (q->_front == NULL)
  22. {
  23. q->_front = q->_rear = newnode;
  24. }
  25. else
  26. {
  27. q->_rear->_next = newnode;
  28. q->_rear = q->_rear->_next;
  29. }
  30. q->size++;
  31. }
  32. // 队头出队列
  33. void QueuePop(Queue* q) {
  34. assert(q);
  35. assert(q->size != 0);
  36. //单个节点
  37. if (q->_front == q->_rear)
  38. {
  39. free(q->_front);
  40. q->_front = q->_rear = NULL;
  41. }
  42. //多个节点
  43. else
  44. {
  45. QNode* next = q->_front->_next;
  46. free(q->_front);
  47. q->_front = next;
  48. }
  49. q->size--;
  50. }
  51. // 获取队列头部元素
  52. QDataType QueueFront(Queue* q) {
  53. assert(q);
  54. assert(q->_front);//队头不能为NULL
  55. return q->_front->_data;
  56. }
  57. // 获取队列队尾元素
  58. QDataType QueueBack(Queue* q) {
  59. assert(q);
  60. assert(q->_rear);//队尾不能为NULL
  61. return q->_rear->_data;
  62. }
  63. // 获取队列中有效元素个数
  64. int QueueSize(Queue* q) {
  65. return q->size;
  66. }
  67. // 检测队列是否为空,如果为空返回非零结果,如果非空返回0
  68. int QueueEmpty(Queue* q) {
  69. assert(q);
  70. return q->size == 0;
  71. }
  72. // 销毁队列
  73. void QueueDestroy(Queue* q) {
  74. assert(q);
  75. QNode* cur = q->_front;
  76. while (cur)
  77. {
  78. QNode* next = cur->_next;
  79. free(cur);
  80. cur = next;
  81. }
  82. q->_front = q->_rear = NULL;
  83. q->size = 0;
  84. //这个应该留给用户去释放
  85. /*free(q);
  86. q = NULL;*/
  87. }

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

闽ICP备14008679号