C/C++数据结构-完整代码(三)队列【Queue】(顺序存储,链式存储)增删改查

x33g5p2x  于2021-09-19 转载在 C/C++  
字(8.8k)|赞(0)|评价(0)|浏览(741)

队列

1、队列的基本概念

队列是一种特殊的线性表,

特殊之处在于它只允许在表的前端(front)进行删除操作,

而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。

进行插入操作的端称为队尾,进行删除操作的端称为队头。

队列中没有元素时,称为空队列。
队列的数据元素又称为队列元素。

在队列中插入一个队列元素称为入队,从队列中删除一个队列元素称为出队。

因为队列只允许在一端插入,在另一端删除,

所以只有最早进入队列的元素才能最先从队列中删除,

故队列又称为先进先出(FIFO—first in first out)线性表。

2、队列的顺序存储

基本概念

队列是在之前的动态数组的基础上实现的

先向项目当中导入以下两个文件

  • dynamaicArray.c
  1. #include "dynamaicArray.h"
  2. //初始化数组
  3. struct dynamicAray * init_DynamicArray(int capacity){
  4. //开辟到堆区
  5. if(capacity <= 0){
  6. return NULL;
  7. }
  8. struct dynamicAray * array = malloc(sizeof(struct dynamicAray ));
  9. //判断内存是否申请成功
  10. if(array == NULL){
  11. return NULL;
  12. }
  13. //设置容量
  14. array -> m_capacity = capacity;
  15. //设置大小
  16. array -> m_size = 0;
  17. //维护在堆区数组的指针
  18. array ->pAddr = malloc(sizeof(void*) * array-> m_capacity);
  19. return array;
  20. }
  21. //插入功能
  22. void insert_dynamicArray(struct dynamicAray * array,int pos,void *data){
  23. if(array == NULL){
  24. return;
  25. }
  26. if(data == NULL){
  27. return;
  28. }
  29. if(pos < 0 || pos > array->m_size){
  30. //无效的位置 进行尾插
  31. pos = array-> m_size;//插入到当前数组的最后一个位置
  32. }
  33. //先判断是否已经满载,如果满载的就动态的开辟
  34. if(array -> m_size >=array -> m_capacity){
  35. //1、申请一个更大的内存空间
  36. int newCapacity = array->m_capacity * 2;
  37. //2、创建新的空间
  38. void ** newSpace = malloc(sizeof(void *) * newCapacity);
  39. //3、将原有的数据 拷贝到新空间下
  40. memcpy(newSpace,array->pAddr,sizeof(void * ) * array->m_capacity);
  41. //4、释放原有的空间
  42. free(array->pAddr);
  43. //5、更改指针的指向
  44. array -> pAddr = newSpace;
  45. //6、更新新容量的大小
  46. array -> m_capacity = newCapacity;
  47. }
  48. //插入新的数据的元素
  49. //从最后一个位置开始依次往后移动数据 后移
  50. int i;
  51. for(i = array -> m_size -1 ;i >= pos;i--){
  52. array->pAddr[i+1] = array->pAddr[i];
  53. }
  54. //将新元素插入到指定的位置
  55. array -> pAddr[pos] = data;
  56. //更新一下大小
  57. array ->m_size++;
  58. }
  59. //遍历数组
  60. void foreach_DynamicArray(struct dynamicAray * array,void(*myForeach)(void *)){
  61. if(array == NULL){
  62. return;
  63. }
  64. if(myForeach == NULL){
  65. return;
  66. }
  67. int i;
  68. for(i = 0; i < array ->m_size; i++)
  69. {
  70. myForeach(array->pAddr[i]);
  71. }
  72. }
  73. //删除素质当中的元素
  74. void removeByPos_DynamicArray(struct dynamicAray * array, int pos){
  75. if(array == NULL)
  76. {
  77. return ;
  78. }
  79. if(pos < 0 || pos > array->m_size-1){
  80. //无效的位置 直接return
  81. return;
  82. }
  83. //从pos位置开始 到数组的尾,数据进行前移动
  84. int i;
  85. for(i = pos; i < array->m_size -1; i++){
  86. array->pAddr[i] = array->pAddr[i+1];
  87. }
  88. array->m_size--;
  89. }
  90. void myPrintPerson(void * data){
  91. struct Person * p = data;
  92. printf("姓名:%s,年龄%d\n",p->name,p->age);
  93. }
  94. //销毁数据
  95. void destroy_DynamicArray(struct dynamicAray * arr){
  96. if(arr == NULL)
  97. {
  98. return;
  99. }
  100. if(arr->pAddr != NULL)
  101. {
  102. free(arr->pAddr);
  103. arr->pAddr = NULL;
  104. }
  105. free(arr);
  106. arr = NULL;
  107. }
  108. void test01(){
  109. //创建 动态数组
  110. struct dynamicAray * arr = init_DynamicArray(5);
  111. //准备出5个person 数据
  112. struct Person p1 = {"亚瑟",28 };
  113. struct Person p2 = {"王昭君",18 };
  114. struct Person p3 = {"赵云",38 };
  115. struct Person p4 = {"张飞",38 };
  116. struct Person p5 = {"关羽",28 };
  117. struct Person p6 = {"宫本",88 };
  118. printf("当前的容量为:%d\n",arr->m_capacity);
  119. //将数据插入到动态数组当中
  120. insert_dynamicArray(arr,0,&p1);
  121. insert_dynamicArray(arr,0,&p2);
  122. insert_dynamicArray(arr,0,&p3);
  123. insert_dynamicArray(arr,2,&p4);
  124. insert_dynamicArray(arr,10,&p5);
  125. insert_dynamicArray(arr,1,&p6);
  126. printf("插入数据后的容量为:%d\n",arr->m_capacity);
  127. //赵云 宫本 王昭君 张飞 亚瑟 关羽
  128. //遍历动态数组
  129. printf("删除前\n");
  130. foreach_DynamicArray(arr,myPrintPerson);
  131. //删除数组当中的元素
  132. removeByPos_DynamicArray(arr,1);
  133. printf("删除后\n");
  134. foreach_DynamicArray(arr,myPrintPerson);
  135. }
  • dynamaicArray.h
  1. #include "stdio.h"
  2. #include "string.h"
  3. #include "stdlib.h"
  4. //动态数组的结构
  5. struct dynamicAray{
  6. void ** pAddr;//维护在堆区真实的数组指针
  7. int m_capacity;//数组的容量
  8. int m_size;//数组的大小
  9. };
  10. //初始化数组
  11. struct dynamicAray * init_DynamicArray(int capacity);
  12. //插入功能
  13. void insert_dynamicArray(struct dynamicAray * array,int pos,void *data);
  14. //遍历数组
  15. void foreach_DynamicArray(struct dynamicAray * array,void(*myForeach)(void *));
  16. //删除素质当中的元素
  17. void removeByPos_DynamicArray(struct dynamicAray * array, int pos);
  18. void destroy_DynamicArray(struct dynamicAray * arr);
  19. struct Person{
  20. char name[64];
  21. int age;
  22. };
  23. void myPrintPerson(void * data);
  24. void test01();
  • 创建seqQueue.h

  1. #pragma once
  2. #include "stdio.h"
  3. #include "string.h"
  4. #include "stdlib.h"
  5. #include "dynamaicArray.h"
  6. #define MAX 1024
  7. typedef void * seqQueue;
  8. //初始化队列
  9. seqQueue init_SeqQueue();
  10. //入队
  11. void push_SeqQueue(seqQueue queue, void * data);
  12. //出队
  13. void pop_SeqQueue(seqQueue queue);
  14. //返回队头元素
  15. void * front_SeqQueue(seqQueue queue);
  16. //返回队尾元素
  17. void * back_SeqQueue(seqQueue queue);
  18. //返回队尾大小
  19. int size_seqQueue(seqQueue queue);
  20. //销毁
  21. void destroy_SeqQueue(seqQueue queue);
  • seqQueue.c
  1. #include "seqQueue.h"
  2. //初始化队列
  3. seqQueue init_SeqQueue()
  4. {
  5. struct dynamicAray * arr = init_DynamicArray (MAX);
  6. return arr;
  7. }
  8. //入队
  9. void push_SeqQueue(seqQueue queue, void * data){
  10. if(queue == NULL){
  11. return;
  12. }
  13. if(data == NULL){
  14. return;
  15. }
  16. struct dynamicAray * myQueue = queue;//将当前插入数据转换为原本的数据
  17. if(myQueue->m_size >= MAX){
  18. return;
  19. }
  20. //入队 === 尾插
  21. insert_dynamicArray (myQueue,myQueue->m_size,data);
  22. }
  23. //出队
  24. void pop_SeqQueue(seqQueue queue){
  25. if(queue == NULL){
  26. return;
  27. }
  28. struct dynamicAray * myQueue = queue;
  29. if(myQueue ->m_size <= 0){
  30. return;
  31. }
  32. removeByPos_DynamicArray (myQueue,0);
  33. }
  34. //返回队头元素
  35. void * front_SeqQueue(seqQueue queue){
  36. if(queue == NULL){
  37. return NULL;
  38. }
  39. struct dynamicAray * myQueue = queue;
  40. return myQueue->pAddr[0];
  41. }
  42. //返回队尾元素
  43. void * back_SeqQueue(seqQueue queue){
  44. if(queue == NULL){
  45. return NULL;
  46. }
  47. struct dynamicAray * myQueue = queue;
  48. return myQueue->pAddr[myQueue->m_size-1];
  49. }
  50. //返回队尾大小
  51. int size_seqQueue(seqQueue queue){
  52. if(queue == NULL){
  53. return -1;
  54. }
  55. struct dynamicAray * myQueue = queue;
  56. return myQueue->m_size;
  57. }
  58. //销毁
  59. void destroy_SeqQueue(seqQueue queue){
  60. if(queue == NULL){
  61. return;
  62. }
  63. destroy_DynamicArray (queue);
  64. }
  • 在main.c当中
  1. #include <stdio.h>
  2. #include "seqQueue.h"
  3. void test02(){
  4. //初始化队列
  5. seqQueue queue = init_SeqQueue();
  6. while (size_seqQueue (queue) > 0 ){
  7. //获取对头元素
  8. struct Person * pFont = front_SeqQueue (queue);
  9. //打印队尾元素
  10. printf ("Front element\tName:%s\t\tAge:%d\n",pFont->name ,pFont->age);
  11. //获取队尾元素
  12. struct Person * pBack = back_SeqQueue(queue);
  13. //打印队尾元素
  14. printf ("Back element \tName:%s\t\tAge:%d\n",pBack->name ,pBack->age);
  15. //出队
  16. pop_SeqQueue (queue);
  17. }
  18. printf ("Queue\t size:%d\n", size_seqQueue (queue));
  19. //销毁
  20. destroy_SeqQueue (queue);
  21. }
  22. int main () {
  23. printf ("Hello, World!\n");
  24. test02();
  25. return 0;
  26. }

