• 第三部分—数据结构与算法基础_3. 受限线性表


    3.1栈(Stack)

    3.1.1栈的基本概念

    • 概念:

    首先它是一个线性表,也就是说,栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里表尾是指栈顶,而不是栈底。

    • 特性

    它的特殊之处在于限制了这个线性表的插入和删除的位置,它始终只在栈顶进行。这也就使得:栈底是固定的,最先进栈的只能在栈底。

    • 操作
      1. 栈的插入操作,叫做进栈,也叫压栈。类似子弹入弹夹(如下图所示)
      2. 栈的删除操作,叫做出栈,也有的叫做弾栈,退栈。如同弹夹中的子弹出夹(如下图所示)

    3.1.2栈的顺序存储

    • 基本概念

    栈的顺序存储结构简称顺序栈,它是运算受限制的顺序表。顺序栈的存储结构是:利用一组地址连续的的存储单元依次存放自栈底到栈顶的数据元素,同时附设指针top只是栈顶元素在顺序表中的位置。

    • 设计与实现

    因为栈是一种特殊的线性表,所以栈的顺序存储可以通过顺序表来实现。

    3.1.3代码实现

    1.创建三个文件

    2.代码

    1. //1.Stack_BySequenceList_Head.h 部分
    2. #pragma once
    3. #define _CRT_SECURE_NO_WARNINGS
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #define MAX 1024
    14. typedef void* pSeqStack;
    15. //1.定义栈结构体
    16. struct Stack
    17. {
    18. //栈的数组
    19. void* data[MAX];
    20. //栈大小
    21. int Size;
    22. };
    23. //2.初始化函数声明
    24. pSeqStack InitSeqStack();
    25. //3.入栈函数声明
    26. void PushSeqStack(pSeqStack stack, void* data);
    27. //4.出栈函数声明
    28. void PopSeqStack(pSeqStack stack);
    29. //5.返回栈大小函数声明
    30. int SeqStackSize(pSeqStack stack);
    31. //6.判断栈是否为空函数声明
    32. int IsEmptyStackSize(pSeqStack stack);
    33. //7.返回栈顶元素函数声明
    34. void* TopStackSize(pSeqStack stack);
    35. //8.销毁栈函数声明
    36. void DestroyStackSize(pSeqStack stack);
    37. //2.Stack_BySequenceList_Function.c 部分
    38. #pragma once
    39. #define _CRT_SECURE_NO_WARNINGS
    40. #include
    41. #include
    42. #include
    43. #include
    44. #include
    45. #include
    46. #include
    47. #include
    48. #include
    49. #include"Stack_BySequenceList_Head.h"
    50. //2.初始化函数实现
    51. pSeqStack InitSeqStack()
    52. {
    53. struct Stack* myStack = malloc(sizeof(struct Stack));
    54. if (myStack == NULL)
    55. {
    56. return NULL;
    57. }
    58. //初始化数组
    59. memset(myStack->data, 0, sizeof(void*) * MAX);
    60. //初始化栈大小
    61. myStack->Size = 0;
    62. return myStack;
    63. }
    64. //3.入栈函数实现
    65. void PushSeqStack(pSeqStack stack, void* data)
    66. {
    67. //入栈本质——数组尾插
    68. if (stack == NULL)
    69. {
    70. return;
    71. }
    72. if (data == NULL)
    73. {
    74. return;
    75. }
    76. struct Stack* mystack = stack;
    77. if (mystack->Size == MAX)
    78. {
    79. return;
    80. }
    81. mystack->data[mystack->Size] = data;
    82. mystack->Size++;
    83. }
    84. //4.出栈函数实现
    85. void PopSeqStack(pSeqStack stack)
    86. {
    87. //出栈本质——数组尾删
    88. if (stack == NULL)
    89. {
    90. return;
    91. }
    92. struct Stack* mystack = stack;
    93. if (mystack->Size == 0)
    94. {
    95. return;
    96. }
    97. mystack->data[mystack->Size - 1] = NULL;
    98. mystack->Size--;
    99. }
    100. //5.返回栈大小函数实现
    101. int SeqStackSize(pSeqStack stack)
    102. {
    103. if (stack == NULL)
    104. {
    105. return -1;
    106. }
    107. struct Stack* mystack = stack;
    108. return mystack->Size;
    109. }
    110. //6.判断栈是否为空函数实现
    111. int IsEmptyStackSize(pSeqStack stack)
    112. {
    113. if (stack == NULL)
    114. {
    115. //返回-1代表栈不存在
    116. return -1;
    117. }
    118. struct Stack* mystack = stack;
    119. if (mystack->Size == 0)
    120. {
    121. //返回1代表栈为空
    122. return 1;
    123. }
    124. //返回0代表栈不为空
    125. return 0;
    126. }
    127. //7.返回栈顶元素函数声明
    128. void* TopStackSize(pSeqStack stack)
    129. {
    130. if (stack == NULL)
    131. {
    132. return NULL;
    133. }
    134. struct Stack* mystack = stack;
    135. if (mystack->Size == 0)
    136. {
    137. return NULL;
    138. }
    139. return mystack->data[mystack->Size - 1];
    140. }
    141. //8.销毁栈函数实现
    142. void DestroyStackSize(pSeqStack stack)
    143. {
    144. if (stack == NULL)
    145. {
    146. return;
    147. }
    148. free(stack);
    149. stack = NULL;
    150. }
    151. //3.Stack_BySequenceList_Main.c 部分
    152. #pragma once
    153. #define _CRT_SECURE_NO_WARNINGS
    154. #include
    155. #include
    156. #include
    157. #include
    158. #include
    159. #include
    160. #include
    161. #include
    162. #include
    163. #include"Stack_BySequenceList_Head.h"
    164. //测试
    165. //1.定义数据结构体
    166. struct Person
    167. {
    168. char name[64];
    169. int age;
    170. };
    171. int main()
    172. {
    173. //初始化栈
    174. pSeqStack myStack = InitSeqStack();
    175. //创建数据
    176. struct Person p1 = { "aaa", 10 };
    177. struct Person p2 = { "bbb", 20 };
    178. struct Person p3 = { "ccc", 30 };
    179. struct Person p4 = { "ddd", 40 };
    180. struct Person p5 = { "eee", 50 };
    181. //入栈
    182. PushSeqStack(myStack, &p1);
    183. PushSeqStack(myStack, &p2);
    184. PushSeqStack(myStack, &p3);
    185. PushSeqStack(myStack, &p4);
    186. PushSeqStack(myStack, &p5);
    187. printf("栈的元素个数为:%d\n", SeqStackSize(myStack));
    188. //栈不为空则查看栈顶元素再出栈
    189. while (IsEmptyStackSize(myStack) == 0)
    190. {
    191. struct Person* p = TopStackSize(myStack);
    192. printf("姓名:%s 年龄:%d\n", p->name, p->age);
    193. //出栈
    194. PopSeqStack(myStack);
    195. }
    196. printf("栈的元素个数为:%d\n", SeqStackSize(myStack));
    197. //销毁栈
    198. DestroyStackSize(myStack);
    199. return 0;
    200. }

     

     

    3.1.3栈的链式存储

    • 基本概念

    栈的链式存储结构简称链栈。

    思考如下问题

    栈只是栈顶来做插入和删除操作,栈顶放在链表的头部还是尾部呢?

    由于单链表有头指针,而栈顶指针也是必须的,所以比较好的办法就是把栈顶放在单链表的头部。另外都已经有了栈顶在头部了,单链表中比较常用的头结点也就失去了意义,通常对于链栈来说,是不需要头结点的。

    • 设计与实现

    链栈是一种特殊的线性表,链栈可以通过链式线性表来实现。

    3.1.4代码实现

    1.创建三个文件

    2.代码

    1. //1.Stack_ByLinkedList_Head.h 部分
    2. #pragma once
    3. #define _CRT_SECURE_NO_WARNINGS
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. typedef void* pLinkedStack;
    14. //1.定义指针结构体
    15. struct StackNode
    16. {
    17. struct StackNode* next;
    18. };
    19. //2.定义栈的结构体
    20. struct LinkedStack
    21. {
    22. struct StackNode pHeader;
    23. int Size;
    24. };
    25. //3.初始化栈函数声明
    26. pLinkedStack InitLinkedStack();
    27. //4.入栈函数声明
    28. void PushLinkedStack(pLinkedStack stack, void* data);
    29. //5.出栈函数声明
    30. void PopLinkedStack(pLinkedStack stack);
    31. //6.返回栈顶元素函数声明
    32. void* TopLinkedStack(pLinkedStack stack);
    33. //7.返回栈元素个数函数声明
    34. int SizeLinkedStack(pLinkedStack stack);
    35. //8.判断栈是否为空函数声明
    36. int IsEmptyLinkedStack(pLinkedStack stack);
    37. //9.栈销毁函数声明
    38. void DestroyLinkedStack(pLinkedStack stack);
    39. //2.Stack_ByLinkedList_Function.c 部分
    40. #pragma once
    41. #define _CRT_SECURE_NO_WARNINGS
    42. #include
    43. #include
    44. #include
    45. #include
    46. #include
    47. #include
    48. #include
    49. #include
    50. #include
    51. #include"Stack_ByLinkedList_Head.h"
    52. //3.初始化栈函数实现
    53. pLinkedStack InitLinkedStack()
    54. {
    55. struct LinkedStack* mystack = malloc(sizeof(struct LinkedStack));
    56. if (mystack == NULL)
    57. {
    58. return NULL;
    59. }
    60. mystack->pHeader.next = NULL;
    61. mystack->Size = 0;
    62. }
    63. //4.入栈函数声实现
    64. void PushLinkedStack(pLinkedStack stack, void* data)
    65. {
    66. //入栈本质——链表头插
    67. if (stack == NULL)
    68. {
    69. return;
    70. }
    71. if (data == NULL)
    72. {
    73. return;
    74. }
    75. struct LinkedStack* mystack = stack;
    76. //将用户数据取出前4个字节
    77. struct StackNode* mynode = data;
    78. //更改指针指向
    79. mynode->next = mystack->pHeader.next;
    80. mystack->pHeader.next = mynode;
    81. //更新链表长度
    82. mystack->Size++;
    83. }
    84. //5.出栈函数声明
    85. void PopLinkedStack(pLinkedStack stack)
    86. {
    87. //出战本质——链表头删
    88. if (stack == NULL)
    89. {
    90. return;
    91. }
    92. struct LinkedStack* mystack = stack;
    93. if(mystack->Size==0)
    94. {
    95. return;
    96. }
    97. //更改指针指向
    98. mystack->pHeader.next = mystack->pHeader.next->next;
    99. //更新栈大小
    100. mystack->Size--;
    101. }
    102. //6.返回栈顶元素函数实现
    103. void* TopLinkedStack(pLinkedStack stack)
    104. {
    105. if (stack == NULL)
    106. {
    107. return;
    108. }
    109. struct LinkedStack* mystack = stack;
    110. if (mystack->Size == 0)
    111. {
    112. return;
    113. }
    114. return mystack->pHeader.next;
    115. }
    116. //7.返回栈元素个数函数实现
    117. int SizeLinkedStack(pLinkedStack stack)
    118. {
    119. if (stack == NULL)
    120. {
    121. //返回-1表示栈不存在
    122. return -1;
    123. }
    124. struct LinkedStack* mystack = stack;
    125. return mystack->Size;
    126. }
    127. //8.判断栈是否为空函数实现
    128. int IsEmptyLinkedStack(pLinkedStack stack)
    129. {
    130. if (stack == NULL)
    131. {
    132. //返回-1表示栈不存在
    133. return -1;
    134. }
    135. struct LinkedStack* mystack = stack;
    136. if (mystack->Size == 0)
    137. {
    138. //返回-1表示栈为空
    139. return 1;
    140. }
    141. //返回0表示栈不为空
    142. return 0;
    143. }
    144. //9.栈销毁函数实现
    145. void DestroyLinkedStack(pLinkedStack stack)
    146. {
    147. if (stack == NULL)
    148. {
    149. return;
    150. }
    151. free(stack);
    152. stack = NULL;
    153. }
    154. //3.Stack_ByLinkedList_Main.c 部分
    155. #pragma once
    156. #define _CRT_SECURE_NO_WARNINGS
    157. #include
    158. #include
    159. #include
    160. #include
    161. #include
    162. #include
    163. #include
    164. #include
    165. #include
    166. #include"Stack_ByLinkedList_Head.h"
    167. //测试
    168. struct Person
    169. {
    170. void* node;
    171. char name[64];
    172. int age;
    173. };
    174. int main()
    175. {
    176. //初始化栈
    177. pLinkedStack myStack = InitLinkedStack();
    178. //创建数据
    179. struct Person p1 = { NULL, "aaa", 10 };
    180. struct Person p2 = { NULL, "bbb", 20 };
    181. struct Person p3 = { NULL, "ccc", 30 };
    182. struct Person p4 = { NULL, "ddd", 40 };
    183. struct Person p5 = { NULL, "eee", 50 };
    184. //入栈
    185. PushLinkedStack(myStack, &p1);
    186. PushLinkedStack(myStack, &p2);
    187. PushLinkedStack(myStack, &p3);
    188. PushLinkedStack(myStack, &p4);
    189. PushLinkedStack(myStack, &p5);
    190. printf("链式存储-- 栈的元素个数为:%d\n", SizeLinkedStack(myStack));
    191. //栈不为空,查看栈顶元素,出栈
    192. while (IsEmptyLinkedStack(myStack) == 0)
    193. {
    194. struct Person* p = TopLinkedStack(myStack);
    195. printf("姓名:%s 年龄:%d\n", p->name, p->age);
    196. //出栈
    197. PopLinkedStack(myStack);
    198. }
    199. printf("链式存储-- 栈的元素个数为:%d\n", SizeLinkedStack(myStack));
    200. //销毁栈
    201. DestroyLinkedStack(myStack);
    202. return 0;
    203. }

     

     

    3.2队列(Queue)

    3.2.1队列基本概念

    队列是一种特殊的受限制的线性表。  

    队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表。

    队列是一种先进先出的t(First In First Out)的线性表,简称FIFO。允许插入的一端为队尾,允许删除的一端为队头。队列不允许在中间部位进行操作!假设队列是q=(a1,a2,……,an),那么a1就是队头元素,而an是队尾元素。这样我们就可以删除时,总是从a1开始,而插入时,总是在队列最后。这也比较符合我们通常生活中的习惯,排在第一个的优先出列,最后来的当然排在队伍最后。如下图:

    3.2.3队列的顺序存储

    • 基本概念

    队列也是一种特殊的线性表;可以用线性表顺序存储来模拟队列。

    1.创建三个文件

    2.代码

    1. //1.Queue_BySequence List_Head.h 部分
    2. #pragma once
    3. #define _CRT_SECURE_NO_WARNINGS
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #define MAX 1024
    14. typedef void* pSeqQueue;
    15. //1.定义队列结构体
    16. struct SeqQueue
    17. {
    18. void** pQueue;
    19. int Capacity;
    20. int Size;
    21. };
    22. //2.初始化队列结构体函数声明
    23. pSeqQueue InitSeqQueue(int capacity);
    24. //3.入队列函数声明
    25. void PushSeqQueue(pSeqQueue queue, void* data);
    26. //4.出队列函数声明
    27. void PopSeqQueue(pSeqQueue queue);
    28. //5.返回队列大小函数声明
    29. int SizeSeqQueue(pSeqQueue queue);
    30. //6.判断队列是否为空函数声明
    31. int IsEmptySeqQueue(pSeqQueue queue);
    32. //7.返回对头元素函数声明
    33. void* FrontSeqQueue(pSeqQueue queue);
    34. //8.返回队尾元素函数声明
    35. void* BackSeqQueue(pSeqQueue queue);
    36. //9.销魂队列函数声明
    37. void DestroySeqQueue(pSeqQueue queue);
    38. //2.Queue_BySequence List_Function.c 部分
    39. #pragma once
    40. #define _CRT_SECURE_NO_WARNINGS
    41. #include
    42. #include
    43. #include
    44. #include
    45. #include
    46. #include
    47. #include
    48. #include
    49. #include
    50. #include"Queue_BySequence List_Head.h"
    51. //2.初始化队列结构体函数实现
    52. pSeqQueue InitSeqQueue(int capacity)
    53. {
    54. if (capacity == 0)
    55. {
    56. return;
    57. }
    58. struct SeqQueue* myQueue = malloc(sizeof(struct SeqQueue));
    59. if (myQueue == NULL)
    60. {
    61. return NULL;
    62. }
    63. myQueue->pQueue = malloc(sizeof(void*) * capacity);
    64. myQueue->Capacity = capacity;
    65. myQueue->Size = 0;
    66. return myQueue;
    67. }
    68. //3.入队列函数声明
    69. void PushSeqQueue(pSeqQueue queue, void* data)
    70. {
    71. //入队列本——数组头插
    72. if (queue == NULL)
    73. {
    74. return;
    75. }
    76. if (data == NULL)
    77. {
    78. return;
    79. }
    80. struct SeqQueue* myQueue = queue;
    81. if (myQueue->Size == MAX)
    82. {
    83. return;
    84. }
    85. for (int i = myQueue->Size - 1; i >= 0; i--)
    86. {
    87. myQueue->pQueue[i + 1] = myQueue->pQueue[i];
    88. }
    89. myQueue->pQueue[0] = data;
    90. myQueue->Size++;
    91. }
    92. //4.出队列函数实现
    93. void PopSeqQueue(pSeqQueue queue)
    94. {
    95. //本质——尾删
    96. if (queue == NULL)
    97. {
    98. return;
    99. }
    100. struct SeqQueue* myQueue = queue;
    101. if (myQueue->Size == 0)
    102. {
    103. return;
    104. }
    105. myQueue->Size--;
    106. }
    107. //5.返回队列大小函数实现
    108. int SizeSeqQueue(pSeqQueue queue)
    109. {
    110. if (queue == NULL)
    111. {
    112. return -1;
    113. }
    114. struct SeqQueue* myQueue = queue;
    115. return myQueue->Size;
    116. }
    117. //6.判断队列是否为空函数实现
    118. int IsEmptySeqQueue(pSeqQueue queue)
    119. {
    120. if (queue == NULL)
    121. {
    122. //返回-1表示队列不存在
    123. return -1;
    124. }
    125. struct SeqQueue* myQueue = queue;
    126. if (myQueue->Size == 0)
    127. {
    128. //返回1表示队列为空
    129. return 1;
    130. }
    131. return 0;
    132. }
    133. //7.返回队头元素函数实现
    134. void* FrontSeqQueue(pSeqQueue queue)
    135. {
    136. if (queue == NULL)
    137. {
    138. return NULL;
    139. }
    140. struct SeqQueue* myQueue = queue;
    141. return myQueue->pQueue[myQueue->Size - 1];
    142. }
    143. //8.返回队尾元素函数实现
    144. void* BackSeqQueue(pSeqQueue queue)
    145. {
    146. if(queue==NULL)
    147. {
    148. return NULL;
    149. }
    150. struct SeqQueue* myQueue = queue;
    151. return myQueue->pQueue[0];
    152. }
    153. //9.销魂队列函数实现
    154. void DestroySeqQueue(pSeqQueue queue)
    155. {
    156. if (queue == NULL)
    157. {
    158. return;
    159. }
    160. struct SeqQueue* myQueue = queue;
    161. free(myQueue->pQueue);
    162. myQueue->pQueue = NULL;
    163. free(myQueue);
    164. myQueue = NULL;
    165. }
    166. //3.Queue_BySequence List_Main.c 部分
    167. #pragma once
    168. #define _CRT_SECURE_NO_WARNINGS
    169. #include
    170. #include
    171. #include
    172. #include
    173. #include
    174. #include
    175. #include
    176. #include
    177. #include
    178. #include"Queue_BySequence List_Head.h"
    179. //测试
    180. //1.定义数据结构体
    181. struct Person
    182. {
    183. char name[64];
    184. int age;
    185. };
    186. int main()
    187. {
    188. //初始化队列
    189. pSeqQueue myQueue = InitSeqQueue(MAX);
    190. //准备数据
    191. struct Person p1 = { "aaa", 10 };
    192. struct Person p2 = { "bbb", 20 };
    193. struct Person p3 = { "ccc", 30 };
    194. struct Person p4 = { "ddd", 40 };
    195. //入队
    196. PushSeqQueue(myQueue, &p1);
    197. PushSeqQueue(myQueue, &p2);
    198. PushSeqQueue(myQueue, &p3);
    199. PushSeqQueue(myQueue, &p4);
    200. printf("队列大小为:%d\n", SizeSeqQueue(myQueue));
    201. while (IsEmptySeqQueue(myQueue) == 0)
    202. {
    203. //访问队头
    204. struct Person* pFront = FrontSeqQueue(myQueue);
    205. printf("队头元素 -- 姓名:%s 年龄: %d\n", pFront->name, pFront->age);
    206. //访问队尾
    207. struct Person* pBack = BackSeqQueue(myQueue);
    208. printf("队尾元素 -- 姓名:%s 年龄: %d\n", pBack->name, pBack->age);
    209. //出队
    210. PopSeqQueue(myQueue);
    211. }
    212. printf("队列大小为:%d\n", SizeSeqQueue(myQueue));
    213. //销毁队列
    214. DestroySeqQueue(myQueue);
    215. return 0;
    216. }

     

    3.2.4队列的链式存储

    • 基本概念

    队列也是一种特殊的线性表;可以用线性表链式存储来模拟队列的链式存储。

    1.创建三个文件

     

    2.代码

    1. //1.Queue_ByLinkedList_Head.h 部分
    2. #pragma once
    3. #define _CRT_SECURE_NO_WARNINGS
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. typedef void* pLinkedQueue;
    14. //1.定义节点结构体
    15. struct QueueNode
    16. {
    17. struct QueueNode* next;
    18. };
    19. //2.定义队列结构体
    20. struct LinkedQueue
    21. {
    22. struct QueueNode pLinkedQueueHeader;
    23. struct QueueNode* pLinkedQueueTail;
    24. int Size;
    25. };
    26. //3.队列初始化函数声明
    27. pLinkedQueue InitLinkedQueue();
    28. //4.入队列函数声明
    29. void PushLinkedQueue(pLinkedQueue queue, void* data);
    30. //5.出队列函数声明
    31. void PopLinkedQueue(pLinkedQueue queue);
    32. //6.返回队列大小函数声明
    33. int SizeLinkedQueue(pLinkedQueue queue);
    34. //7.判断队列是否为空函数声明
    35. int IsEmptyLinkedQueue(pLinkedQueue queue);
    36. //8.返回队头函数声明
    37. void* FrontLinkedQueue(pLinkedQueue queue);
    38. //9.返回队尾函数声明
    39. void* BackLinkedQueue(pLinkedQueue queue);
    40. //10.销毁函数声明
    41. void DestroyLinkedQueue(pLinkedQueue queue);
    42. //2.Queue_ByLinkedList_Function.c 部分
    43. #pragma once
    44. #define _CRT_SECURE_NO_WARNINGS
    45. #include
    46. #include
    47. #include
    48. #include
    49. #include
    50. #include
    51. #include
    52. #include
    53. #include
    54. #include"Queue_ByLinkedList_Head.h"
    55. //3.队列初始化函数实现
    56. pLinkedQueue InitLinkedQueue()
    57. {
    58. struct LinkedQueue* myQueue = malloc(sizeof(struct LinkedQueue));
    59. if (myQueue == NULL)
    60. {
    61. return NULL;
    62. }
    63. myQueue->pLinkedQueueHeader.next = NULL;
    64. myQueue->pLinkedQueueTail = &myQueue->pLinkedQueueHeader;
    65. myQueue->Size = 0;
    66. return myQueue;
    67. }
    68. //4.入队列函数实现
    69. void PushLinkedQueue(pLinkedQueue queue, void* data)
    70. {
    71. if (queue == NULL)
    72. {
    73. return;
    74. }
    75. if (data == NULL)
    76. {
    77. return;
    78. }
    79. struct LinkedQueue* myQueue = queue;
    80. struct QueueNode* myQueueNode = data;
    81. myQueue->pLinkedQueueTail->next = myQueueNode;
    82. myQueueNode->next = NULL;
    83. //更新新的尾节点
    84. myQueue->pLinkedQueueTail = myQueueNode;
    85. myQueue->Size++;
    86. }
    87. //5.出队列函数实现
    88. void PopLinkedQueue(pLinkedQueue queue)
    89. {
    90. if (queue == NULL)
    91. {
    92. return;
    93. }
    94. struct LinkedQueue* myQueue = queue;
    95. if (myQueue->Size == 0)
    96. {
    97. return;
    98. }
    99. //当只有一个节点时情况需要特殊处理
    100. if (myQueue->Size == 1)
    101. {
    102. myQueue->pLinkedQueueHeader.next = NULL;
    103. myQueue->pLinkedQueueTail = &myQueue->pLinkedQueueHeader;
    104. myQueue->Size--;
    105. return;
    106. }
    107. //更改指针方向
    108. myQueue->pLinkedQueueHeader.next = myQueue->pLinkedQueueHeader.next->next;
    109. myQueue->Size--;
    110. }
    111. //6.返回队列大小函数实现
    112. int SizeLinkedQueue(pLinkedQueue queue)
    113. {
    114. if (queue == NULL)
    115. {
    116. return -1;
    117. }
    118. struct LinkedQueue* myQueue = queue;
    119. return myQueue->Size;
    120. }
    121. //7.判断队列是否为空函数实现
    122. int IsEmptyLinkedQueue(pLinkedQueue queue)
    123. {
    124. if (queue == NULL)
    125. {
    126. return -1;
    127. }
    128. struct LinkedQueue* myQueue = queue;
    129. if (myQueue->Size == 0)
    130. {
    131. return 1;
    132. }
    133. return 0;
    134. }
    135. //8.返回队头函数实现
    136. void* FrontLinkedQueue(pLinkedQueue queue)
    137. {
    138. if (queue == NULL)
    139. {
    140. return;
    141. }
    142. struct LinkedQueue* myQueue = queue;
    143. return myQueue->pLinkedQueueHeader.next;
    144. }
    145. //9.返回队尾函数实现
    146. void* BackLinkedQueue(pLinkedQueue queue)
    147. {
    148. if (queue == NULL)
    149. {
    150. return;
    151. }
    152. struct LinkedQueue* myQueue = queue;
    153. return myQueue->pLinkedQueueTail;
    154. }
    155. //10.销毁函数实现
    156. void DestroyLinkedQueue(pLinkedQueue queue)
    157. {
    158. if (queue == NULL)
    159. {
    160. return;
    161. }
    162. free(queue);
    163. queue = NULL;
    164. }
    165. //3.Queue_ByLinkedList_Main.c 部分
    166. #pragma once
    167. #define _CRT_SECURE_NO_WARNINGS
    168. #include
    169. #include
    170. #include
    171. #include
    172. #include
    173. #include
    174. #include
    175. #include
    176. #include
    177. #include"Queue_ByLinkedList_Head.h"
    178. //测试
    179. //1.定义数据结构体
    180. struct Person
    181. {
    182. void* node;
    183. char name[64];
    184. int age;
    185. };
    186. int main()
    187. {
    188. //初始化队列
    189. pLinkedQueue myQueue = InitLinkedQueue();
    190. //准备数据
    191. struct Person p1 = { NULL,"aaa", 10 };
    192. struct Person p2 = { NULL,"bbb", 20 };
    193. struct Person p3 = { NULL,"ccc", 30 };
    194. struct Person p4 = { NULL,"ddd", 40 };
    195. //入队
    196. PushLinkedQueue(myQueue, &p1);
    197. PushLinkedQueue(myQueue, &p2);
    198. PushLinkedQueue(myQueue, &p3);
    199. PushLinkedQueue(myQueue, &p4);
    200. printf("队列大小为:%d\n", SizeLinkedQueue(myQueue));
    201. while (IsEmptyLinkedQueue(myQueue) == 0)
    202. {
    203. //访问队头
    204. struct Person* pFront = FrontLinkedQueue(myQueue);
    205. printf("链式存储::队头元素 -- 姓名:%s 年龄: %d\n", pFront->name, pFront->age);
    206. //访问队尾
    207. struct Person* pBack = BackLinkedQueue(myQueue);
    208. printf("链式存储::队尾元素 -- 姓名:%s 年龄: %d\n", pBack->name, pBack->age);
    209. //出队
    210. PopLinkedQueue(myQueue);
    211. }
    212. printf("队列大小为:%d\n", SizeLinkedQueue(myQueue));
    213. //销毁队列
    214. DestroyLinkedQueue(myQueue);
    215. return 0;
    216. }

     

     

  • 相关阅读:
    酷玩Go命令行工具—Cobra
    微服务的发展历程的详细说明及每个阶段主流的架构和组件
    Notion+Zotero+Notero 联动教程(23年9月更新版)
    猿创征文丨赶紧进来!!! 详细介绍C语言指针(九千字完结篇)
    SingletonKit单例源码阅读学习
    ETH2.0 合并,投资者该做些什么准备?
    [unity]三角形顶点顺序
    16-Linux磁盘管理
    电商后台项目 + 源码
    一次企业网丢包故障定位过程
  • 原文地址:https://blog.csdn.net/qq_43205256/article/details/126042073