当前位置:   article > 正文

线性表的简单实现_线性表怎么创建

线性表怎么创建

1. 写在前面

作为计算机领域的核心基础理论学科之一——数据结构,其讨论研究的主要相关内容为,数据是如何在内存中进行存储与管理的;我们知道,应用程序(.exe文件)在运行时,会将存储在磁盘中的数据读入到内存中,再进行相应的处理操作;而在这一过程中,数据在内存中的存储组织方式就显得十分的重要啦;在算法中,根据实际业务需求,采用合适的数据组织方式,能极大地发挥出算法的威力,提高算法的性能。而笔者今天的内容,主要是对近期学习线性表这一数据结构知识的总结与梳理,内容如下:

2. 线性表的定义

什么是线性表?(What)

线性表(linear list): 是n个具有相同特性数据元素的有限序列。

常见的线性表:

  • 顺序表  -  (数组)
  • 链表
  • 队列
  • 字符串

值得注意的是:线性表在逻辑上是连续的,但在物理存储结构上不一定是连续的,如链表。

3. 顺序表

3.1 顺序表的定义

什么是顺序表?(What)

顺序表:用一段物理地址连续的存储单元依次存储数据元素的线性结构

常见顺序表:

  • 静态顺序表:使用定长数组存储元素
  • 动态顺序表:使用动态开辟的元素存储元素

3.2 顺序表的实现

支持动态增长的顺序表实现

代码实现

SeqList.h :类型与函数的声明

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. #define __DEBUG__ 0
  6. // 静态顺序表
  7. #if __DEBUG__
  8. #define N 100 // 定长数组的大小
  9. typedef int SLDdataType; // 重命名顺序表的数据类型
  10. struct SeqList
  11. {
  12. SLDdataType a[N]; // 定长数组
  13. int size; // 已存储的数据个数
  14. };
  15. #endif
  16. // 动态顺序表
  17. typedef int SLDataType;
  18. typedef struct SeqList
  19. {
  20. SLDataType* a; // 指向动态开辟的数组
  21. int size; // 有效的数据个数
  22. int capacity; // 动态数组的容量
  23. }SL;
  24. // 功能操作
  25. void SeqListInit(SL* ps); // 初始化
  26. void SeqListPrint(SL* ps); // 打印
  27. void SeqListDestory(SL* ps); // 销毁
  28. void SeqListCheckCapacity(SL* ps); // 检查容量
  29. void SeqListPushBack(SL* ps, SLDataType x); // 尾插
  30. void SeqListPopBack(SL* ps); // 尾删
  31. void SeqListPushFront(SL* ps, SLDataType x); // 头插
  32. void SeqListPopFront(SL* ps); // 头删
  33. void SeqListInsert(SL* ps, int pos, SLDataType x); // 任意位置插入
  34. void SeqListErase(SL* ps, int pos); // 任意位置删除
  35. void SeqListModify(SL* ps, int pos, SLDataType x); // 修改
  36. int SeqListFind(SL* ps, SLDataType x); // 查找

SeqList.c  : 功能实现

  1. #include "SeqList.h"
  2. // 初始化
  3. void SeqListInit(SL* ps)
  4. {
  5. assert(ps);
  6. ps->a = NULL;
  7. ps->size = 0;
  8. ps->capacity = 0;
  9. }
  10. // 销毁
  11. void SeqListDestory(SL* ps)
  12. {
  13. if (ps->a)
  14. {
  15. free(ps->a);
  16. ps->a = NULL;
  17. ps->capacity = ps->size = 0;
  18. }
  19. }
  20. // 打印
  21. void SeqListPrint(SL* ps)
  22. {
  23. assert(ps);
  24. int i = 0;
  25. for (i = 0; i < ps->size; i++)
  26. {
  27. printf("%d ", ps->a[i]);
  28. }
  29. printf("\n");
  30. }
  31. // 扩容
  32. void SeqListCheckCapacity(SL* ps)
  33. {
  34. assert(ps);
  35. if (ps->size == ps->capacity)
  36. {
  37. int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
  38. SLDataType* tmp = (SLDataType*)realloc(ps->a, newCapacity * sizeof(SLDataType));
  39. if (tmp != NULL)
  40. {
  41. ps->a = tmp;
  42. }
  43. else
  44. {
  45. perror("CheckCapacity::realloc\n");
  46. exit(-1);
  47. }
  48. ps->capacity = newCapacity;
  49. }
  50. }
  51. // 尾插
  52. void SeqListPushBack(SL* ps, SLDataType x)
  53. {
  54. SeqListInsert(ps, ps->size, x);
  55. //assert(ps);
  56. 检查容量空间
  57. //SeqListCheckCapacity(ps);
  58. //ps->a[ps->size] = x;
  59. //ps->size++;
  60. }
  61. // 头插
  62. void SeqListPushFront(SL* ps, SLDataType x)
  63. {
  64. SeqListInsert(ps, 0, x);
  65. //assert(ps);
  66. //SeqListCheckCapacity(ps);
  67. 挪动数据
  68. //int end = ps->size - 1;
  69. //while (end >= 0)
  70. //{
  71. // ps->a[end + 1] = ps->a[end];
  72. // end--;
  73. //}
  74. //ps->a[0] = x;
  75. //ps->size++;
  76. }
  77. // 尾删
  78. void SeqListPopBack(SL* ps)
  79. {
  80. SeqListErase(ps, ps->size - 1);
  81. //assert(ps);
  82. 暴力检查
  83. //assert(ps->size);
  84. ps->size--;
  85. 避免越界访问越界访问
  86. //if (ps->size)
  87. //{
  88. // ps->size--;
  89. //}
  90. //else
  91. //{
  92. // printf("SeqList is already empty"); // 温柔检查
  93. // exit(-1);
  94. //}
  95. }
  96. // 头删
  97. void SeqListPopFront(SL* ps)
  98. {
  99. SeqListErase(ps, 0);
  100. //assert(ps);
  101. //assert(ps->size);
  102. //int i = 0;
  103. //if (ps->size)
  104. //{
  105. // for (i = 0; i < ps->size - 1; i++)
  106. // {
  107. // ps->a[i] = ps->a[i + 1];
  108. // }
  109. // ps->size--;
  110. //}
  111. //else
  112. //{
  113. // printf("SeqList is already empty"); // 温柔检查
  114. // exit(-1);
  115. //}
  116. }
  117. // 任意位置插入
  118. void SeqListInsert(SL* ps, int pos, SLDataType x)
  119. {
  120. // 防御式检查
  121. assert(ps);
  122. assert(pos >= 0 && pos <= ps->size);
  123. SeqListCheckCapacity(ps);
  124. int end = ps->size - 1;
  125. while (end >= pos)
  126. {
  127. ps->a[end + 1] = ps->a[end];
  128. end--;
  129. }
  130. ps->a[pos] = x;
  131. ps->size++;
  132. }
  133. // 任意位置删除
  134. void SeqListErase(SL* ps, int pos)
  135. {
  136. assert(ps);
  137. assert(pos >= 0 && pos < ps->size);
  138. int begin = pos;
  139. while (begin < ps->size-1) // 边界控制
  140. {
  141. ps->a[begin] = ps->a[begin + 1];
  142. begin++;
  143. }
  144. ps->size--;
  145. }
  146. // 查找
  147. int SeqListFind(SL* ps, SLDataType x)
  148. {
  149. assert(ps);
  150. int i = 0;
  151. for (i = 0; i < ps->size; i++)
  152. {
  153. if (ps->a[i] == x)
  154. {
  155. return i; // 返回下标
  156. }
  157. }
  158. return -1;
  159. }
  160. // 修改
  161. void SeqListModify(SL* ps, int pos, SLDataType x)
  162. {
  163. assert(ps);
  164. assert(pos >= 0 && pos < ps->size);
  165. ps->a[pos] = x;
  166. }