运行结果

3、队列的链式存储

对外接口
初始化
入队
出队
返回对头
返回队尾大小

分文件编写
目录结构

(1)linkQueue.h

  1. #pragma once
  2. #include "stdio.h"
  3. #include "string.h"
  4. #include "stdlib.h"
  5. //声明链表的节点
  6. struct QueueNode{
  7. struct QueueNode * next;//只维护指针域
  8. };
  9. //队列的结构体
  10. struct LQueue{
  11. //头节点
  12. struct QueueNode pHeader;
  13. //队列的大小
  14. int m_Size;
  15. //维护尾节点的指针
  16. struct QueueNode * pTail;
  17. };
  18. typedef void * LinkQueue;
  19. //初始化队列
  20. LinkQueue init_LinkQueue();
  21. //入队
  22. void push_LinkQueue(LinkQueue queue,void * data);
  23. //出队
  24. void pop_LinkQueue(LinkQueue queue);
  25. //返回对头
  26. void * front_LinkQueue(LinkQueue queue);
  27. //返回队尾
  28. void * back_LinkQueue(LinkQueue queue);
  29. //返回队的大小
  30. int size_LinkQueue(LinkQueue queue);
  31. //销毁
  32. void destory_LinkQueue(LinkQueue queue);
(2)linkQueue.c

  1. #include "linkQueue.h"
  2. //初始化队列
  3. LinkQueue init_LinkQueue(){
  4. struct LQueue * myQueue = malloc (sizeof(struct LQueue));
  5. if(myQueue == NULL){
  6. return NULL;
  7. }
  8. myQueue->pHeader.next = NULL;
  9. myQueue->m_Size = 0;
  10. myQueue->pTail = &(myQueue->pHeader);//尾结点的初始化,就是在头结点
  11. return myQueue;
  12. }
  13. //入队
  14. void push_LinkQueue(LinkQueue queue,void * data){
  15. if(queue == NULL){
  16. return;
  17. }
  18. if(data == NULL){
  19. return;
  20. }
  21. //还原真实的队列的结构体
  22. struct LQueue * myQueue = queue;
  23. //取出用户数据的前四个字节
  24. struct QueueNode * myNode = data;
  25. //插入新I节点-尾插,将队列的为节点的指针指向新节点(也就是尾结点的指针保存新节点的地址)
  26. myQueue->pTail->next = myNode;
  27. //将新节点的指针域置空
  28. myNode->next = NULL;
  29. myQueue->pTail = myNode;//移动尾节点的指针到新节点的位置
  30. //更新队列的长度
  31. myQueue->m_Size++;
  32. }
  33. //出队
  34. void pop_LinkQueue(LinkQueue queue){
  35. if(queue == NULL){
  36. return;
  37. }
  38. struct LQueue * myQueue = queue;
  39. if(myQueue->m_Size <= 0){
  40. return;
  41. }
  42. //获取链表当中第一个有数据的节点
  43. struct QueueNode * pFirst = myQueue->pHeader.next;
  44. //更新指针的指向
  45. myQueue->pHeader.next = pFirst->next;
  46. //更新队列的长度
  47. myQueue->m_Size--;
  48. }
  49. //返回对头
  50. void * front_LinkQueue(LinkQueue queue){
  51. if(queue == NULL){
  52. return NULL;
  53. }
  54. struct LQueue * myQueue = queue;
  55. return myQueue->pHeader.next;
  56. }
  57. //返回队尾
  58. void * back_LinkQueue(LinkQueue queue){
  59. if(queue == NULL){
  60. return NULL;
  61. }
  62. struct LQueue * myQueue = queue;
  63. return myQueue->pTail;
  64. }
  65. //返回队的大小
  66. int size_LinkQueue(LinkQueue queue){
  67. if(queue == NULL){
  68. return -1;
  69. }
  70. struct LQueue * myQueue = queue;
  71. return myQueue->m_Size;
  72. }
  73. //销毁
  74. void destory_LinkQueue(LinkQueue queue){
  75. if(queue == NULL){
  76. return;
  77. }
  78. free (queue);
  79. queue == NULL;
  80. }
