当前位置:   article > 正文

线性链表之栈、队列的代码实现

线性链表之栈、队列的代码实现

目录

一 、栈

1.栈的概念

2.栈的主要操作:

size(): 返回栈中元素的数量。

3.栈的应用场景:

4.栈的代码实现

4.1 初始化栈

4.2 入栈

 4.3 出栈

4.4 判空

4.5 取栈顶元素

3.6 获取栈中有效元素个数

 3.7 销毁栈

 5.总体代码

二、队列

1.队列的概念:

2.队列的主要操作:

3.队列的应用场景:

 ​编辑4.队列的代码实现

4.1 初始化队列

4.2  入队

 4.3 出队

 4.4 获取对列的元素个数

4.5 判空

4.6获取队列头部元素

 4.7获取队列队尾元素

4.8 队列销毁

5.总体代码

三、结尾


一 、栈

1.栈的概念

栈:栈是一种后进先出(LIFO, Last In First Out)的数据结构。它只允许在栈顶进行添加(push)或删除(pop)元素的操作。这意味着最后添加到栈中的元素将是第一个被移除的。

2.栈的主要操作

  • push(element): 将元素压入栈顶。
  • pop(): 移除并返回栈顶元素。
  • peek() 或 top(): 返回栈顶元素,但不移除它。
  • isEmpty(): 检查栈是否为空。
  • size(): 返回栈中元素的数量。

3.栈的应用场景

  • 表达式求值(如后缀表达式求值)。
  • 递归调用(函数调用栈)。
  • 浏览器历史记录(最近访问的页面放在最上面)。
  • 回溯算法(如深度优先搜索DFS)。

4.栈的代码实现

在这我就用通过顺序表的形式来实现栈 

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. #include<stdbool.h>
  6. //动态栈
  7. typedef int STDataType;
  8. typedef struct Stack
  9. {
  10. int* a;
  11. int top;
  12. int capacity;
  13. }ST;
  14. //栈的初始化
  15. void STInit(ST* pc);
  16. //栈的销毁
  17. void STDestory(ST* pc);
  18. //压栈
  19. void STPush(ST* pc, STDataType x);
  20. //出栈
  21. void STPop(ST* pc);
  22. //返回栈内的空间大小
  23. int STSize(ST* pc);
  24. //判断栈内是否为空
  25. bool STEmpty(ST* pc);
  26. //返回栈顶的元素
  27. STDataType STTop(ST* pc);
4.1 初始化

栈的初始化将传入函数的结构体进行初始化:

a. 栈顶初始化的时候注意有两种情况:
1. top指向栈顶元素
2. top指向栈顶元素的后面一个位置
当然都可以,我选择 2 仅仅方便我自己理解

b.对栈申请容量为4个STDataType的字节大小

  1. void STInit(ST* pc)
  2. {
  3. assert(pc);
  4. pc->a = (STDataType*)malloc(sizeof(STDataType) * 4);
  5. if (pc->a == NULL)
  6. {
  7. perror("malloc");
  8. return;
  9. }
  10. pc->capacity = 4;
  11. pc->top = 0;//从栈底的下一个元素开始
  12. }
4.2 入栈

当数据入栈时需要判断栈是否为满,若为满则需要扩容

  1. void STPush(ST* pc, STDataType x)
  2. {
  3. assert(pc);
  4. if (pc->top == pc->capacity)
  5. {
  6. STDataType* tmp = (STDataType*)realloc(pc->a, sizeof(STDataType) * (pc->capacity) * 2);
  7. if (tmp == 0)
  8. {
  9. perror("realloc");
  10. return;
  11. }
  12. pc->a = tmp;
  13. pc->capacity *= 2;
  14. }
  15. pc->a[pc->top] = x;
  16. ++pc->top;
  17. }
 4.3 出栈

执行出栈操作时,栈不能为空,且只需要 top-- , 不需要将其数据抹除。

  1. void STPop(ST* pc)
  2. {
  3. assert(pc);
  4. assert(!STEmpty(pc));
  5. pc->top--;
  6. }
4.4 判空

 此次的bool类型接收若为真,则返回Ture,若为假,则返回Flase,通过返回pc->top是否等与零,也就是栈是否为空来判断返回。

  1. bool STEmpty(ST* pc)
  2. {
  3. assert(pc);
  4. return pc->top == 0;
  5. }
4.5 取栈顶元素

先通过STEmpty判断栈内是否为空

top是指栈顶元素的最后一个位置,所以需要减一(top-1)来指定栈顶数据

  1. STDataType STTop(ST* pc)
  2. {
  3. assert(pc);
  4. assert(!STEmpty(pc));
  5. return pc->a[pc->top - 1];
  6. }