New.c : 功能测试 

  1. #include "SeqList.h"
  2. void Test1()
  3. {
  4. SL s1;
  5. SeqListInit(&s1);
  6. SeqListPushBack(&s1, 1);
  7. SeqListPushBack(&s1, 2);
  8. SeqListPushBack(&s1, 3);
  9. SeqListPushBack(&s1, 4);
  10. SeqListPrint(&s1);
  11. SeqListPushBack(&s1, 5);
  12. SeqListPushBack(&s1, 4);
  13. SeqListPushBack(&s1, 3);
  14. SeqListPushBack(&s1, 2);
  15. SeqListPushBack(&s1, 1);
  16. SeqListPrint(&s1);
  17. }
  18. void Test2()
  19. {
  20. SL s1;
  21. SL* ps = &s1;
  22. SeqListInit(ps);
  23. SeqListPushFront(&s1, 5);
  24. SeqListPushFront(&s1, 4);
  25. SeqListPushFront(&s1, 3);
  26. SeqListPushFront(&s1, 2);
  27. SeqListPushFront(&s1, 1);
  28. SeqListPrint(ps);
  29. SeqListPushBack(&s1, 4);
  30. SeqListPushBack(&s1, 3);
  31. SeqListPushBack(&s1, 2);
  32. SeqListPushBack(&s1, 1);
  33. SeqListPrint(ps);
  34. }
  35. void Test3()
  36. {
  37. SL s1;
  38. SL* ps = &s1;
  39. SeqListInit(ps);
  40. SeqListPushFront(ps, 5);
  41. SeqListPushFront(ps, 4);
  42. SeqListPushFront(ps, 3);
  43. SeqListPushFront(ps, 2);
  44. SeqListPushFront(ps, 1);
  45. SeqListPrint(ps);
  46. SeqListPopBack(ps);
  47. SeqListPopBack(ps);
  48. SeqListPopBack(ps);
  49. SeqListPopBack(ps);
  50. SeqListPopBack(ps);
  51. SeqListPopBack(ps);
  52. SeqListPopBack(ps);
  53. SeqListPushFront(ps, 2);
  54. SeqListPushFront(ps, 3);
  55. SeqListPushFront(ps, 2);
  56. SeqListPrint(ps);
  57. SeqListDestory(ps);
  58. }
  59. void Test4()
  60. {
  61. SL s1;
  62. SL* ps = &s1;
  63. SeqListInit(ps);
  64. SeqListPushFront(&s1, 5);
  65. SeqListPushFront(&s1, 4);
  66. SeqListPushFront(&s1, 3);
  67. SeqListPushFront(&s1, 2);
  68. SeqListPushFront(&s1, 1);
  69. SeqListPrint(ps);
  70. SeqListPopFront(ps);
  71. SeqListPopFront(ps);
  72. SeqListPopFront(ps);
  73. SeqListPopFront(ps);
  74. SeqListPopFront(ps);
  75. SeqListPopFront(ps);
  76. SeqListPopFront(ps);
  77. SeqListPrint(ps);
  78. }
  79. void Test5()
  80. {
  81. SL s1;
  82. SL* ps = &s1;
  83. SeqListInit(ps);
  84. SeqListPushFront(&s1, 5);
  85. SeqListPushFront(&s1, 4);
  86. SeqListPushFront(&s1, 3);
  87. SeqListPushFront(&s1, 2);
  88. SeqListPushFront(&s1, 1);
  89. SeqListPrint(ps);
  90. SeqListInsert(ps, 0, 8);
  91. SeqListPrint(ps);
  92. }
  93. void Test6()
  94. {
  95. SL s1;
  96. SL* ps = &s1;
  97. SeqListInit(ps);
  98. SeqListPushFront(&s1, 5);
  99. SeqListPushFront(&s1, 4);
  100. SeqListPushFront(&s1, 3);
  101. SeqListPushFront(&s1, 2);
  102. SeqListPushFront(&s1, 1);
  103. SeqListPrint(ps);
  104. SeqListErase(ps, 2);
  105. SeqListPrint(ps);
  106. SeqListErase(ps, 0);
  107. SeqListPrint(ps);
  108. SeqListErase(ps, ps->size-1);
  109. SeqListPrint(ps);
  110. SeqListPopFront(ps);
  111. SeqListPushFront(ps, 6);
  112. SeqListPrint(ps);
  113. SeqListPopBack(ps);
  114. SeqListPrint(ps);
  115. }
  116. void Test7()
  117. {
  118. SL s1;
  119. SL* ps = &s1;
  120. SeqListInit(ps);
  121. SeqListPushFront(&s1, 5);
  122. SeqListPushFront(&s1, 4);
  123. SeqListPushFront(&s1, 3);
  124. SeqListPushFront(&s1, 2);
  125. SeqListPushFront(&s1, 1);
  126. SeqListPrint(ps);
  127. int x = 0;
  128. printf("请输入你要删除的值:> ");
  129. scanf("%d", &x);
  130. int pos = SeqListFind(ps, x);
  131. if (pos != -1)
  132. {
  133. SeqListErase(ps, pos);
  134. }
  135. else
  136. {
  137. printf("没有找到\n");
  138. }
  139. SeqListPrint(ps);
  140. }
  141. void Test8()
  142. {
  143. SL s1;
  144. SL* ps = &s1;
  145. SeqListInit(ps);
  146. SeqListPushFront(&s1, 5);
  147. SeqListPushFront(&s1, 4);
  148. SeqListPushFront(&s1, 3);
  149. SeqListPushFront(&s1, 2);
  150. SeqListPushFront(&s1, 1);
  151. SeqListPrint(ps);
  152. int y = 0;
  153. int z = 0;
  154. printf("请输入你要修改的值和修改之后的值:> ");
  155. scanf("%d %d", &y, &z);
  156. int pos = SeqListFind(ps, y);
  157. if (pos != -1)
  158. {
  159. SeqListModify(ps, pos, z);
  160. }
  161. else
  162. {
  163. printf("没有找到\n");
  164. }
  165. SeqListPrint(ps);
  166. }
  167. int main()
  168. {
  169. //Test1();
  170. //Test2();
  171. //Test3();
  172. //Test4();
  173. //Test5();
  174. //Test6();
  175. //Test7();
  176. Test8();
  177. return 0;
  178. }

