• 数据结构之顺序表


    顺序表就是数组,但是在数组的基础上,它要求数据是从头开始并且连续存储的,不能间隔存储

    静态顺序表

    静态顺序表中如果数据满了则不让继续存储,因此我们无法确定该给它多少内存

    其头文件:

    1. #pragma once
    2. #define N 1000
    3. typedef int SLDataType
    4. //静态顺序表
    5. typedef struct SeqList
    6. {
    7. SLDataType a[N];
    8. int size;//表示数组中存储了多少个数据
    9. }SL;
    10. //接口函数
    11. void SeqListInit(SL* ps);
    12. void SeqListPushBack(SL* ps,SLDataType x);
    13. void SeqListPopBack(SL* ps);
    14. void SeqListPushFront(SL* ps,SLDataType x);
    15. void SeqListPopFront(SL* ps);

    动态顺序表

    动态顺序表:

    1. typedef int SLDataType;
    2. //动态顺序表
    3. typedef struct SeqList
    4. {
    5. SLDataType* a;
    6. int size;//表示数组中存储了多少个数据
    7. int capacity;//表示数组时间能存储多少个数据
    8. }SL;

    各接口函数实现

    顺序表初始化:

    1. void SeqListInit(SL *ps)//顺序表初始化
    2. {
    3. ps->a = NULL;
    4. ps->size = ps->capacity = 0;
    5. }

    顺序表销毁:

    1. void SeqListDestory(SL* ps)
    2. {
    3. free(ps->a);
    4. ps->a = NULL;
    5. ps->capacity = ps->size = 0;
    6. }

    顺序表检查内存空间是否足够:

    1. void SeqListCheckCapacity(SL* ps)//检查内存空间是否足够
    2. {
    3. if (ps->size == ps->capacity)//没有空间或者空间不足的情况下
    4. {
    5. int newcapacity = ps->capacity = 0 ? 4 : ps->capacity * 2;
    6. SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));//没有空间则申请内存空间,有则进行扩容
    7. if (tmp == NULL)
    8. {
    9. printf("realloc fail \n");
    10. exit(-1);
    11. }
    12. ps->a = tmp;
    13. ps->capacity = newcapacity;
    14. }
    15. }

    顺序表尾插:

    尾插时需考虑三种情况:

    1. 整个顺序表没有空间
    2. 空间不够,需要扩容
    3. 空间足够,直接插入数据
    1. void SeqListPushBack(SL* ps, SLDataType x)//顺序表尾插
    2. {
    3. SeqListCheckCapacity(ps);
    4. ps->a[ps->size] = x;
    5. ps->size++;
    6. }

    顺序表尾插:

    1. void SeqListPopBack(SL* ps)//数据表尾删
    2. {
    3. if(ps->size > 0)
    4. {
    5. ps->size--;
    6. }
    7. }

    顺序表头插:

    1. void SeqListPushFront(SL* ps, SLDataType x)//顺序表头插
    2. {
    3. SeqListCheckCapacity(ps);
    4. int end = ps->size - 1;
    5. while(end >= 0)//数据向后挪动
    6. {
    7. ps->a[end+1] = ps->a[end];
    8. --end;
    9. }
    10. ps->a[0] = x;
    11. ps->size++;
    12. }

    顺序表头删:

    1. void SeqListPopFront(SL* ps)
    2. {
    3. assert(ps->size > 0);//存储数据不能为零,否则会终止
    4. int begin = 1;
    5. while(begin < ps->size)//数据向前挪动
    6. {
    7. ps->a[begin-1] = ps->a[begin];
    8. begin++;
    9. }
    10. ps->size--;
    11. }

    使用assert方法时需导入assert库

    顺序表中查找数据位置(找到了返回数据位置下标,没有找到则返回-1):

    1. int SeqListFind(SL* ps,SLDataType x)
    2. {
    3. for(int i = 0;i < ps->size;i++)
    4. {
    5. if(ps->a[i] == x)
    6. {
    7. return i;
    8. }
    9. }
    10. return -1;
    11. }

    顺序表指定位置插入:

    1. void SeqListInsert(SL* ps,int pos,SLDataType x)
    2. {
    3. if(pos > ps->size || pos < 0)
    4. {
    5. printf("pos invalid \n")
    6. return ;
    7. }
    8. //assert(pos <= ps->size && pos => 0)//暴力方法不得输入非法pos
    9. SeqListCheckCapcaity(ps);
    10. int end = ps->size-1;
    11. while(end >= pos)
    12. {
    13. ps->a[end+1] = ps->a[end];
    14. end--;
    15. }
    16. ps->a[pos] = x;
    17. ps->size++;
    18. }

    顺序表指定位置删除:

    1. void SeqListErase(SL* ps,int pos)
    2. {
    3. if(pos > ps->size || pos < 0)
    4. {
    5. printf("pos invalid \n")
    6. return ;
    7. }
    8. int begin = pos + 1;
    9. while(begin < ps->size)
    10. {
    11. ps->a[begin-1] = ps->a[begin];
    12. begin++;
    13. }
    14. ps->size--;
    15. }

    通过顺序表的指定位置删除我们可以改善顺序表的头删

    动态顺序表(完整版)

    头文件:

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. typedef int SLDataType;
    6. //动态顺序表
    7. typedef struct SeqList
    8. {
    9. SLDataType* a;
    10. int size;//表示数组中存储了多少个数据
    11. int capacity;//表示数组时间能存储多少个数据
    12. }SL;
    13. //接口函数
    14. void SeqListInit(SL* ps);
    15. void SeqListDestory(SL* ps);
    16. void SeqListPrint(SL* ps);
    17. void SeqListPushBack(SL* ps, SLDataType x);
    18. void SeqListPopBack(SL* ps);
    19. void SeqListPushFront(SL* ps, SLDataType x);
    20. void SeqListPopFront(SL* ps);
    21. void SeqListCheckCapcaity(SL* ps);
    22. int SeqListFind(SL* ps,SLDataType x);
    23. void SeqListInsert(SL* ps,int pos,SLDataType x);
    24. void SeqListErase(SL* ps,int pos);

    接口函数以及结构体的.c文件:

    1. #include "SeqList.h"
    2. void SeqListInit(SL* ps)//顺序表初始化
    3. {
    4. ps->a = NULL;
    5. ps->size = ps->capacity = 0;
    6. }
    7. void SeqListDestory(SL* ps)
    8. {
    9. free(ps->a);
    10. ps->a = NULL;
    11. ps->capacity = ps->size = 0;
    12. }
    13. void SeqListPrint(SL* ps)//顺序表销毁
    14. {
    15. for(int i = 0; i < ps->size; i++)
    16. {
    17. printf("%d ", ps->a[i]);
    18. }
    19. printf("\n");
    20. }
    21. void SeqListCheckCapacity(SL* ps)//检查内存空间是否足够
    22. {
    23. if (ps->size == ps->capacity)//没有空间或者空间不足的情况下
    24. {
    25. int newcapacity = ps->capacity = 0 ? 4 : ps->capacity * 2;
    26. SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));//没有空间则申请内存空间,有则进行扩容
    27. if (tmp == NULL)
    28. {
    29. printf("realloc fail \n");
    30. exit(-1);
    31. }
    32. ps->a = tmp;
    33. ps->capacity = newcapacity;
    34. }
    35. }
    36. void SeqListPushBack(SL* ps, SLDataType x)//顺序表尾插
    37. {
    38. SeqListCheckCapacity(ps);
    39. ps->a[ps->size] = x;
    40. ps->size++;
    41. }
    42. void SeqListPopBack(SL* ps)//数据表尾删
    43. {
    44. if(ps->size > 0)
    45. {
    46. ps->size--;
    47. }
    48. }
    49. void SeqListPushFront(SL* ps, SLDataType x)//顺序表头插
    50. {
    51. SeqListCheckCapacity(ps);
    52. int end = ps->size - 1;
    53. while(end >= 0)//数据向后挪动
    54. {
    55. ps->a[end+1] = ps->a[end];
    56. --end;
    57. }
    58. ps->a[0] = x;
    59. ps->size++;
    60. }
    61. void SeqListPopFront(SL* ps)
    62. {
    63. assert(ps->size > 0);//存储数据不能为零,否则会终止
    64. int begin = 1;
    65. while(begin < ps->size)//数据向前挪动
    66. {
    67. ps->a[begin-1] = ps->a[begin];
    68. begin++;
    69. }
    70. ps->size--;
    71. }
    72. int SeqListFind(SL* ps,SLDataType x)
    73. {
    74. for(int i = 0;i < ps->size;i++)
    75. {
    76. if(ps->a[i] == x)
    77. {
    78. return i;
    79. }
    80. }
    81. return -1;
    82. }
    83. void SeqListInsert(SL* ps,int pos,SLDataType x)
    84. {
    85. if(pos > ps->size || pos < 0)
    86. {
    87. printf("pos invalid \n");
    88. return ;
    89. }
    90. //assert(pos <= ps->size && pos => 0)//暴力方法不得输入非法pos
    91. SeqListCheckCapacity(ps);
    92. int end = ps->size-1;
    93. while(end >= pos)
    94. {
    95. ps->a[end+1] = ps->a[end];
    96. end--;
    97. }
    98. ps->a[pos] = x;
    99. ps->size++;
    100. }
    101. void SeqListErase(SL* ps,int pos)
    102. {
    103. if(pos > ps->size || pos < 0)
    104. {
    105. printf("pos invalid \n");
    106. return ;
    107. }
    108. int begin = pos + 1;
    109. while(begin < ps->size)
    110. {
    111. ps->a[begin-1] = ps->a[begin];
    112. begin++;
    113. }
    114. ps->size--;
    115. }

    测试顺序表的.c文件:

    1. #include "SeqList.h"
    2. void TestSeqList1() {
    3. SL s1;
    4. SeqListInit(&s1);
    5. SeqListPushBack(&s1, 1);
    6. SeqListPushBack(&s1, 2);
    7. SeqListPushBack(&s1, 3);
    8. SeqListPopBack(&s1);
    9. SeqListPopBack(&s1);
    10. SeqListPrint(&s1);
    11. SeqListDestory(&s1);
    12. }
    13. void TestSeqList2()
    14. {
    15. SL s1;
    16. SeqListInit(&s1);
    17. SeqListPushBack(&s1,1);
    18. SeqListPushBack(&s1,2);
    19. SeqListPushBack(&s1,3);
    20. SeqListPushBack(&s1,4);
    21. SeqListPushBack(&s1,5);
    22. SeqListPushFront(&s1,10);
    23. SeqListPushFront(&s1,20);
    24. SeqListPushFront(&s1,30);
    25. SeqListPushFront(&s1,40);
    26. SeqListPushFront(&s1,50);
    27. SeqListPushFront(&s1,60);
    28. SeqListPushFront(&s1,70);
    29. SeqListPopFront(&s1);
    30. SeqListPopFront(&s1);
    31. SeqListPopFront(&s1);
    32. SeqListPopFront(&s1);
    33. SeqListPrint(&s1);
    34. SeqListDestory(&s1);
    35. }
    36. void TestSeqList3()
    37. {
    38. SL s1;
    39. SeqListInit(&s1);
    40. SeqListPushBack(&s1,1);
    41. SeqListPushBack(&s1,2);
    42. SeqListPushBack(&s1,3);
    43. SeqListPushBack(&s1,4);
    44. SeqListPushBack(&s1,5);
    45. SeqListInsert(&s1,1,10);
    46. SeqListInsert(&s1,2,200);
    47. SeqListErase(&s1,5);
    48. SeqListErase(&s1,2);
    49. SeqListPrint(&s1);
    50. int pos = SeqListFind(&s1,5);
    51. printf("%d",pos);
    52. SeqListDestory(&s1);
    53. }
    54. int main() {
    55. TestSeqList1();
    56. TestSeqList2();
    57. TestSeqList3();
    58. return 0;
    59. }

    顺序表缺点:

    1. 空间不够时需要扩容,而扩容需要付出代价。扩容时当内存后面有足够空间时会原地扩容,没有足够空间时会重新找一块内存申请空间
    2. 为了避免频繁扩容,当内存空间满了时,基本都是扩容两倍,这就可能导致内存一定空间的浪费
    3. 顺序表要求从头开始连续存储数据,因此我们在头部或中间插入删除数据时就需要挪动数据,效率不高

    顺序表优点:

    1. 存储密度大
    2. 可随机存取某一元素

  • 相关阅读:
    spark深度剖析
    计算机毕业设计Python+Django的毕业设计过程管理系统(源码+系统+mysql数据库+Lw文档)
    深度学习遇到内存溢出的情况
    广州搬砖第三年,从一枚小菜鸡到架构师
    wsl2迁移镜像虚拟磁盘
    [DevOps云实践] 彻底删除AWS云资源
    Redis高可用方案之主从复制
    IO 模型的演变
    git实现服务器自动push拉取代码--webhooks
    DSGC:双空间图对比学习
  • 原文地址:https://blog.csdn.net/Thewei666/article/details/127588064