(2)main.c

  1. #include "stdio.h"
  2. #include "linkQueue.h"
  3. struct Person{
  4. void * node;
  5. char name[64];
  6. int age;
  7. };
  8. void test01(){
  9. LinkQueue queue = init_LinkQueue();
  10. //准备数据
  11. struct Person p1 = {NULL,"aa",10};
  12. struct Person p2 = {NULL,"bb",20};
  13. struct Person p3 = {NULL,"cc",30};
  14. struct Person p4 = {NULL,"dd",40};
  15. struct Person p5 = {NULL,"ee",50};
  16. //入队
  17. push_LinkQueue (queue,&p1);
  18. push_LinkQueue (queue,&p2);
  19. push_LinkQueue (queue,&p3);
  20. push_LinkQueue (queue,&p4);
  21. push_LinkQueue (queue,&p5);
  22. printf ("LinkQueue size : %d \n", size_LinkQueue (queue));
  23. while (size_LinkQueue (queue) > 0){
  24. struct Person * pFront = front_LinkQueue (queue);
  25. printf ("front_LinkQueue Name = %s\tAge = %d\n",pFront->name,pFront->age);
  26. struct Person * pBack = back_LinkQueue(queue);
  27. printf ("back_LinkQueue Name = %s\tAge = %d\n",pBack->name,pBack->age);
  28. pop_LinkQueue(queue);
  29. }
  30. printf ("LinkQueue size : %d \n", size_LinkQueue (queue));
  31. destory_LinkQueue (queue);
  32. }
  33. int main () {
  34. test01();
  35. printf ("Hello, World!\n");
  36. return 0;
  37. }

运行结果

相关文章

最新文章

更多