运行结果

4. 链表

4.1 链表的定义

什么是链表?(What)

链表:物理存储非连续,数据存储的逻辑顺序是连续的线性存储结构

常见链表:

  • 无头单向非循环链表
  • 带头双向循环链表

4.2 链表的实现

无头单向非循环链表的实现

代码实现

SList.h : 功能与类型的声明

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. typedef int SLDataType;
  6. typedef struct SListNode
  7. {
  8. SLDataType data; // 存储的数据
  9. struct SListNode* next; // 指向下一个节点
  10. }SLNode;
  11. void SListPrint(SLNode* phead); // 打印
  12. SLNode* CreateSListNode(SLDataType* x); // 创建新节点
  13. void SListPushBack(SLNode** pphead, SLDataType x); // 尾插
  14. void SListPushFront(SLNode** pphead, SLDataType x); // 头插
  15. void SListPopBack(SLNode** pphead); // 尾删
  16. void SListPopFront(SLNode** pphead); // 头删
  17. SLNode* SListFind(SLNode* phead, SLDataType x); // 查找
  18. void SListModify(SLNode* pos, SLDataType x, SLDataType y); // 修改
  19. void SListInsert(SLNode** pphead, SLNode* pos, SLDataType x); // 在指定位置之前插入
  20. void SListInsertAfter(SLNode* pos, SLDataType x); // 在指定位置之后插入
  21. void SListErase(SLNode** pphead, SLNode* pos); // 删除指定位置的节点
  22. void SListEraseAfter(SLNode* pos); // 在指定位置之后删除