3.6 获取栈中有效元素个数

 由于op是指栈顶元素的最后一个位置,而元素个数从下标零开始,所以直接放回top

  1. int STSize(ST* pc)
  2. {
  3. assert(pc);
  4. return pc->top;
  5. }
 3.7 销毁栈
  1. void STDestory(ST* pc)
  2. {
  3. assert(pc);
  4. free(pc->a);
  5. pc->a = NULL;
  6. pc->capacity = 0;
  7. pc->top = 0;
  8. }

 5.总体代码

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include"Stack.h"
  3. void STInit(ST* pc)
  4. {
  5. assert(pc);
  6. pc->a = (STDataType*)malloc(sizeof(STDataType) * 4);
  7. if (pc->a == NULL)
  8. {
  9. perror("malloc");
  10. return;
  11. }
  12. pc->capacity = 4;
  13. pc->top = 0;//从栈底的下一个元素开始
  14. }
  15. void STDestory(ST* pc)
  16. {
  17. assert(pc);
  18. free(pc->a);
  19. pc->a = NULL;
  20. pc->capacity = 0;
  21. pc->top = 0;
  22. }
  23. void STPush(ST* pc, STDataType x)
  24. {
  25. assert(pc);
  26. if (pc->top == pc->capacity)
  27. {
  28. STDataType* tmp = (STDataType*)realloc(pc->a, sizeof(STDataType) * (pc->capacity) * 2);
  29. if (tmp == 0)
  30. {
  31. perror("realloc");
  32. return;
  33. }
  34. pc->a = tmp;
  35. pc->capacity *= 2;
  36. }
  37. pc->a[pc->top] = x;
  38. ++pc->top;
  39. }
  40. void STPop(ST* pc)
  41. {
  42. assert(pc);
  43. assert(!STEmpty(pc));
  44. pc->top--;
  45. }
  46. int STSize(ST* pc)
  47. {
  48. assert(pc);
  49. return pc->top;
  50. }
  51. bool STEmpty(ST* pc)
  52. {
  53. assert(pc);
  54. return pc->top == 0;
  55. }
  56. STDataType STTop(ST* pc)
  57. {
  58. assert(pc);
  59. assert(!STEmpty(pc));
  60. return pc->a[pc->top - 1];
  61. }

二、队列

1.队列的概念:

队列是一种先进先出(FIFO, First In First Out)的数据结构。它允许在队尾添加元素(入队),在队首移除元素(出队)。这意味着最先添加到队列中的元素将是第一个被移除的

2.队列的主要操作

  • enqueue(element): 在队尾添加一个元素。
  • dequeue(): 移除并返回队首元素。
  • front(): 返回队首元素,但不移除它。
  • rear(): 返回队尾元素(在某些实现中可能不提供)。
  • isEmpty(): 检查队列是否为空。
  • size(): 返回队列中元素的数量。

3.队列的应用场景

  • 缓冲区(如网络数据包)。
  • 任务调度(如操作系统的进程调度)。
  • 广度优先搜索(BFS)。
  • 打印机任务队列。

 4.队列的代码实现

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. #include<stdbool.h>
  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. int size;
  17. }Queue;
  18. //队列的初始化
  19. void QueueInit(Queue* pc);
  20. //队列的销毁
  21. void QueueDestory(Queue* pc);
  22. //入队
  23. void QueuePush(Queue* pc,QDataType x);
  24. //出队
  25. void QueuePop(Queue* pc);
  26. //队列的元素个数
  27. void QueueSize(Queue* pc);
  28. //判空
  29. bool QueueEmpty(Queue* pc);
  30. //获取队列队头元素
  31. QDataType QueueFront(Queue* pc);
  32. //获取队列队尾元素
  33. QDataType QueueBack(Queue* pc);
4.1 初始化队列

为了方便找到头和尾和元素个数所以定义了一个结构体:

这里队列的front指向队头,rear指向队尾,size表示元素个数。
当队列为空的时候,那么frontrear 都是指向 NULL

  1. void QueueInit(Queue* pc)
  2. {
  3. assert(pc);
  4. pc->head = pc->tail = NULL;
  5. pc->size = 0;
  6. }
4.2  入队

插入时,需要向空间申请空间

1.队列为空时,需要改变队头和队尾的指针

2.不为空时,只需要将新结点指向队尾并把队尾指向新结点(注意顺序)

  1. void QueuePush(Queue* pc, QDataType x)
  2. {
  3. QNode* newnode = (Queue*)malloc(sizeof(Queue));
  4. if (newnode == NULL)
  5. {
  6. perror("malloc");
  7. return;
  8. }
  9. newnode->next = x;
  10. newnode->next = NULL;
  11. if (pc->head == NULL)
  12. {
  13. pc->head = pc->tail = newnode;
  14. }
  15. else
  16. {
  17. pc->tail->next = newnode;
  18. pc->tail = newnode;
  19. }
  20. pc->size++;
  21. }
 4.3 出队

