【数据结构】---栈和队列的实现【C语言实现】

悠悠 2023-02-27 10:46 100阅读 0赞

目录

  1. 栈的实现

  2. 队列的实现


1. 栈的实现

栈是一种先进后出的数据结构。

栈(stack)是限定仅在表的一端进行操作的数据结构,只有一个入口和出口,只能从这个口子,进去或者出去。

31.png

如图:栈就像一个放球的单管桶,只允许球从桶的开口这一端取出,并且球先放入桶中则后从桶中拿出。

栈的节点的设计

栈分为数组栈和链表栈,其区别是数组栈使用数组进行功能的模拟,实现较为快速和便利,

链表栈使用链表的思路去设计,实现较为麻烦,但是其稳定不易出错

在链表栈中又分为静态链表栈和动态链表栈,静态链表栈给定栈的空间大小,不允许超过存储超过给定数据大小的元素,

而动态栈使用的是自动创建空间的方法进行创建,只要符合机器的硬件要求以及编译器的控制,其理论上是极大的。

我们以链表栈的动态链表栈为例子,

先设计2 个结构体

个作为保存节点数值和指向下一个节点的指针,

另一个用于节点数量和指向最顶端的节点指针

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 栈的实现,一种先进后出的数据结构
  4. // 定义 2 个结构体
  5. typedef struct node{
  6. int data;
  7. struct node *next;
  8. }Node;
  9. typedef struct stack{
  10. int count;// 用于计算栈的大小
  11. Node *top; // 用于指向最顶端的节点
  12. }Link_stack;

初始化头部节点

  1. // 初始化头部节点
  2. Link_stack *init(){
  3. Link_stack *head;
  4. head = (Link_stack *)malloc(sizeof(Link_stack ));
  5. if (head == NULL){
  6. printf("无法创建--- \n");
  7. exit(0);
  8. }
  9. head->count = 0;
  10. head->top = NULL;
  11. return head;
  12. }

将元素 push 进链表,并更新头部节点的指针

  1. void stack_push(Link_stack *head, int value){
  2. if (head == NULL){
  3. printf("请先创建一个头部节点---- \n");
  4. return NULL;
  5. }
  6. Node *temp = (Node *)malloc(sizeof(Node));
  7. temp->data = value;
  8. temp->next = head->top;
  9. head->top = temp; // 更新头部节点
  10. head->count++;
  11. }

打印栈的大小

  1. int stack_size(Link_stack *head){
  2. return head->count;
  3. }

将元素 pop 出链表,返回删除了的元素的数值

  1. int stack_pop(Link_stack *head){
  2. if (head == NULL) return -1;
  3. Node *temp = head->top;
  4. int res = temp->data;
  5. head->top = temp->next; // 指向下一个节点就可以,记得free temp
  6. free(temp);
  7. head->count--;
  8. return res;
  9. }

遍历栈 链表结构

  1. void show_stack(Link_stack *head){
  2. if (stack_size(head) == 0){
  3. printf("stack data is empty \n");
  4. }
  5. Node *temp = head->top;
  6. while (temp != NULL){
  7. printf("stack data is : %d \n", temp->data);
  8. temp = temp->next;
  9. }
  10. }

测试代码:

  1. int main(){
  2. printf("starting ------ \n");
  3. Link_stack *head = init();
  4. for (int i = 0; i < 4; i++){
  5. stack_push(head, i+1);
  6. }
  7. show_stack(head);
  8. printf("delete stack node : %d \n", stack_pop(head));
  9. printf("delete stack node : %d \n", stack_pop(head));
  10. printf("stack size : %d \n", stack_size(head));
  11. show_stack(head);
  12. return 0;
  13. }

2. 队列的实现

队列是一个先进先出的数据结构。

队列(queue)是限定在表的一端进行插入,表的另一端进行删除的数据结构,如同栈的学习,请联系前文所学链表,试想一个单链表,我们只能对他的链表表尾进行插入,而只能对链表的表头进行结点的删除,其余一切的操作均不允许,这样强限制性的“链表“,就是我们所说的队列。

41.png

如图:队列就像一个两端相通的水管,只允许一端插入,另一端取出,先放入管中的球先从管中拿出。

设定2 个结构体

411.png

next指针表示,下一个的指针,其指向下一个结点,通过next指针将各个结点链接。

412.png