SList.c :  功能实现

  1. #include"SList.h"
  2. // 打印
  3. void SListPrint(SLNode* phead)
  4. {
  5. SLNode* cur = phead;
  6. while (cur)
  7. {
  8. printf("%d->", cur->data);
  9. cur = cur->next;
  10. }
  11. printf("NULL\n");
  12. }
  13. // 创建新节点
  14. SLNode* CreateSListNode(SLDataType* x)
  15. {
  16. SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
  17. assert(newnode);
  18. newnode->data = x;
  19. newnode->next = NULL;
  20. return newnode;
  21. }
  22. // 尾插 想改变外部的指针(实参),就需要传入指针的地址;想在函数中改变外部变量(实参)的内容,就需要传入该外部变量的地址
  23. // 因为函数的形参只是实参的一份临时拷贝,与实参没有直接联系,只是模拟实参的效果,形参的改变对实参没有直接的影响
  24. void SListPushBack(SLNode** pphead, SLDataType x)
  25. {
  26. assert(pphead);
  27. // 允许空链表传入
  28. SLNode* cur = *pphead;
  29. SLNode* newnode = CreateSListNode(x);
  30. if (*pphead == NULL)
  31. {
  32. *pphead = newnode;
  33. }
  34. else
  35. {
  36. while (cur->next) // 找尾节点
  37. {
  38. cur = cur->next;
  39. }
  40. cur->next = newnode;
  41. }
  42. // 只有当节点不被需要了,才进行free操作
  43. // 函数结束,函数中定义的局部变量被销毁,但malloc的内存空间依旧存在有效
  44. }
  45. // 头插 使用二级指针,与外部的phead建立直接的联系,头插完成之后,phead要指向新的头节点
  46. void SListPushFront(SLNode** pphead, SLDataType x)
  47. {
  48. assert(pphead);
  49. // 允许空链表传入
  50. /*assert(*pphead);*/
  51. SLNode* cur = *pphead;
  52. SLNode* newnode = CreateSListNode(x);
  53. newnode->next = cur;
  54. *pphead = newnode;
  55. }
  56. // 尾删
  57. void SListPopBack(SLNode** pphead)
  58. {
  59. assert(pphead);
  60. // 链表本就为空,就不能再进行删除了
  61. assert(*pphead);
  62. // 只有一个节点
  63. if ((*pphead)->next == NULL)
  64. {
  65. free(*pphead);
  66. *pphead = NULL; // 改变了phead指针的值,所以要传二级指针
  67. }
  68. else // 多个节点
  69. {
  70. // 找尾节点的前一个节点
  71. SLNode* prev = *pphead;
  72. while (prev->next->next) // 当只有一个节点时,会有越界访问的问题
  73. {
  74. prev = prev->next;
  75. }
  76. SLNode* tail = prev->next;
  77. free(tail); // 释放掉tail指针指向的结构体空间; 但只有一个节点时,则会发生释放NULL指针的的错误
  78. prev->next = NULL; // 将尾节点的前一个节点的next指针,置空
  79. }
  80. }
  81. // 头删
  82. void SListPopFront(SLNode** pphead)
  83. {
  84. assert(pphead);
  85. // 链表本就为空,就不能再进行删除了
  86. assert(*pphead);
  87. SLNode* next = (*pphead)->next;
  88. free(*pphead); // 将结构体节点所占用的空间,进行释放,即销毁
  89. *pphead = next;
  90. }
  91. // 查找
  92. SLNode* SListFind(SLNode* phead, SLDataType x)
  93. {
  94. // 空链表无法进行查找
  95. assert(phead);
  96. SLNode* cur = phead;
  97. while (cur->next) // 逻辑有问题,如果查找的是尾节点,则将尾节点的情况直接跳过而没有进行检查
  98. {
  99. if (cur->data == x)
  100. {
  101. return cur;
  102. }
  103. cur = cur->next;
  104. }
  105. if (cur->data == x) // 检查一下跳过的尾节点
  106. return cur;
  107. else
  108. return NULL;
  109. }
  110. // 修改
  111. void SListModify(SLNode* phead, SLDataType x, SLDataType y)
  112. {
  113. SLNode* cur = SListFind(phead, x);
  114. if (cur)
  115. {
  116. cur->data = y;
  117. }
  118. else
  119. {
  120. printf("%d不存在\n", x);
  121. }
  122. }
  123. // 在pos节点之前插入
  124. void SListInsert(SLNode** pphead, SLNode* pos, SLDataType x)
  125. {
  126. // 以防恶意插入
  127. assert(pos);
  128. assert(pphead);
  129. // 空链表也可以传入
  130. SLNode* newnode = CreateSListNode(x);
  131. if (*pphead == NULL)
  132. {
  133. newnode->next = *pphead;
  134. *pphead = newnode;
  135. }
  136. else
  137. {
  138. // 找到pos节点的前一个节点
  139. SLNode* prev = *pphead;
  140. while (prev->next != pos)
  141. {
  142. prev = prev->next;
  143. }
  144. newnode->next = pos;
  145. prev->next = newnode;
  146. }
  147. }
  148. // 在pos之后进行插入
  149. void SListInsertAfter(SLNode* pos, SLDataType x)
  150. {
  151. // 以防恶意插入
  152. assert(pos);
  153. // 空链表无法进行查找,已在SListFind内进行断言,保证了pos的有效性
  154. SLNode* newnode = CreateSListNode(x);
  155. newnode->next = pos->next;
  156. pos->next = newnode;
  157. }
  158. // 删除指定位置的节点
  159. void SListErase(SLNode** pphead, SLNode* pos)
  160. {
  161. // 以防恶意删除
  162. assert(pos);
  163. assert(pphead);
  164. // 空链表无法进行删除,已在SListFind内进行断言,保证了*phead和pos的有效性
  165. // 找到pos的前一个节点
  166. if ((*pphead)->next == NULL) // 只有一个节点时
  167. {
  168. free(*pphead);
  169. *pphead = NULL;
  170. }
  171. else if (*pphead == pos) // 有多个节点时,要删除头节点
  172. {
  173. *pphead = pos->next;
  174. free(pos);
  175. }
  176. else // 有多个节点时,删除其它节点
  177. {
  178. SLNode* prev = *pphead;
  179. while (prev->next != pos)
  180. {
  181. prev = prev->next;
  182. }
  183. prev->next = pos->next;
  184. free(pos);
  185. }
  186. }
  187. // 在指定位置之后删除
  188. void SListEraseAfter(SLNode* pos)
  189. {
  190. // 以防恶意删除
  191. assert(pos);
  192. // 空链表无法进行删除,已在SListFind内进行断言,pos的有效性
  193. if (pos->next == NULL) // pos已为尾节点
  194. {
  195. return;
  196. }
  197. else
  198. {
  199. SLNode* after = pos->next->next;
  200. free(pos->next);
  201. pos->next = after;
  202. }
  203. }

