• 数据结构--顺序表


    目录

    1.顺序表

    1.1顺序表的概念及结构

    线性表

     2、顺序表分类

    2.1顺序表和数组的区别

    静态顺序表

    动态顺序表

    3.顺序表的实现

     3.1初始化

    随后便可对顺序表初始化

    3.2插入数据

    尾插

    头插

     在指定位置插入数据

    顺序表的查找

    头删、尾删及指定位置删除

    实现代码:


    1.顺序表

    1.1顺序表的概念及结构

    线性表

    线性表( linear list )是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使⽤的数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串...
    线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
    案例:蔬菜分为绿叶类、⽠类、菌菇类。

     2、顺序表分类

    2.1顺序表和数组的区别

    顺序表的底层结构是数组,对数组的封装,实现了常⽤的增删改查等接⼝
    • 静态顺序表

    1. struct SeqList
    2. {
    3. int arr[100];//定长数组
    4. int size;//顺序表当前的数据个数
    5. };

    概念:使用定长数组存放元素

    缺陷:空间给少了不够⽤,给多了造成空间浪费

    • 动态顺序表

    1. struct SeqList
    2. {
    3. int *arr;
    4. int size;//有效的数据个数
    5. int capacity;//空间大小
    6. };

    因为数组并不是定长的,可根据实际数据大小进行动态申请空间,随着数据的增加,也可进行动态增容

    3.顺序表的实现

    分成三个文件实现:

    SeqList.h

    SeqList.c

    test.c

     3.1初始化

    首先在SeqList.h创建好顺序表的结构

    1. typedef int SLDataType;//顺序表存放的类型可能是int 也可能是char,
    2. 所有重新起个名字,方便以后更改
    3. //动态顺序表
    4. typedef struct SeqList
    5. {
    6. SLDataType* arr;
    7. int size;//有效数据个数
    8. int capacity;//空间大小
    9. }SL;

    随后便可对顺序表初始化

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

    3.2插入数据

    在插入数据之前首先要判断空间是否为0,空间是否足够,

    若不够,一次应增容多少?

    通常来说增容是成倍的增长,一般是2倍或3倍

    因此,创建一个函数SLCheckCapacity专门实现增容,每次插入数据之前需调用一次函数

    1. void SLCheckCapacity(SL* ps)
    2. {
    3. //插入数据之前先看空间够不够
    4. if (ps->capacity == ps->size)
    5. {
    6. //申请空间-->增容realloc
    7. int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
    8. //三目表达式 判断capacity是否为0 是:赋值为4 否:赋值为2 * ps->capacity
    9. //增容通常来说是成倍数的增加,一般是23
    10. SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//要申请多大的空间
    11. if (tmp == NULL)
    12. {
    13. perror("realloc fail!");
    14. exit(1);//直接退出程序,不再继续执行
    15. }
    16. //空间申请成功
    17. ps->arr = tmp;
    18. ps->capacity = newCapacity;
    19. }
    20. }

    尾插

    在数据的尾部插入数据

    1. //尾插
    2. void SLPushBack(SL* ps, SLDataType x)
    3. {
    4. //防止ps可能为NULL
    5. assert(ps);//等价于assert(ps!=NULL);
    6. SLCheckCapacity(ps);
    7. ps->arr[ps->size++] = x;
    8. }

    头插

    在数据的头部插入数据;

    插入数据之前把原有数据全部向后移动一位

    1. //头插
    2. void SLPushFront(SL* ps, SLDataType x)
    3. {
    4. assert(ps);
    5. SLCheckCapacity(ps);
    6. //先让顺序表中已有的数据整体往后挪动一位
    7. for (int i = ps->size; i > 0; i--)//数组下标不会为-1
    8. {
    9. ps->arr[i] = ps->arr[i - 1];
    10. }
    11. ps->arr[0] = x;//头插
    12. ps->size++;
    13. }

     在指定位置插入数据

    创建一个变量pos存放指定位置,然后把pos之后的数据整体往后移动一位,在pos位置插入所需要的数据即可。

    1. //在指定位置之前插入数据
    2. void SLlnsert(SL* ps, int pos, SLDataType x)//pos:指定的位置 x:插入的数据
    3. {
    4. assert(ps);
    5. assert(pos >= 0 && pos <= ps->size);
    6. //插入数据:空间够不够
    7. SLCheckCapacity(ps);
    8. //让pos及之后的数据整体往后挪动一位
    9. for (int i = ps->size; i > pos; i--)//从后往前挪动
    10. {
    11. ps->arr[i] = ps->arr[i - 1];//arr[pos+1]=arr[pos] 最后下标为pos位置为空
    12. }
    13. ps->arr[pos] = x;//在pos位置插入数据
    14. ps->size++;
    15. }

    顺序表的查找

    1. //查找
    2. int SLFind(SL* ps, SLDataType x)
    3. {
    4. assert(ps);
    5. for (int i = 0; i < ps->size; i++)
    6. {
    7. if (ps->arr[i] == x)
    8. {
    9. //找到了
    10. return i;
    11. }
    12. }
    13. //没有找到
    14. return -1;
    15. }

    头删、尾删及指定位置删除

    与插入数据原理一样,只需在所需的位置删除数据即可

    实现代码:

    SeqList.h

    1. #pragma once
    2. #include<stdio.h>
    3. #include<stdlib.h>
    4. #include<assert.h>
    5. //定义顺序表的结构
    6. //#define N 100
    7. 静态顺序表
    8. //struct SeqList
    9. //{
    10. // int arr[N];
    11. // int size;//有效数据个数
    12. //};
    13. typedef int SLDataType;//顺序表存放的类型可能是int 也可能是char,所有重新起个名字,方便以后更改
    14. //动态顺序表
    15. typedef struct SeqList
    16. {
    17. SLDataType* arr;
    18. int size;//有效数据个数
    19. int capacity;//空间大小
    20. }SL;
    21. //顺序表初始化
    22. void SLlnit(SL* ps);
    23. //顺序表的销毁
    24. void SLDestroy(SL* ps);
    25. //顺序表的打印
    26. void SLprint(SL s);
    27. //头部插入删除/尾部插入删除
    28. void SLPushBack(SL* ps, SLDataType x);
    29. void SLPushFront(SL* ps, SLDataType x);
    30. void SLPopBack(SL* ps);
    31. void SLPopFront(SL* ps);
    32. //指定位置之前插入/删除数据
    33. void SLlnsert(SL* ps,int pos,SLDataType x );
    34. void SLErase(SL* ps, int pos);
    35. //查找
    36. int SLFind(SL* ps, SLDataType x);

    SeqList.c

    1. #include"SeqList.h"
    2. void SLlnit(SL* ps)//顺序表初始化
    3. {
    4. ps->arr = NULL;
    5. ps->size = ps->capacity=0;
    6. }
    7. //顺序表的销毁
    8. void SLDestroy(SL* ps)
    9. {
    10. if (ps->arr)//等价于 if(ps->!=NULL)
    11. {
    12. free(ps-> arr);//释放空间
    13. }
    14. ps->arr = NULL;
    15. ps->size = ps->capacity = 0;
    16. }
    17. void SLCheckCapacity(SL* ps)
    18. {
    19. //插入数据之前先看空间够不够
    20. if (ps->capacity == ps->size)
    21. {
    22. //申请空间-->增容realloc
    23. int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
    24. //三目表达式 判断capacity是否为0 是:赋值为4 否:赋值为2 * ps->capacity
    25. //增容通常来说是成倍数的增加,一般是23
    26. SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));//要申请多大的空间
    27. if (tmp == NULL)
    28. {
    29. perror("realloc fail!");
    30. exit(1);//直接退出程序,不再继续执行
    31. }
    32. //空间申请成功
    33. ps->arr = tmp;
    34. ps->capacity = newCapacity;
    35. }
    36. }
    37. //尾插
    38. void SLPushBack(SL* ps, SLDataType x)
    39. {
    40. //防止ps可能为NULL
    41. assert(ps);//等价于assert(ps!=NULL);
    42. SLCheckCapacity(ps);
    43. ps->arr[ps->size++] = x;
    44. }
    45. //头插
    46. void SLPushFront(SL* ps, SLDataType x)
    47. {
    48. assert(ps);
    49. SLCheckCapacity(ps);
    50. //先让顺序表中已有的数据整体往后挪动一位
    51. for (int i = ps->size; i > 0; i--)//数组下标不会为-1
    52. {
    53. ps->arr[i] = ps->arr[i - 1];
    54. }
    55. ps->arr[0] = x;//头插
    56. ps->size++;
    57. }
    58. //打印顺序表
    59. void SLprint(SL s)
    60. {
    61. for (int i = 0; i < s.size; i++)
    62. {
    63. printf("%d ", s.arr[i]);
    64. }
    65. printf("\n");
    66. }
    67. //尾部删除
    68. void SLPopBack(SL* ps)
    69. {
    70. assert(ps);
    71. assert(ps->size);
    72. //顺序表不为空
    73. //ps->arr[ps->size - 1] = -1;
    74. --ps->size;//删除
    75. }
    76. //头删
    77. void SLPopFront(SL* ps)
    78. {
    79. assert(ps);
    80. assert(ps->size);
    81. //数据整体往前挪动一位
    82. for (int i = 0; i < ps->size - 1; i++)
    83. {
    84. ps->arr[i] = ps->arr[i + 1];
    85. }
    86. ps->size--;//删除
    87. }
    88. //在指定位置之前插入数据
    89. void SLlnsert(SL* ps, int pos, SLDataType x)//pos:指定的位置 x:插入的数据
    90. {
    91. assert(ps);
    92. assert(pos >= 0 && pos <= ps->size);
    93. //插入数据:空间够不够
    94. SLCheckCapacity(ps);
    95. //让pos及之后的数据整体往后挪动一位
    96. for (int i = ps->size; i > pos; i--)//从后往前挪动
    97. {
    98. ps->arr[i] = ps->arr[i - 1];//arr[pos+1]=arr[pos] 最后下标为pos位置为空
    99. }
    100. ps->arr[pos] = x;//在pos位置插入数据
    101. ps->size++;
    102. }
    103. //删除指定位置的数据
    104. void SLErase(SL* ps, int pos)
    105. {
    106. assert(ps);
    107. assert(pos >= 0 && pos < ps->size);
    108. for (int i = pos; i < ps->size - 1; i++)
    109. {
    110. ps->arr[i] = ps->arr[i + 1];//pos位置后的数据全部往前挪动一位
    111. }
    112. ps->size--;
    113. }
    114. //查找
    115. int SLFind(SL* ps, SLDataType x)
    116. {
    117. assert(ps);
    118. for (int i = 0; i < ps->size; i++)
    119. {
    120. if (ps->arr[i] == x)
    121. {
    122. //找到了
    123. return i;
    124. }
    125. }
    126. //没有找到
    127. return -1;
    128. }

    test.c

    1. #include<SeqList.h>
    2. void SLTest01()//测试
    3. {
    4. SL sl;
    5. //初始化
    6. SLlnit(&sl);
    7. //尾插
    8. SLPushBack(&sl, 1);
    9. //打印顺序表
    10. SLprint(sl);
    11. //头插
    12. SLPushFront(&sl,1);
    13. SLPushFront(&sl, 2);
    14. SLPushFront(&sl, 3);
    15. SLPushFront(&sl, 4);
    16. SLprint(sl);
    17. SLPopBack(&sl);
    18. SLprint(sl);
    19. //测试指定位置之前插入数据
    20. SLlnsert(&sl, 3, 90);
    21. SLprint(sl);
    22. //删除指定位置的数据
    23. SLErase(&sl, 4);
    24. SLprint(sl);
    25. int a=SLFind(&sl, 40);
    26. if (a >= 0)
    27. {
    28. printf("找到了,下标是:%d\n", a);
    29. }
    30. else
    31. {
    32. printf("没找到\n");
    33. }
    34. SLDestroy(&sl);
    35. }
    36. int main()
    37. {
    38. SLTest01();
    39. return 0;
    40. }

    感谢观看,再见

  • 相关阅读:
    QT中QTableView获取单元格内容的方法
    工作中出现什么「迹象」,表明你应该换工作了?
    单片机常见的屏幕驱动移植
    镜舟科技荣获第十三届中国智能制造高峰论坛两项大奖
    error: reference to ‘byte‘ is ambiguous使用QtCharts报的错误
    GFI Archiver节省电子邮件服务器空间并轻松检索文件以确保合规性
    【WINDOWS / DOS 批处理】call命令与变量延迟展开
    CRF后处理技术--学习笔记
    CheckBox/RadioButton切换动效实现
    Jan 2023-Prioritizing Samples in Reinforcement Learning with Reducible Loss
  • 原文地址:https://blog.csdn.net/pzn2506/article/details/139198809