我们也额外添加一个结构体,其包括了两个分别永远指向队列的队尾和队头的指针,由于队列只能从头节点删除,尾节点插入,所以需要保存 2 个节点

  1. // 定义 2 个结构体
  2. typedef struct node{
  3. int data;
  4. struct node *next;
  5. }Node;
  6. typedef struct my_q{
  7. Node *front; // 保存指向头节点的指针
  8. Node *rear; // 保存指向尾部节点的指针
  9. int size;
  10. }queue;

入队操作:

  1. 进行入队(push)操作的时候,我们首先需要特判一下队列是否为空,如果队列为空的话,需要将头指针和尾指针一同指向第一个结点

402.png

  1. 当如果队列不为空的时候,我们只需要将尾结点向后移动,通过不断移动next指针指向新的结点构成队列即可

4022.png

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. // 队列的实现,一种先进先出的数据结构,
  4. // 定义 2 个结构体
  5. typedef struct node{
  6. int data;
  7. struct node *next;
  8. }Node;
  9. typedef struct my_q{
  10. Node *front; // 保存指向头节点的指针
  11. Node *rear; // 保存指向尾部节点的指针
  12. int size;
  13. }queue;
  14. // 初始化队列
  15. queue *init_queue(){
  16. queue *q = (queue*)malloc(sizeof(queue));
  17. if (q == NULL){
  18. printf("无法创建----- \n");
  19. exit(0);
  20. }
  21. q->front = NULL;
  22. q->rear = NULL;
  23. q->size = 0;
  24. return q;
  25. }
  26. // 判断是否为空:
  27. int isEmpty(queue* q){
  28. return q->front == NULL;
  29. }
  30. // 将元素 push 进链表队列中
  31. void queue_push(queue *q, int value){
  32. Node* temp = (Node*)malloc(sizeof(Node));
  33. temp->data = value;
  34. temp->next = NULL; // 设置最后指针指向空,否则遍历无法终止
  35. // 如果是为空情况下
  36. if (isEmpty(q)){
  37. q->front = temp;
  38. q->rear = temp;
  39. q->size++;
  40. }
  41. else{
  42. q->rear->next = temp; // 将队列连接起来
  43. q->rear = temp; // 更新尾部节点
  44. q->size++;
  45. }
  46. }
  47. // 队列的大小
  48. int queue_size(queue *q){
  49. return q->size;
  50. }
  51. // 将元素 pop 出链表,返回删除了的元素的数值
  52. int queue_pop(queue *q){
  53. if (isEmpty(q)){
  54. printf("queue is empty -- \n");
  55. return 0;
  56. }
  57. else{
  58. Node *temp = q->front;
  59. int res = temp->data;
  60. q->front = q->front->next; // 删除节点
  61. q->size--;
  62. free(temp);
  63. return res;
  64. }
  65. }
  66. // 遍历队列结构
  67. void show_queue(queue *q){
  68. if (q->front == NULL){
  69. printf("queue is empty --- \n");
  70. }
  71. else{
  72. Node *node = q->front;
  73. while (node != NULL){
  74. printf("node data is : %d \n", node->data);
  75. node = node->next;
  76. }
  77. printf(" over --- \n");
  78. }
  79. }
  80. int main(){
  81. printf("starting ------2222 \n");
  82. queue *q = init_queue();
  83. for (int i = 0; i < 4; i++){
  84. queue_push(q, i + 1);
  85. }
  86. show_queue(q);
  87. printf("size of queue is : %d \n", queue_size(q));
  88. printf("delete node: %d \n", queue_pop(q));
  89. printf("delete node: %d \n", queue_pop(q));
  90. show_queue(q);
  91. printf("size of queue is : %d \n", queue_size(q));
  92. return 0;
  93. }

项目推荐:

2000多G的计算机各行业电子资源分享(持续更新)

2020年微信小程序全栈项目之喵喵交友【附课件和源码】

Spring Boot开发小而美的个人博客【附课件和源码】

Java微服务实战296集大型视频-谷粒商城【附代码和课件】

Java开发微服务畅购商城实战【全357集大项目】-附代码和课件

最全最详细数据结构与算法视频-【附课件和源码】

在这里插入图片描述


发表评论

表情:
评论列表 (有 0 条评论,100人围观)

还没有评论,来说两句吧...

相关阅读