New.c :  功能测试

  1. #include "SList.h"
  2. void Test1()
  3. {
  4. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  5. assert(n1);
  6. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  7. assert(n2);
  8. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  9. assert(n3);
  10. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  11. assert(n4);
  12. n1->data = 1;
  13. n2->data = 2;
  14. n3->data = 3;
  15. n4->data = 4;
  16. n1->next = n2;
  17. n2->next = n3;
  18. n3->next = n4;
  19. n4->next = NULL;
  20. SListPrint(n1);
  21. }
  22. void Test2()
  23. {
  24. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  25. assert(n1);
  26. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  27. assert(n2);
  28. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  29. assert(n3);
  30. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  31. assert(n4);
  32. n1->data = 1;
  33. n2->data = 2;
  34. n3->data = 3;
  35. n4->data = 4;
  36. n1->next = n2;
  37. n2->next = n3;
  38. n3->next = n4;
  39. n4->next = NULL;
  40. SListPrint(n1);
  41. SListPushBack(&n1, 5);
  42. SListPrint(&n1);
  43. SListPushBack(&n1, 4);
  44. SListPushBack(&n1, 3);
  45. SListPushBack(&n1, 2);
  46. SListPushBack(&n1, 1);
  47. SListPrint(n1);
  48. }
  49. void Test3()
  50. {
  51. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  52. assert(n1);
  53. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  54. assert(n2);
  55. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  56. assert(n3);
  57. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  58. assert(n4);
  59. n1->data = 1;
  60. n2->data = 2;
  61. n3->data = 3;
  62. n4->data = 4;
  63. n1->next = n2;
  64. n2->next = n3;
  65. n3->next = n4;
  66. n4->next = NULL;
  67. SListPrint(n1);
  68. SListPushFront(&n1, 0);
  69. SListPushFront(&n1, -1);
  70. SListPushFront(&n1, -2);
  71. SListPushFront(&n1, -3);
  72. SListPushFront(&n1, -4);
  73. SListPrint(n1);
  74. }
  75. void Test4()
  76. {
  77. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  78. assert(n1);
  79. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  80. assert(n2);
  81. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  82. assert(n3);
  83. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  84. assert(n4);
  85. n1->data = 1;
  86. n2->data = 2;
  87. n3->data = 3;
  88. n4->data = 4;
  89. n1->next = n2;
  90. n2->next = n3;
  91. n3->next = n4;
  92. n4->next = NULL;
  93. SListPrint(n1);
  94. SLNode** pphead = &n1;
  95. SListPopFront(pphead);
  96. SListPopFront(pphead);
  97. SListPopFront(pphead);
  98. SListPopFront(pphead);
  99. SListPopFront(pphead);
  100. SListPrint(n1);
  101. }
  102. void Test5()
  103. {
  104. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  105. assert(n1);
  106. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  107. assert(n2);
  108. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  109. assert(n3);
  110. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  111. assert(n4);
  112. n1->data = 1;
  113. n2->data = 2;
  114. n3->data = 3;
  115. n4->data = 4;
  116. n1->next = n2;
  117. n2->next = n3;
  118. n3->next = n4;
  119. n4->next = NULL;
  120. SListPrint(n1);
  121. SLNode** pphead = &n1;
  122. SListPopBack(pphead);
  123. SListPrint(n1);
  124. SListPopBack(pphead);
  125. SListPrint(n1);
  126. SListPopBack(pphead);
  127. SListPrint(n1);
  128. SListPopBack(pphead);
  129. SListPrint(n1);
  130. }
  131. void Test6()
  132. {
  133. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  134. assert(n1);
  135. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  136. assert(n2);
  137. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  138. assert(n3);
  139. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  140. assert(n4);
  141. n1->data = 1;
  142. n2->data = 2;
  143. n3->data = 3;
  144. n4->data = 4;
  145. n1->next = n2;
  146. n2->next = n3;
  147. n3->next = n4;
  148. n4->next = NULL;
  149. SListPrint(n1);
  150. SLNode* phead = n1;
  151. int x = 0;
  152. int y = 0;
  153. printf("请输入要修改的值和修改之后的值:> ");
  154. scanf("%d %d", &x, &y);
  155. SListModify(phead, x, y);
  156. SListPrint(n1);
  157. }
  158. void Test7()
  159. {
  160. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  161. assert(n1);
  162. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  163. assert(n2);
  164. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  165. assert(n3);
  166. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  167. assert(n4);
  168. n1->data = 1;
  169. n2->data = 2;
  170. n3->data = 3;
  171. n4->data = 4;
  172. n1->next = n2;
  173. n2->next = n3;
  174. n3->next = n4;
  175. n4->next = NULL;
  176. SListPrint(n1);
  177. SLNode* phead = n1;
  178. SLNode** pphead = &n1;
  179. int x = 0;
  180. int y = 0;
  181. printf("输入指定的插入位置与要插入的数字(在该位置之前插入):> ");
  182. scanf("%d %d", &x, &y);
  183. SLNode* pos = SListFind(phead, x);
  184. SListInsert(pphead, pos, y);
  185. SListPrint(n1);
  186. }
  187. void Test8()
  188. {
  189. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  190. assert(n1);
  191. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  192. assert(n2);
  193. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  194. assert(n3);
  195. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  196. assert(n4);
  197. n1->data = 1;
  198. n2->data = 2;
  199. n3->data = 3;
  200. n4->data = 4;
  201. n1->next = n2;
  202. n2->next = n3;
  203. n3->next = n4;
  204. n4->next = NULL;
  205. SListPrint(n1);
  206. SLNode* phead = n1;
  207. SLNode** pphead = &n1;
  208. int x = 0;
  209. int y = 0;
  210. printf("输入指定的插入位置与要插入的数字(在该位置之后插入):> ");
  211. scanf("%d %d", &x, &y);
  212. SLNode* pos = SListFind(phead, x);
  213. SListInsertAfter(pos, y);
  214. SListPrint(n1);
  215. }
  216. void Test9()
  217. {
  218. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  219. assert(n1);
  220. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  221. assert(n2);
  222. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  223. assert(n3);
  224. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  225. assert(n4);
  226. n1->data = 1;
  227. n2->data = 2;
  228. n3->data = 3;
  229. n4->data = 4;
  230. n1->next = n2;
  231. n2->next = n3;
  232. n3->next = n4;
  233. n4->next = NULL;
  234. SListPrint(n1);
  235. SLNode* phead = n1;
  236. SLNode** pphead = &n1;
  237. int x = 0;
  238. printf("输入要删除的数字:> ");
  239. scanf("%d", &x);
  240. SLNode* pos = SListFind(phead, x);
  241. SListErase(pphead, pos);
  242. SListPrint(n1);
  243. }
  244. void Test10()
  245. {
  246. SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
  247. assert(n1);
  248. SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
  249. assert(n2);
  250. SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
  251. assert(n3);
  252. SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
  253. assert(n4);
  254. n1->data = 1;
  255. n2->data = 2;
  256. n3->data = 3;
  257. n4->data = 4;
  258. n1->next = n2;
  259. n2->next = n3;
  260. n3->next = n4;
  261. n4->next = NULL;
  262. SListPrint(n1);
  263. SLNode* phead = n1;
  264. SLNode** pphead = &n1;
  265. int x = 0;
  266. printf("输入所删除数字的前一个数字:> ");
  267. scanf("%d", &x);
  268. SLNode* pos = SListFind(phead, x);
  269. SListEraseAfter(pos);
  270. SListPrint(n1);
  271. }
  272. int main()
  273. {
  274. //Test1();
  275. //Test2();
  276. //Test3();
  277. //Test4();
  278. //Test5();
  279. //Test6();
  280. //Test7();
  281. //Test8();
  282. //Test9();
  283. Test10();
  284. return 0;
  285. }

运行结果

带头双向循环链表的实现

代码实现

DList.h :功能与类型的声明

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<stdbool.h>
  5. #include<assert.h>
  6. typedef int LTDataType;
  7. typedef struct ListNode
  8. {
  9. struct ListNode* next; // 后继指针
  10. struct ListNode* prev; // 前驱指针
  11. LTDataType data;
  12. }LTNode;
  13. LTNode* ListInit(); // 初始化
  14. void ListPrint(LTNode* phead); // 打印
  15. void ListPushBack(LTNode* phead, LTDataType x); // 尾插
  16. void ListPushFront(LTNode* phead, LTDataType x); // 头插
  17. void ListPopBack(LTNode* phead); // 尾删
  18. void ListPopFront(LTNode* phead); // 头删
  19. bool ListEmpty(LTNode* phead); // 判断链表是否为空
  20. LTNode* ListFind(LTNode* phead, LTDataType x); // 查找
  21. void ListInsert(LTNode* pos, LTDataType x); // 在pos位置之前插入
  22. void ListErase(LTNode* pos); // 删除pos位置的节点
  23. int ListSize(LTNode* phead); // 统计链表有效节点的个数
  24. void ListDestory(LTNode* phead); // 销毁链表

