• 【数据结构】动态数组(vector)的基本操作,包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释:


    这段C代码实现了一个动态数组(vector)的基本操作,包括插入、删除、扩容、输出、释放内存等。以下是代码的解释和注释:

    1. // 引入标准输入输出库和标准库函数,用于后续的内存分配和打印输出等操作
    2. #include
    3. #include
    4. // 引入时间库,用于生成随机数(这里并未使用,但保留了引入头文件)
    5. #include
    6. // 定义一个名为vector的结构体,该结构体有三个成员:size表示数组的大小,count表示数组中元素的数量,data是一个指向整型数组的指针,存储数组中的元素
    7. typedef struct vector {
    8. int size, count;
    9. int *data;
    10. } vector;
    11. // getNewVector函数用于创建一个新的动态数组,并返回其指针
    12. vector *getNewVector(int n) {
    13. // 使用malloc函数为vector结构体分配内存
    14. vector *p = (vector *)malloc(sizeof(vector));
    15. // 设置新创建的vector的大小为n,元素数量为0,并为data指针分配n个int类型的内存空间
    16. p->size = n;
    17. p->count = 0;
    18. p->data = (int *)malloc(sizeof(int) * n);
    19. // 返回新创建的vector的指针
    20. return p;
    21. }
    22. // expand函数用于扩容动态数组,将数组的大小翻倍
    23. int expand(vector *v) {
    24. // 检查传入的指针是否为空,如果为空则返回0
    25. if (v == NULL) return 0;
    26. // 打印一条消息表示开始扩容
    27. printf("expand v from %d to %d\n", v->size, 2 * v->size);
    28. // 使用realloc重新分配足够的内存来存储int类型的2n个元素,并将这些元素的地址赋值给data指针
    29. int *p = (int *)realloc(v->data, sizeof(int) * 2 * v->size);
    30. // 如果realloc失败(返回NULL),则返回0;否则,将新分配的内存地址赋值给data,将数组的大小乘以2,并返回1表示扩容成功
    31. if (p == NULL) return 0;
    32. v->data = p;
    33. v->size *= 2;
    34. return 1;
    35. }
    36. // insert函数用于在动态数组的指定位置插入一个元素
    37. int insert(vector *v, int pos, int val) {
    38. // 检查插入的位置是否合法,如果不合法则返回0
    39. if (pos < 0 || pos > v->count) return 0;
    40. // 检查数组是否需要扩容,如果需要扩容但是扩容失败则返回0
    41. if (v->size == v->count && !expand(v)) return 0;
    42. // 从数组的末尾开始向前遍历每个元素,将每个元素向后移动一个位置
    43. for (int i = v->count - 1; i >= pos; i--) {
    44. v->data[i + 1] = v->data[i];
    45. }
    46. // 在指定的位置插入新的元素
    47. v->data[pos] = val;
    48. // 将元素数量加1,然后返回1表示插入成功
    49. v->count += 1;
    50. return 1;
    51. }
    52. // erase函数用于从动态数组中删除指定位置的元素
    53. int erase(vector *v, int pos) {
    54. // 检查删除的位置是否合法,如果不合法则返回0
    55. if (pos < 0 || pos >= v->count) return 0;
    56. // 从删除位置的下一个位置开始遍历每个元素,将每个元素向前移动一个位置
    57. for (int i = pos + 1; i < v->count; i++) {
    58. v->data[i - 1] = v->data[i];
    59. }
    60. // 将元素数量减1,然后返回1表示删除成功
    61. v->count -= 1;
    62. return 1;
    63. }
    64. // 定义一个名为output_vector的函数,它接受一个指向vector结构体的指针作为参数
    65. void output_vector(vector* v) {
    66. // 初始化一个整型变量len,用于存储要输出的整数之和
    67. int len = 0;
    68. // 遍历vector的大小(即其可以容纳的元素数量)
    69. for (int i = 0; i < v->size; i++) {
    70. // 在每次循环中,将整数i的值加到len上,同时输出i的值(格式化为三个数字宽)
    71. len += printf("%3d", i);
    72. }
    73. // 输出一个换行符
    74. printf("\n");
    75. // 根据前面输出的整数数量,输出相应数量的短横线(-)以形成一个框架
    76. for (int i = 0; i < len; i++) printf("-");
    77. // 再输出一个换行符
    78. printf("\n");
    79. // 遍历vector中的元素(只遍历实际存在的元素,即count个)
    80. for (int i = 0; i < v->count; i++) {
    81. // 输出vector中第i个元素的值(格式化为三个数字宽)
    82. printf("%3d", v->data[i]);
    83. }
    84. // 输出一个换行符
    85. printf("\n");
    86. // 输出两个空行,可能是为了创建视觉分隔或提供一些视觉清晰度
    87. printf("\n\n");
    88. // 函数结束,返回无值(void)
    89. return;
    90. }
    91. // 释放动态数组内存
    92. void clear(vector *v) {
    93. // 如果传入的指针为NULL,则直接返回,不进行任何操作
    94. if (v == NULL) return ;
    95. // 释放data指针指向的内存空间
    96. free(v->data);
    97. // 释放v指针指向的内存空间
    98. free(v);
    99. // 返回
    100. return ;
    101. }
    102. // 程序从main函数开始执行
    103. int main() {
    104. // 使用当前时间作为随机数生成器的种子,这样可以使得每次运行程序时生成的随机数都不同
    105. srand(time(0));
    106. // 定义常量MAX_OP为20,表示要进行的操作次数
    107. #define MAX_OP 20
    108. // 调用getNewVector函数创建一个新的动态数组,并返回指向该数组的指针,数组的大小为2
    109. vector *v = getNewVector(2);
    110. // 执行MAX_OP次循环,每次循环都会随机生成一个操作和相应的参数
    111. for (int i = 0; i < MAX_OP; i++) {
    112. // 生成一个介于0到3之间的随机数,这个随机数将用于决定执行哪种操作
    113. int op = rand() % 4, pos, val, ret;
    114. // 根据随机数决定执行哪种操作
    115. switch (op) {
    116. // 如果操作是0、1或2,表示要进行插入操作
    117. case 0:
    118. case 1:
    119. case 2:
    120. // 生成一个介于0到(数组大小+1)之间的随机数,作为插入位置
    121. pos = rand() % (v->count + 2);
    122. // 生成一个介于0到99之间的随机数,作为要插入的值
    123. val = rand() % 100;
    124. // 调用insert函数进行插入操作,并把返回值保存在ret变量中
    125. ret = insert(v, pos, val);
    126. // 输出插入操作的信息,包括插入的值、插入的位置以及插入是否成功的返回值
    127. printf("insert %d at %d to vector = %d\n", val, pos, ret);
    128. break;
    129. // 如果操作是3,表示要进行删除操作
    130. case 3:
    131. // 生成一个介于0到(数组大小+1)之间的随机数,作为删除位置
    132. pos = rand() % (v->count + 2);
    133. // 调用erase函数进行删除操作,并把返回值保存在ret变量中
    134. ret = erase(v, pos);
    135. // 输出删除操作的信息,包括删除位置以及删除是否成功的返回值
    136. printf("erase item at %d in vector = %d\n", pos, ret);
    137. break;
    138. }
    139. // 输出当前动态数组的内容
    140. output_vector(v);
    141. }
    142. // 调用clear函数释放动态数组所占用的内存空间
    143. clear(v);
    144. // 程序正常结束,返回0
    145. return 0;
    146. }

    这段代码实现了一个简单的动态数组(vector),包含插入、删除和打印数组元素的功能。下面是各个函数的功能解释:

    1. getNewVector(int n):这个函数创建了一个新的动态数组,并为其分配了指定数量的整数存储空间。它返回一个指向新创建的动态数组的指针。
    2. expand(vector *v):这个函数用于将动态数组的存储空间扩大一倍。如果当前的存储空间已经足够,那么它什么都不做。否则,它会使用 realloc 函数来重新分配两倍于当前大小的存储空间,并将旧的数据复制到新的存储空间。如果扩大存储空间失败,它会返回0,否则返回1。
    3. insert(vector *v, int pos, int val):这个函数在动态数组中插入一个新的元素。它首先检查插入的位置是否有效,然后检查是否需要扩大存储空间。如果需要扩大存储空间且扩大操作失败,它会返回0。否则,它会将数组中的所有元素向后移动一位,然后在指定的位置插入新的元素。最后,它会返回1表示插入成功。
    4. erase(vector *v, int pos):这个函数从动态数组中删除一个元素。它首先检查删除的位置是否有效,然后删除元素并返回1表示删除成功。
    5. output_vector(vector *v):这个函数打印动态数组的所有元素和它们的位置(包括空位)。
    6. clear(vector *v):这个函数释放动态数组的内存空间。
  • 相关阅读:
    string类接口介绍及应用
    国民技术 N32G45x 串口踩坑
    k8s存储卷 PV和PVC
    虚拟桌面和云桌面办公系统
    Kubernetes(k8s)服务账号Service Accounts
    matlab绁炵粡缃戠粶缂栫▼,绁炵粡缃戠粶 matlab
    spring cloud+spring boot__基于SpringSecurity实现RABC模式实现系统登录和动态权限
    基于STM32F103ZET6库函数独立看门狗(IWDG)实验
    应急响应.windows
    Hardhat开发智能合约和DApp
  • 原文地址:https://blog.csdn.net/dsafefvf/article/details/132677564