认识线性表

定义

零个或多个数据元素的有限序列

特点

  • 它是一个序列,数据之间是有序的,数据元素是一对一的关系。
  • 线性表的数据元素个数是有限的。

常见操作

  • 创建和初始化队列
  • 查找
  • 插入
  • 删除
  • 清空

线性表的抽象数据类型

image.png

线性表的顺序存储结构

定义

线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。

优点

  • 无须为表示表中元素之间的逻辑而增加额外的存储空间。
  • 可以快速地存取任意位置的元素

缺点

  • 插入删除操作需要移动大量的元素
  • 当线性表长度变化较大时,难以确定元素存储空间的内容
  • 造成空间的“碎片”

代码实现

  1. // DataElement.h
  2. #ifndef INC_01_DATAELEMENT_H
  3. #define INC_01_DATAELEMENT_H
  4. #define MAX_SIZE 255
  5. // 定义数据元素
  6. typedef struct {
  7. int id;
  8. char * name;
  9. } ElementType;
  10. // 定义顺序表结构
  11. typedef struct {
  12. ElementType datas[MAX_SIZE]; // 顺序表中的数据集合
  13. int length; // 当前顺序表中的元素个数
  14. } SeqList;
  15. #endif
  1. // SequenceList.h
  2. #ifndef INC_01_SEQUENCELIST_H
  3. #define INC_01_SEQUENCELIST_H
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include "DataElement.h"
  7. /**
  8. * 初始化顺序表
  9. * @param seqList 需要初始化的顺序表指针
  10. * @param elemArray 初始化时要添加的元素内容
  11. * @param length 初始化时添加的元素个数
  12. */
  13. void InitList(SeqList * seqList, ElementType * elemArray, int length);
  14. /**
  15. * 向顺序表中插入某个元素
  16. * @param seqList 需要插入元素的顺序表指针
  17. * @param index 插入的位置
  18. * @param element 插入的元素
  19. */
  20. void InsertElement(SeqList * seqList, int index, ElementType element);
  21. /**
  22. * 打印顺序表
  23. * @param seqList
  24. */
  25. void PrintList(SeqList * seqList);
  26. /**
  27. * 在顺序表中删除某个元素
  28. * @param seqList 删除元素所在的顺序表指针
  29. * @param index 删除元素的下标
  30. * @return 返回删除的元素,如果删除失败返回 NULL
  31. */
  32. ElementType * DeleteElement(SeqList * seqList, int index);
  33. /**
  34. * 在顺序表中查找某个元素
  35. * @param seqList 查找元素所在的顺序表指针
  36. * @param index 查找元素的下标
  37. * @return 返回查找元素的下标,如果查找失败返回 NULL
  38. */
  39. ElementType * GetElement(SeqList * seqList, int index);
  40. /**
  41. * 返回顺序表的长度
  42. * @param seqList 返回总长度的顺序表指针
  43. * @return 返回顺序表长度
  44. */
  45. int GetLength(SeqList * seqList);
  46. /**
  47. * 判断顺序表是否为空
  48. * @param seqList 判断是否为空的顺序表指针
  49. * @return 顺序表为空返回 1,否则返回 0
  50. */
  51. int IsEmpty(SeqList * seqList);
  52. /**
  53. * 清空顺序表
  54. * @param seqList 要清空的顺序表指针
  55. */
  56. void ClearList(SeqList * seqList);
  57. #endif
  1. // SequenceList.c
  2. #include "SequenceList.h"
  3. /**
  4. * 初始化顺序表
  5. * @param seqList 需要初始化的顺序表
  6. * @param elemArray 初始化时要添加的元素内容
  7. * @param length 初始化时添加的元素个数
  8. */
  9. void InitList(SeqList * seqList, ElementType * elemArray, int length) {
  10. if (length > MAX_SIZE) {
  11. printf("超出了数组的最大容量,初始化失败!\n");
  12. return;
  13. }
  14. seqList -> length = 0;
  15. for (int i = 0; i < length; i++) {
  16. InsertElement(seqList, i, elemArray[i]);
  17. }
  18. };
  19. /**
  20. * 向顺序表中插入某个元素
  21. * @param seqList 需要插入元素的顺序表
  22. * @param index 插入的位置
  23. * @param element 插入的元素
  24. */
  25. void InsertElement(SeqList * seqList, int index, ElementType element) {
  26. if (seqList->length + 1 >= MAX_SIZE) {
  27. printf("数组已满, 插入元素失败!\n");
  28. return;
  29. }
  30. if (index < 0 || index > MAX_SIZE -1) {
  31. printf("只能在允许的下标范围内插入元素[0, %d]!\n", MAX_SIZE - 1);
  32. return;
  33. }
  34. if (index > seqList -> length) {
  35. printf("插入的下标超过了数组的最大长度-1,插入失败!\n");
  36. return;
  37. }
  38. for (int i = seqList -> length - 1; i >= index; i--) {
  39. seqList -> datas[i + 1] = seqList -> datas[i];
  40. }
  41. // 插入元素
  42. seqList -> datas[index] = element;
  43. // 顺序表的总长度 +1
  44. seqList -> length++;
  45. };
  46. /**
  47. * 打印顺序表
  48. * @param seqList
  49. */
  50. void PrintList(SeqList * seqList) {
  51. for (int i = 0; i < seqList -> length; i++) {
  52. printf("%d\t%s\n", seqList -> datas[i].id, seqList -> datas[i].name);
  53. }
  54. };
  55. void PrintList(SeqList * seqList);
  56. /**
  57. * 在顺序表中删除某个元素 (使用完毕后必须 free!!!)
  58. * @param seqList 删除元素所在的顺序表
  59. * @param index 删除元素的下标
  60. * @return 返回删除的元素,如果删除失败返回 NULL
  61. */
  62. ElementType * DeleteElement(SeqList * seqList, int index) {
  63. if (index < 0 || index > MAX_SIZE - 1) {
  64. printf("下标越界,无法删除!");
  65. return NULL;
  66. }
  67. // 保存已删除元素的副本
  68. ElementType * delElement = (ElementType*)malloc(sizeof(ElementType));
  69. *delElement = *GetElement(seqList, index);
  70. for (int i = index; i < seqList ->length - 1 ; ++i) {
  71. seqList -> datas[i] = seqList -> datas[i+1];
  72. }
  73. seqList -> length--;
  74. return delElement;
  75. };
  76. /**
  77. * 在顺序表中查找某个元素
  78. * @param seqList 查找元素所在的顺序表
  79. * @param index 查找元素的下标
  80. * @return 返回查找元素的下标,如果查找失败返回 NULL
  81. */
  82. ElementType * GetElement(SeqList * seqList, int index) {
  83. if (index < 0 || index > MAX_SIZE) {
  84. printf("下标越界,无法找到指定元素!");
  85. return NULL;
  86. }
  87. ElementType * element; // 要查找的元素
  88. element = &seqList -> datas[index];
  89. return element;
  90. };
  91. /**
  92. * 返回顺序表的长度
  93. * @param seqList 返回总长度的顺序表指针
  94. * @return 返回顺序表长度
  95. */
  96. int GetLength(SeqList * seqList) {
  97. if (seqList == NULL) {
  98. return 0;
  99. }
  100. return seqList ->length;
  101. };
  102. /**
  103. * 判断顺序表是否为空
  104. * @param seqList 判断是否为空的顺序表指针
  105. * @return 顺序表为空返回 1,否则返回 0
  106. */
  107. int IsEmpty(SeqList * seqList) {
  108. return GetLength(seqList) == 0 ? 0 : 1;
  109. };
  110. /**
  111. * 清空顺序表
  112. * @param seqList 要清空的顺序表指针
  113. */
  114. void ClearList(SeqList * seqList) {
  115. if (seqList == NULL) {
  116. return;
  117. }
  118. seqList->length = 0;
  119. };
// main.c
#include <stdio.h>
#include <stdlib.h>
#include "SequenceList.h"

ElementType dataArray[] = {
        {1, "奇异博士"},
        {2, "美国队长"},
        {3, "太上老君"},
        {4, "齐天大圣"},
};

void TestSequenceList();

int main() {
    TestSequenceList();
    return 0;
}


void TestSequenceList() {
    SeqList seqList;  // 要操作的顺序表
    InitList(&seqList, dataArray, sizeof(dataArray) / sizeof(dataArray[0]));
    PrintList(&seqList);
};