1.对列只有一个结点时:删除该结点,并把headtail指向NULL

2.队列有多个结点时:保存head->next,删除head的结点并更新head

  1. void QueuePop(Queue* pc)
  2. {
  3. assert(pc);
  4. assert(pc->head != NULL);
  5. if (pc->head->next == NULL)
  6. {
  7. free(pc->head);
  8. pc->head = pc->tail = NULL;
  9. }
  10. else
  11. {
  12. Queue* next = pc->head->next;
  13. free(pc->head);
  14. pc->head = next;
  15. }
  16. pc->size--;
  17. }
 4.4 获取对列的元素个数

size表示队列存储的元素个数

  1. void QueueSize(Queue* pc)
  2. {
  3. assert(pc);
  4. return pc->size;
  5. }
4.5 判空

通过size存储的元素个数来进行判断

  1. bool QueueEmpty(Queue* pc)
  2. {
  3. assert(pc);
  4. return pc->size == 0;
  5. }
4.6获取队列头部元素

head存储着队列的头部元素

  1. QDataType QueueFront(Queue* pc)
  2. {
  3. assert(pc);
  4. assert(!QueueEmpty(pc));
  5. return pc->head->data;
  6. }
 4.7获取队列队尾元素

tail存储着队列的队尾元素

  1. QDataType QueueBack(Queue* pc)
  2. {
  3. assert(pc);
  4. assert(!QueueEmpty(pc));
  5. return pc->tail->data;
  6. }
4.8 队列销毁
  1. void QueueDestory(Queue* pc)
  2. {
  3. assert(pc);
  4. Queue* cur = pc->head;
  5. while (cur)
  6. {
  7. Queue* next = cur->next;
  8. free(cur);
  9. cur = next;
  10. }
  11. pc->head = pc->tail = NULL;
  12. pc->size = 0;
  13. }

5.总体代码

  1. #define _CRT_SECURE_NO_WARNINGS 1
  2. #include"Queue.h"
  3. void QueueInit(Queue* pc)
  4. {
  5. assert(pc);
  6. pc->head = pc->tail = NULL;
  7. pc->size = 0;
  8. }
  9. void QueueDestory(Queue* pc)
  10. {
  11. assert(pc);
  12. Queue* cur = pc->head;
  13. while (cur)
  14. {
  15. Queue* next = cur->next;
  16. free(cur);
  17. cur = next;
  18. }
  19. pc->head = pc->tail = NULL;
  20. pc->size = 0;
  21. }
  22. void QueuePush(Queue* pc, QDataType x)
  23. {
  24. QNode* newnode = (Queue*)malloc(sizeof(Queue));
  25. if (newnode == NULL)
  26. {
  27. perror("malloc");
  28. return;
  29. }
  30. newnode->next = x;
  31. newnode->next = NULL;
  32. if (pc->head == NULL)
  33. {
  34. pc->head = pc->tail = newnode;
  35. }
  36. else
  37. {
  38. pc->tail->next = newnode;
  39. pc->tail = newnode;
  40. }
  41. pc->size++;
  42. }
  43. void QueuePop(Queue* pc)
  44. {
  45. assert(pc);
  46. assert(pc->head != NULL);
  47. if (pc->head->next == NULL)
  48. {
  49. free(pc->head);
  50. pc->head = pc->tail = NULL;
  51. }
  52. else
  53. {
  54. Queue* next = pc->head->next;
  55. free(pc->head);
  56. pc->head = next;
  57. }
  58. pc->size--;
  59. }
  60. void QueueSize(Queue* pc)
  61. {
  62. assert(pc);
  63. return pc->size;
  64. }
  65. bool QueueEmpty(Queue* pc)
  66. {
  67. assert(pc);
  68. return pc->size == 0;
  69. }
  70. QDataType QueueFront(Queue* pc)
  71. {
  72. assert(pc);
  73. assert(!QueueEmpty(pc));
  74. return pc->head->data;
  75. }
  76. QDataType QueueBack(Queue* pc)
  77. {
  78. assert(pc);
  79. assert(!QueueEmpty(pc));
  80. return pc->tail->data;
  81. }

三、结尾

如果有什么建议和疑问,或是有什么错误,希望大家可以在评论区提一下。
希望大家以后也能和我一起进步!!
如果这篇文章对你有用的话,希望能给我一个小小的赞!

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

闽ICP备14008679号