DList.c :  功能实现

  1. #include "DList.h"
  2. LTNode* CreateListNode(LTDataType x)
  3. {
  4. LTNode* node = (LTNode*)malloc(sizeof(LTNode));
  5. if (node == NULL)
  6. {
  7. perror("CreateListNode:: malloc");
  8. exit(-1);
  9. }
  10. node->data = x;
  11. node->next = NULL;
  12. node->prev = NULL;
  13. return node;
  14. }
  15. // 初始化链表
  16. LTNode* ListInit()
  17. {
  18. LTNode* phead = CreateListNode(-1);
  19. phead->next = phead;
  20. phead->prev = phead;
  21. return phead;
  22. }
  23. // 打印
  24. void ListPrint(LTNode* phead)
  25. {
  26. assert(phead);
  27. LTNode* cur = phead->next;
  28. while (cur != phead)
  29. {
  30. printf("%d ", cur->data);
  31. cur = cur->next;
  32. }
  33. printf("\n");
  34. }
  35. // 尾插
  36. void ListPushBack(LTNode* phead, LTDataType x)
  37. {
  38. assert(phead);
  39. /*LTNode* newnode = CreateListNode(x);
  40. LTNode* tail = phead->prev;
  41. tail->next = newnode;
  42. newnode->prev = tail;
  43. phead->prev = newnode;
  44. newnode->next = phead;*/
  45. ListInsert(phead, x);
  46. }
  47. // 头插
  48. void ListPushFront(LTNode* phead, LTDataType x)
  49. {
  50. assert(phead);
  51. /*LTNode* newnode = CreateListNode(x);
  52. phead->next->prev = newnode;
  53. newnode->next = phead->next;
  54. newnode->prev = phead;
  55. phead->next = newnode;*/
  56. ListInsert(phead->next, x);
  57. }
  58. // 判断链表是否为空
  59. bool ListEmpty(LTNode* phead)
  60. {
  61. assert(phead);
  62. return phead->next == phead;
  63. }
  64. // 尾删
  65. void ListPopBack(LTNode* phead)
  66. {
  67. assert(phead);
  68. assert(phead->prev != phead);
  69. //LTNode* newtail = phead->prev->prev;
  70. //LTNode* tail = phead->prev;
  71. //free(tail);
  72. //phead->prev = newtail;
  73. //newtail->next = phead;
  74. ListErase(phead->prev);
  75. }
  76. // 头删
  77. void ListPopFront(LTNode* phead)
  78. {
  79. assert(phead);
  80. assert(phead->prev != phead);
  81. /*LTNode* next = phead->next->next;
  82. phead->next = next;
  83. next->prev = phead;*/
  84. ListErase(phead->next);
  85. }
  86. // 查找
  87. LTNode* ListFind(LTNode* phead, LTDataType x)
  88. {
  89. assert(phead);
  90. LTNode* cur = phead->next;
  91. while (cur != phead)
  92. {
  93. if (cur->data == x)
  94. return cur;
  95. cur = cur->next;
  96. }
  97. return NULL;
  98. }
  99. // 在pos位置之前插入
  100. void ListInsert(LTNode* pos, LTDataType x)
  101. {
  102. LTNode* newnode = CreateListNode(x);
  103. LTNode* prev = pos->prev;
  104. prev->next = newnode;
  105. newnode->prev = prev;
  106. newnode->next = pos;
  107. pos->prev = newnode;
  108. }
  109. // 删除pos位置的节点
  110. void ListErase(LTNode* pos)
  111. {
  112. LTNode* prev = pos->prev;
  113. LTNode* next = pos->next;
  114. prev->next = next;
  115. next->prev = prev;
  116. free(pos);
  117. }
  118. // 统计链表有效节点的个数
  119. int ListSize(LTNode* phead)
  120. {
  121. assert(phead);
  122. LTNode* cur = phead->next;
  123. int size = 0;
  124. while (cur != phead)
  125. {
  126. ++size;
  127. cur = cur->next;
  128. }
  129. return size;
  130. }
  131. // 销毁链表
  132. void ListDestory(LTNode* phead)
  133. {
  134. assert(phead);
  135. LTNode* cur = phead->next;
  136. while (cur != phead)
  137. {
  138. LTNode* next = cur->next;
  139. ListErase(cur);
  140. cur = next;
  141. }
  142. free(phead);
  143. }

