• 顺序表(7.24)


    1.线性表

    线性表 linear list n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
    线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
    线性表在物理上存储时,通常以数组和链式结构的形式存储。

    2.顺序表

    2.1 概念及结构
    顺序表是用一段 物理地址连续 的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。
    顺序表一般可以分为:
    1. 静态顺序表:使用定长(长度确定)数组存储元素,使用比较局限。

    2. 动态顺序表:使用动态开辟的数组存储。

    2.2 动态顺序表的实现

    头文件

    1. #pragma once
    2. #include
    3. #include
    4. #include
    5. //静态顺序表
    6. //#define N 1000
    7. //typedef int SLDataType;
    8. //typedef struct SeqList
    9. //{
    10. // int a[N];
    11. // int size;
    12. //};
    13. //动态顺序表
    14. typedef int SLDataType;
    15. typedef struct SeqList
    16. {
    17. SLDataType* a;//动态内存指针
    18. int size;//存储有效数据个数
    19. int capacity;//动态内存空间大小
    20. }SL;
    21. //管理数据,增删查改
    22. //初始化
    23. void SLInit(SL* ps);
    24. //销毁
    25. void SLDestroy(SL* ps);
    26. //检查空间,如果满了,进行增容
    27. void CheckCapacity(SL* ps);
    28. // 顺序表尾插
    29. void SLPushBack(SL* ps, SLDataType x);
    30. // 顺序表尾删
    31. void SLPopBack(SL* ps);
    32. // 顺序表头插
    33. void SLPushFront(SL* ps, SLDataType x);
    34. // 顺序表头删
    35. void SLPopFront(SL* ps);
    36. //打印
    37. void SLPrint(SL* ps);

    测试文件

    1. //顺序表
    2. #include"SeqList.h"
    3. void TestSeqList1()
    4. {
    5. SL sl;
    6. SLInit(&sl);
    7. SLPushBack(&sl, 1);
    8. SLPushBack(&sl, 2);
    9. SLPushBack(&sl, 3);
    10. SLPushBack(&sl, 4);
    11. SLPushBack(&sl, 5);
    12. SLPushBack(&sl, 6);
    13. SLPushBack(&sl, 6);
    14. SLPushBack(&sl, 0);
    15. SLPushBack(&sl, 0);
    16. SLPrint(&sl);
    17. SLPopBack(&sl);
    18. SLPopBack(&sl);
    19. SLPrint(&sl);
    20. SLPopBack(&sl);
    21. SLPopBack(&sl);
    22. SLPopBack(&sl);
    23. SLPopBack(&sl);
    24. SLPopBack(&sl);
    25. SLPopBack(&sl);
    26. SLPopBack(&sl);
    27. //SLPopBack(&sl);
    28. //SLPopBack(&sl);
    29. /*SLPopBack(&sl);
    30. SLPopBack(&sl);
    31. SLPopBack(&sl);
    32. SLPopBack(&sl);*/
    33. SLPrint(&sl);
    34. SLPushBack(&sl, 1);
    35. SLPushBack(&sl, 2);
    36. SLPrint(&sl);
    37. SLDestroy(&sl);
    38. }
    39. void TestSeqList2()
    40. {
    41. SL sl;
    42. SLInit(&sl);
    43. SLPushBack(&sl, 1);
    44. SLPushBack(&sl, 2);
    45. SLPushBack(&sl, 3);
    46. SLPushBack(&sl, 4);
    47. SLPushBack(&sl, 5);
    48. SLPrint(&sl);
    49. SLPushFront(&sl, 10);
    50. SLPushFront(&sl, 20);
    51. SLPushFront(&sl, 30);
    52. SLPushFront(&sl, 40);
    53. SLPrint(&sl);
    54. }
    55. int main()
    56. {
    57. //TestSeqList1();
    58. TestSeqList2();
    59. return 0;
    60. }

    实现文件

    1. #define _CRT_SECURE_NO_WARNINGS 1
    2. #include"SeqList.h"
    3. //初始化顺序表
    4. void SLInit(SL* ps)
    5. {
    6. //防止传空指针
    7. assert(ps);
    8. //为顺序表开辟动态内存
    9. ps->a = (SLDataType*)malloc(sizeof(SLDataType) *4);
    10. if (ps->a == NULL)
    11. {
    12. perror("malloc");
    13. exit(-1);//退出程序
    14. }
    15. ps->size = 0;
    16. ps->capacity = 4;
    17. }
    18. //检查空间,如果满了,进行增容
    19. void CheckCapacity(SL* ps)
    20. {
    21. //防止传空指针
    22. assert(ps);
    23. //动态内存放满,需要扩容
    24. if (ps->size == ps->capacity)
    25. {
    26. //用临时指针存放扩容后的动态内存地址
    27. SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * sizeof(SLDataType) * 2);
    28. if (tmp == NULL)
    29. {
    30. perror("realloc");
    31. exit(-1);
    32. }
    33. //归还地址
    34. ps->a = tmp;
    35. ps->capacity *= 2;
    36. }
    37. }
    38. // 顺序表头插
    39. void SLPushFront(SL * ps, SLDataType x)
    40. {
    41. //防止传空指针
    42. assert(ps);
    43. //CheckCapacity(ps);
    44. 挪动数据,从后往前挪,次数为size-1
    45. //int end = ps->size - 1;
    46. //while (end>=0)
    47. //{
    48. // ps->a[end + 1] = ps->a[end];
    49. // end--;
    50. //}
    51. //ps->a[0] = x;
    52. //ps->size++;
    53. //函数复用
    54. SLInsert(ps,0, x);
    55. }
    56. // 顺序表头删
    57. void SLPopFront(SL* ps)
    58. {
    59. //防止传空指针
    60. assert(ps);
    61. //防止数据表空了继续删除
    62. assert(ps->size > 0);
    63. int end = 0;
    64. while (end <= ps->size - 1)
    65. {
    66. //从左往右移,将首位覆盖
    67. ps->a[end] = ps->a[end + 1];//画图便于控制越界问题
    68. end++;
    69. }
    70. ps->size--;
    71. }
    72. // 顺序表尾插
    73. void SLPushBack(SL* ps, SLDataType x)
    74. {
    75. //防止传空指针
    76. assert(ps);
    77. //检查放满
    78. /*CheckCapacity(ps);
    79. ps->a[ps->size] = x;
    80. ps->size++;*/
    81. //函数复用
    82. SLInsert(ps,ps->size,x);
    83. }
    84. // 顺序表尾删
    85. void SLPopBack(SL* ps)
    86. {
    87. //防止传空指针
    88. assert(ps);
    89. //如果size为0,就返回,继续删会导致越界(温柔检查)
    90. if (ps->size == 0)
    91. {
    92. return;
    93. }
    94. //或者使用断言检查size(暴力检查)
    95. assert(ps->size);
    96. //size--就代表将数据删除了
    97. ps->size--;
    98. }
    99. //销毁
    100. void SLDestroy(SL* ps)
    101. {
    102. //防止传空指针
    103. assert(ps);
    104. free(ps->a);
    105. ps->a = NULL;
    106. ps->capacity = ps->size = 0;
    107. }
    108. //在pos位置插入x
    109. void SLInsert(SL* ps, int pos, SLDataType x)
    110. {
    111. //防止传空指针
    112. assert(ps);
    113. //判断pos的位置是否合法
    114. assert(pos >= 0 && pos <= ps->size);
    115. //检查放满
    116. CheckCapacity(ps);
    117. int end = ps->size - 1;
    118. while (pos <= end)
    119. {
    120. ps->a[end+1] = ps->a[end];
    121. }
    122. ps->a[pos] = x;
    123. ps->size++;
    124. }
    125. //在pos位置删除
    126. void SLErase(SL* ps, int pos)
    127. {
    128. //防止传空指针
    129. assert(ps);
    130. //判断pos的位置是否合法
    131. //与插入时不同,能够插入数组后一个空位,但不能删除这个空位
    132. assert(pos >= 0 && pos < ps->size);
    133. int end = ps->size - 2;
    134. while (pos <= end)
    135. {
    136. ps->a[pos] = ps->a[pos + 1];
    137. pos++;
    138. }
    139. ps->size--;
    140. }
    141. //查找某个数的位置
    142. int SLFind(SL* ps, SLDataType x)
    143. {
    144. //防止传空指针
    145. assert(ps);
    146. for (int i = 0; i < ps->size; i++)
    147. {
    148. if (x == ps->a[i])
    149. {
    150. return i;
    151. }
    152. }
    153. return -1;
    154. }
    155. //打印
    156. void SLPrint(SL* ps)
    157. {
    158. //防止传空指针
    159. assert(ps);
    160. int i = 0;
    161. for (i = 0; i < ps->size; i++)
    162. {
    163. printf("%d ", ps->a[i]);
    164. }
    165. printf("\n");
    166. }

    测试

     //在pos位置插入x
    void SLInsert(SL* ps,int pos,SLDataType x);

     1.先检查pos的位置是否合法,即是否在数组范围内(0-size)

    2.检查内存空间是否放满,否则扩容

    3.实现:从后往前挪,然后将数据放入挪出的空位中

    1. //在pos位置插入x
    2. void SLInsert(SL* ps, int pos, SLDataType x)
    3. {
    4. //判断pos的位置是否合法
    5. assert(pos >= 0 && pos <= ps->size);
    6. //检查放满
    7. CheckCapacity(ps);
    8. int end = ps->size - 1;
    9. while (pos <= end)
    10. {
    11. ps->a[end+1] = ps->a[end];
    12. }
    13. ps->a[pos] = x;
    14. ps->size++;
    15. }

    注意:1.在顺序表中不要随意直接调用成员,而是通过函数,以便出错时能通过函数内的检查直接发现错误。

    2.数据结构一般不写菜单,不利于调试,如果要写,将程序正常运行之后最后写菜单。

  • 相关阅读:
    基于RabbitMQ的模拟消息队列之六——网络通信设计
    PyQt5 QSS的UI美化
    数据结构与算法之LeetCode-652. 寻找重复的子树
    Leetcode周赛304
    使用xss来打cookie
    Nginx的location作用
    10年测试经验,在35岁的生理年龄面前,一文不值
    [前端框架]-VUE(下篇)
    IPNV6
    利用QT来实现经典小游戏之经典
  • 原文地址:https://blog.csdn.net/dn235z/article/details/133429945