New.c : 功能测试

  1. #include "DList.h"
  2. void Test1()
  3. {
  4. LTNode* plist = ListInit();
  5. ListPushBack(plist, 1);
  6. ListPushBack(plist, 2);
  7. ListPushBack(plist, 3);
  8. ListPushBack(plist, 4);
  9. ListPrint(plist);
  10. ListPushBack(plist, 5);
  11. ListPrint(plist);
  12. }
  13. void Test2()
  14. {
  15. LTNode* plist = ListInit();
  16. ListPushBack(plist, 1);
  17. ListPushBack(plist, 2);
  18. ListPushBack(plist, 3);
  19. ListPushBack(plist, 4);
  20. ListPrint(plist);
  21. ListPushFront(plist, 0);
  22. ListPushFront(plist, -1);
  23. ListPushFront(plist, -2);
  24. ListPushFront(plist, -3);
  25. ListPushFront(plist, -4);
  26. ListPrint(plist);
  27. }
  28. void Test3()
  29. {
  30. LTNode* plist = ListInit();
  31. ListPushBack(plist, 1);
  32. ListPushBack(plist, 2);
  33. ListPushBack(plist, 3);
  34. ListPushBack(plist, 4);
  35. ListPrint(plist);
  36. ListPushFront(plist, 0);
  37. ListPushFront(plist, -1);
  38. ListPushFront(plist, -2);
  39. ListPushFront(plist, -3);
  40. ListPushFront(plist, -4);
  41. ListPrint(plist);
  42. ListPopBack(plist);
  43. ListPopBack(plist);
  44. ListPopBack(plist);
  45. ListPopBack(plist);
  46. ListPrint(plist);
  47. }
  48. void Test4()
  49. {
  50. LTNode* plist = ListInit();
  51. ListPushBack(plist, 1);
  52. ListPushBack(plist, 2);
  53. ListPushBack(plist, 3);
  54. ListPushBack(plist, 4);
  55. ListPrint(plist);
  56. ListPushBack(plist, 3);
  57. ListPushBack(plist, 2);
  58. ListPushBack(plist, 1);
  59. ListPrint(plist);
  60. ListPopFront(plist);
  61. ListPopFront(plist);
  62. ListPopFront(plist);
  63. ListPrint(plist);
  64. }
  65. void Test5()
  66. {
  67. LTNode* plist = ListInit();
  68. ListPushBack(plist, 1);
  69. ListPushBack(plist, 2);
  70. ListPushBack(plist, 3);
  71. ListPushBack(plist, 4);
  72. ListPrint(plist);
  73. int x = 0;
  74. int y = 0;
  75. printf("请输入要插入的位置与要插入的数字(在该节点之前插入):> ");
  76. scanf("%d %d", &x, &y);
  77. LTNode* pos = ListFind(plist, x);
  78. if (pos != NULL)
  79. {
  80. ListInsert(pos, y);
  81. }
  82. else
  83. {
  84. printf("输入不合法\n");
  85. }
  86. ListPrint(plist);
  87. }
  88. void Test6()
  89. {
  90. LTNode* plist = ListInit();
  91. ListPushBack(plist, 1);
  92. ListPushBack(plist, 2);
  93. ListPushBack(plist, 3);
  94. ListPushBack(plist, 4);
  95. ListPrint(plist);
  96. int x = 0;
  97. printf("请输入要插入的位置:> ");
  98. scanf("%d", &x);
  99. LTNode* pos = ListFind(plist, x);
  100. if (pos != NULL)
  101. {
  102. ListErase(pos);
  103. }
  104. else
  105. {
  106. printf("输入不合法\n");
  107. }
  108. ListPrint(plist);
  109. }
  110. void Test7()
  111. {
  112. LTNode* plist = ListInit();
  113. ListPushFront(plist, 5);
  114. ListPushFront(plist, 4);
  115. ListPushFront(plist, 3);
  116. ListPushFront(plist, 2);
  117. ListPushFront(plist, 1);
  118. ListPrint(plist);
  119. ListPushBack(plist, 4);
  120. ListPushBack(plist, 3);
  121. ListPushBack(plist, 2);
  122. ListPushBack(plist, 1);
  123. ListPrint(plist);
  124. ListPopBack(plist);
  125. ListPrint(plist);
  126. ListPopFront(plist);
  127. ListPrint(plist);
  128. }
  129. int main()
  130. {
  131. //Test1();
  132. //Test2();
  133. //Test3();
  134. //Test4();
  135. //Test5();
  136. //Test6();
  137. Test7();
  138. return 0;
  139. }

运行结果

5. 栈

5.1 栈的定义

什么是栈?(What)

栈:只允许在固定的一端进行插入删除元素操作的线性结构  (Last  In  Frist  Out

栈顶:进行数据插入删除操作的一端

常见栈:

  • 数组栈  (更优)
  • 链表栈

5.2 栈的实现

使用支持动态增长循序表实现的栈

代码实现

Stack.h : 功能与类型的声明

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<assert.h>
  5. #include<stdbool.h>
  6. #define __DEBUG__ 0
  7. // 静态栈的定义
  8. #if __DEBUG__
  9. typedef int STDataType;
  10. #define N 10
  11. struct Stack
  12. {
  13. STDataType a[N];
  14. int top; // 栈顶
  15. };
  16. #endif
  17. // 支持动态增长的栈
  18. typedef int STDataType;
  19. typedef struct Stack
  20. {
  21. STDataType* a;
  22. int top; // 栈顶
  23. int capacity; // 容量
  24. }Stack;
  25. void StackInit(Stack* ps); // 初始化栈
  26. void StackPush(Stack* ps, STDataType x); // 入栈
  27. void StackPop(Stack* ps); // 出栈
  28. STDataType StackTop(Stack* ps); // 取栈顶的元素
  29. int StackSize(Stack* ps); // 获取栈中有效元素的个数
  30. bool StackEmpty(Stack* ps); // 检测栈是否为空
  31. void StackDestory(Stack* ps); // 销毁栈

Stack.c : 功能实现

  1. #include "Stack.h"
  2. // 初始化栈
  3. void StackInit(Stack* ps)
  4. {
  5. assert(ps);
  6. ps->a = NULL;
  7. ps->capacity = ps->top = 0; // 栈顶的位置无数据
  8. }
  9. // 检测栈是否为空
  10. bool StackEmpty(Stack* ps)
  11. {
  12. assert(ps);
  13. return ps->top == 0;
  14. }
  15. // 入栈
  16. void StackPush(Stack* ps,STDataType x)
  17. {
  18. assert(ps);
  19. // 检查是否需要扩容
  20. if (ps->top == ps->capacity)
  21. {
  22. int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
  23. STDataType* new = (STDataType*)realloc(ps->a, sizeof(STDataType) * newCapacity);
  24. if (new == NULL)
  25. {
  26. perror("StackPush::realloc\n");
  27. exit(-1);
  28. }
  29. ps->a = new;
  30. ps->capacity = newCapacity;
  31. }
  32. ps->a[ps->top] = x;
  33. ps->top++;
  34. }
  35. // 出栈
  36. void StackPop(Stack* ps)
  37. {
  38. assert(ps);
  39. assert(!StackEmpty(ps));
  40. ps->top--;
  41. }
  42. // 取栈顶的元素
  43. STDataType StackTop(Stack* ps)
  44. {
  45. assert(ps);
  46. assert(!StackEmpty(ps));
  47. return ps->a[ps->top - 1];
  48. }
  49. // 获取栈中有效元素的个数
  50. int StackSize(Stack* ps)
  51. {
  52. assert(ps);
  53. return ps->top;
  54. }
  55. // 销毁栈
  56. void StackDestory(Stack* ps)
  57. {
  58. assert(ps);
  59. free(ps->a);
  60. ps->top = ps->capacity = 0;
  61. }

New.c : 功能测试

  1. #include "Stack.h"
  2. void Test1()
  3. {
  4. Stack s;
  5. Stack* ps = &s;
  6. StackInit(ps);
  7. StackPush(ps, 1);
  8. StackPush(ps, 2);
  9. StackPush(ps, 3);
  10. StackPush(ps, 4);
  11. StackPush(ps, 5);
  12. int size = 0;
  13. size = StackSize(ps);
  14. printf("%d:\n", size);
  15. while (!StackEmpty(ps))
  16. {
  17. int ret = StackTop(ps);
  18. printf("%d ", ret);
  19. StackPop(ps);
  20. }
  21. printf("\n");
  22. StackDestory(ps);
  23. }
  24. int main()
  25. {
  26. Test1();
  27. return 0;
  28. }

运行结果

6. 队列

6.1 队列的定义

什么是队列?(What)

队列:只允许在一端插入数据,而在另一端删除数据的线性结构  (Frist  In  Frist  Out)

队头:删除数据的一端

队尾:插入数据的一端

常见队列:

  • 数组队列 
  • 链表队列  (更优)

6.2 队列的实现

使用单链表实现的队列

代码实现

Queue.h : 功能与类型的声明

  1. #pragma once
  2. #include<stdio.h>
  3. #include<stdlib.h>
  4. #include<stdbool.h>
  5. #include<assert.h>
  6. typedef int QDataType;
  7. // 使用单链表实现队列
  8. typedef struct QueueNode
  9. {
  10. struct QueueNode* next;
  11. QDataType data;
  12. }QNode;
  13. typedef struct Queue
  14. {
  15. QNode* head; // 队头
  16. QNode* tail; // 队尾
  17. }Queue;
  18. void QueueInit(Queue* pq); // 初始化
  19. void QueueDestory(Queue* pq); // 销毁队列
  20. void QueuePush(Queue* pq, QDataType x); // 入队列
  21. void QueuePop(Queue* pq); // 出队列
  22. QDataType QueueFront(Queue* pq); // 取队头的元素
  23. QDataType QueueBack(Queue* pq); // 取队尾的元素
  24. bool QueueEmpty(Queue* pq); // 判断队列是否为空
  25. int QueueSize(Queue* pq); // 计算队列中的有效元素

Queue.c : 功能实现

  1. #include "Queue.h"
  2. // 初始化
  3. void QueueInit(Queue* pq)
  4. {
  5. assert(pq);
  6. pq->head = pq->tail = NULL;
  7. }
  8. // 入队列
  9. void QueuePush(Queue* pq, QDataType x)
  10. {
  11. assert(pq);
  12. QNode* newnode = (QNode*)malloc(sizeof(QNode));
  13. if (newnode == NULL)
  14. {
  15. perror("QueuePush::malloc\n");
  16. exit(-1);
  17. }
  18. newnode->data = x;
  19. newnode->next = NULL;
  20. if (pq->tail == NULL)
  21. {
  22. pq->head = pq->tail = newnode;
  23. }
  24. else
  25. {
  26. pq->tail->next = newnode;
  27. pq->tail = newnode;
  28. }
  29. }
  30. // 出队列
  31. void QueuePop(Queue* pq)
  32. {
  33. assert(pq);
  34. // 只剩一个节点
  35. if (pq->head->next == NULL)
  36. {
  37. free(pq->head);
  38. pq->head = pq->tail = NULL; // 避免tail成为野指针 (指针的指向是不确定的)
  39. }
  40. else
  41. {
  42. // 多个节点
  43. QNode* next = pq->head->next;
  44. free(pq->head);
  45. pq->head = next;
  46. }
  47. }
  48. // 取队头的元素
  49. QDataType QueueFront(Queue* pq)
  50. {
  51. assert(pq);
  52. assert(!QueueEmpty(pq));
  53. return pq->head->data;
  54. }
  55. // 取队尾的元素
  56. QDataType QueueBack(Queue* pq)
  57. {
  58. assert(pq);
  59. assert(!QueueEmpty(pq));
  60. return pq->tail->data;
  61. }
  62. // 判断队列是否为空
  63. bool QueueEmpty(Queue* pq)
  64. {
  65. assert(pq);
  66. //if (pq->head == NULL)
  67. // return true;
  68. //return false;
  69. return pq->head == NULL;
  70. }
  71. // 计算队列中的有效元素
  72. int QueueSize(Queue* pq)
  73. {
  74. assert(pq);
  75. QNode* cur = pq->head;
  76. int size = 0;
  77. while (cur)
  78. {
  79. ++size;
  80. cur = cur->next;
  81. }
  82. return size;
  83. }
  84. // 销毁队列 - 即将队列都删空
  85. void QueueDestory(Queue* pq)
  86. {
  87. assert(pq);
  88. QNode* cur = pq->head;
  89. while (cur)
  90. {
  91. QNode* next = cur->next;
  92. free(cur);
  93. cur = next;
  94. }
  95. pq->head = pq->tail = NULL;
  96. }

New.c : 功能测试

  1. #include "Queue.h"
  2. void Test1()
  3. {
  4. Queue q;
  5. Queue* pq = &q;
  6. QueueInit(pq);
  7. QueuePush(pq, 1);
  8. QueuePush(pq, 2);
  9. QueuePush(pq, 3);
  10. QueuePush(pq, 4);
  11. QueuePush(pq, 5);
  12. int size = 0;
  13. size = QueueSize(pq);
  14. printf("%d:\n", size);
  15. while (!QueueEmpty(pq))
  16. {
  17. int ret = QueueFront(pq);
  18. printf("%d ", ret);
  19. QueuePop(pq);
  20. }
  21. printf("\n");
  22. QueueDestory(pq);
  23. }
  24. int main()
  25. {
  26. Test1();
  27. return 0;
  28. }

运行结果

 7. 小结

最后,我们来进行总结一下,今天的博客主要介绍了数据结构中的线性结构及它们的实现(C语言),如顺序表、链表、栈、队列;熟练掌握各种数据结构以及它们的实现,我们软件开发者在进阶过程中必须要攀登的一座“大山”!好啦,希望今天的博客能够对你有所帮助,我们山顶见!

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

闽ICP备14008679号