1. 连续存储【数组】

1.1 什么叫做数组

元素类型相同,大小相等(数组传参,只要传进去首地址和长度就行)

1.2 数组的优缺点:

1.2.1 优点:

  1. 存取速度快

    1.2.2 缺点:

  2. 事先必须知道数组的长度

  3. 插入删除元素很慢
  4. 空间通常是有限制的
  5. 需要大块连续的内存块
  6. 插入删除元素的效率很低

    1.3 数组的实现-不可自动增长版code

    ```c /*
    • @Descripttion: 线性数据结构-数组-不可自动增长版
    • @version: Beta-v1.0.0
    • @Author: jhong.tao
    • @Date: 2020-11-28 16:38:42 */

include // 包含了printf()

include // 包含了bool

include // 包含了malloc()

include // 包含了exit()

// 定义 struct Arr 结构体数据类型 struct Arr{ int * pBase; // 存储数组第一个元素的地址 int len; // 数组元素的长度 int cnt; // 当前数组有效元素的个数 // int increment // 自动增长因子 allocate() };

void init_arr(struct Arr pArr, int lenght); // 初始化 bool append_arr(struct Arr pArr, int val); // 末尾追加数据 bool insert_arr(struct Arr pArr, int pos, int val); // 插入数据,在pos位置插入一个数据,pos计数从1开始 bool delete_arr(struct Arr pArr, int pos, int pVal); // 删除数据,pos从1开始 int get(); // 获取下标值 bool is_enpty(struct Arr pArr); // 判空 bool is_full(struct Arr pArr); // 判满 void sort_arr(struct Arr pArr); // 排序 void show_arr(struct Arr pArr); // 打印 void inversion_arr(struct Arr pArr); // 倒置

int main(void){ struct Arr arr; int val;

  1. init_arr(&arr, 3);
  2. append_arr(&arr,2);
  3. append_arr(&arr,1);
  4. insert_arr(&arr,3,5);
  5. //delete_arr(&arr, 3, &val);
  6. inversion_arr(&arr);
  7. sort_arr(&arr);
  8. show_arr(&arr);
  9. // printf("%d",val);
  10. return 0;

}

/**

  • @name: sort_arr(struct Arr * pArr)
  • @brief: 直接插入排序
  • @param {struct Arr * pArr:结构体数组地址}
  • @return {无返回值} / void sort_arr(struct Arr pArr){ if(pArr->cnt <2 ||is_enpty(pArr)) // 单个元素或空不用排序
    1. return;
    else{
    1. int temp,j; // temp哨兵和j前面拍好序的编辑
    2. for (int i = 1; i < pArr->cnt; i++){ //后面乱序部分
    3. temp = pArr->pBase[i]; // 取一个后面乱序的数与前面已经拍好序的比较
    4. for(j = i-1;j>=0;j--){
    5. if(temp>=pArr->pBase[j]) // 如果后面取出来的数比前面最大的都大则位置不变
    6. break;
    7. else{
    8. pArr->pBase[j+1]=pArr->pBase[j]; // 移位操作
    9. }
    10. }
    11. pArr->pBase[j+1] = temp; // 插入合适的位置
    12. }
    }

}

/**

  • @name: inversion_arr(struct Arr * pArr)
  • @brief: 将数组元素反向
  • @param {struct Arr * pArr:结构体数组地址}
  • @return {无返回值} / void inversion_arr(struct Arr pArr){ int temp; for(int i = pArr->cnt-1;i>=pArr->cnt/2;i—){
    1. temp = pArr->pBase[i];
    2. pArr->pBase[i] = pArr->pBase[pArr->cnt-i-1];
    3. pArr->pBase[pArr->cnt-i-1] = temp;
    } return; }

/**

  • @name: init_arr(struct Arr * pArr, int lenght)
  • @brief: 初始化结构体数组
  • @param {struct Arr * pArr:结构体数组地址}
  • @param {int lenght:数组初试长度}
  • @return {没有返回值} / void init_arr(struct Arr pArr, int lenght){ pArr->pBase = (int)malloc(sizeof(int)lenght); //pArr指针变量所指向的arr结构体变量中的pBase成员 if(NULL == pArr->pBase){
    1. printf("动态内存分配失败");
    2. exit(-1); // 终止整个程序
    }else{
    1. pArr->len = lenght;
    2. pArr->cnt = 0;
    } return; }

/**

  • @name: is_enpty(struct Arr * pArr)
  • @brief: 判断结构体数组是否为空
  • @param {struct Arr * pArr:结构体数组地址}
  • @return {bool类型,数组为空返回true} / bool is_enpty(struct Arr pArr){ if(pArr->cnt == 0)
    1. return true;
    else
    1. return false;
    }

/**

  • @name: show_arr(struct Arr * pArr)
  • @brief: 打印结构体数组
  • @param {struct Arr * pArr:结构体数组地址}
  • @return {无返回值,直接打印数组元素} / void show_arr(struct Arr pArr){ if(is_enpty(pArr)){
    1. printf("数组为空\n");
    }else{
    1. for(int i=0; i<pArr->cnt;i++)
    2. printf("%d ",pArr->pBase[i]);
    3. printf("\n");
    } }

/**

  • @name: is_full(struct Arr * pArr)
  • @brief: 判断数组元素是否满
  • @param {struct Arr * pArr:结构体数组地址}
  • @return {bool类型,true:表示数组已满} / bool is_full(struct Arr pArr){ if(pArr->cnt == pArr->len)
    1. return true;
    else
    1. return false;
    }

/**

  • @name: append_arr(struct Arr * pArr, int val)
  • @brief: 向数组末尾追加一个元素
  • @param {struct Arr * pArr:结构体数组地址}
  • @param {int val:需要追加的元素}
  • @return {bool类型值,判断数据追加是否成功} / bool append_arr(struct Arr pArr, int val){ if(is_full(pArr)){
    1. printf("数组已满,追加数据失败\n");
    2. return false;
    }else{// 不满追加数据
    1. pArr->pBase[pArr->cnt] = val;
    2. pArr->cnt++;
    3. return true;
    } }

/**

  • @name: insert_arr(struct Arr * pArr, int pos, int val)
  • @brief: 在数组的第pos个位置上插入一个元素
  • @param {struct Arr * pArr:结构体数组变量}
  • @param {int pos:在数组中需要插入数据的位置,pos从1开始,数组元组下标从0开始}
  • @param {int val:被插入的数}
  • @return {bool类型值,判断插入成功与否} / bool insert_arr(struct Arr pArr, int pos, int val){ int i; if(is_full(pArr) ||(pos<1 || pos>pArr->len)){
    1. printf("越界异常,插入数据失败\n");
    2. return false;
    }else{
    1. if(pos>pArr->cnt){ // pos位置落在数组真实元素个数之后,直接追加
    2. append_arr(pArr,val);
    3. return true;
    4. }else{ // pos位置落在数组真实元素之间
    5. for(i=pArr->cnt;i>=pos;i--){ // 移位操作
    6. pArr->pBase[i] = pArr->pBase[i-1];
    7. }
    8. pArr->pBase[i] = val; // 插入pos位置元素val
    9. pArr->cnt++; // 数组长度加一
    10. return true;
    11. }
    }

}

/**

  • @name: delete_arr(struct Arr pArr, int pos, int pVal)
  • @brief: 删除数组中pos位置的元素
  • @param {struct Arr * pArr:结构体数组的地址}
  • @param {int pos:被删除元素在数组中的位置,pos计数从1开始,数组元素计数从0开始}
  • @param {int * pVal:返回被删除的数}
  • @return {bool 类型值,表示删除成功与否} / bool delete_arr(struct Arr pArr, int pos, int * pVal){ if(is_enpty(pArr) || (pos<1 || pos>pArr->len)){
    1. printf("数组为空或越界异常,删除失败\n");
    2. return false;
    }else{
    1. if(pos >= pArr->cnt){ // 如果pos大于数组中实际元素的个数,小于数组长度,则删除最后一个元素
    2. *pVal = pArr->pBase[pArr->cnt-1]; // 返回被删除的数
    3. pArr->cnt--; // 数组元素减一
    4. return true;
    5. }else{ // pos落在数组实际元素中间
    6. *pVal = pArr->pBase[pos-1]; // 返回被删除的数
    7. for(int i = pos-1; i<pArr->cnt-1; i++){ // 移位操作
    8. pArr->pBase[i] = pArr->pBase[i+1];
    9. }
    10. pArr->cnt--; // 数组元素减一
    11. return true;
    12. }
    } return false; }
  1. <a name="PVetJ"></a>
  2. ## 1.4 数组的实现-可自动增长版code
  3. ```c
  4. /*
  5. * @Descripttion: 线性数据结构-数组-可自动增长版
  6. * @version: Beta-v1.0.0
  7. * @Author: jhong.tao
  8. * @Date: 2020-11-28 16:38:42
  9. */
  10. # include <stdio.h> // 包含了printf()
  11. # include <stdbool.h> // 包含了bool
  12. # include <malloc.h> // 包含了malloc()
  13. # include <stdlib.h> // 包含了exit()
  14. /**
  15. * @name: struct Arr
  16. * @brief: 定义 struct Arr 结构体数据类型
  17. * @param {int * pBase:数组第一个元素的地址}
  18. * @param {int len:数组的长度,从一开始计数,数组下标从0开始}
  19. * @param {int cnt:数组中实际元素的个数,从1开始计数,数组下标从0开始}
  20. * @param {int increment:数组长度不够时,自动增长因子}
  21. */
  22. struct Arr{
  23. int * pBase; // 存储数组第一个元素的地址
  24. int len; // 数组元素的长度
  25. int cnt; // 当前数组有效元素的个数
  26. int increment; // 自动增长因子 realloc()
  27. };
  28. void init_arr(struct Arr * pArr, int lenght); // 初始化
  29. bool append_arr(struct Arr * pArr, int val); // 末尾追加数据
  30. bool insert_arr(struct Arr * pArr, int pos, int val); // 插入数据,在pos位置插入一个数据,pos计数从1开始
  31. bool delete_arr(struct Arr * pArr, int pos, int * pVal); // 删除数据,pos从1开始
  32. int get(); // 获取下标值
  33. bool is_enpty(struct Arr * pArr); // 判空
  34. bool is_full(struct Arr * pArr); // 判满
  35. void sort_arr(struct Arr * pArr); // 排序
  36. void show_arr(struct Arr * pArr); // 打印
  37. void inversion_arr(struct Arr * pArr); // 倒置
  38. int main(void){
  39. struct Arr arr;
  40. int val;
  41. init_arr(&arr, 2);
  42. append_arr(&arr,2);
  43. append_arr(&arr,1);
  44. insert_arr(&arr,1,5);
  45. //delete_arr(&arr, 3, &val);
  46. inversion_arr(&arr);
  47. sort_arr(&arr);
  48. show_arr(&arr);
  49. // printf("%d",val);
  50. return 0;
  51. }
  52. /**
  53. * @name: sort_arr(struct Arr * pArr)
  54. * @brief: 直接插入排序
  55. * @param {struct Arr * pArr:结构体数组地址}
  56. * @return {无返回值}
  57. */
  58. void sort_arr(struct Arr * pArr){
  59. if(pArr->cnt <2 ||is_enpty(pArr)) // 单个元素或空不用排序
  60. return;
  61. else{
  62. int temp,j; // temp哨兵和j前面拍好序的编辑
  63. for (int i = 1; i < pArr->cnt; i++){ //后面乱序部分
  64. temp = pArr->pBase[i]; // 取一个后面乱序的数与前面已经拍好序的比较
  65. for(j = i-1;j>=0;j--){
  66. if(temp>=pArr->pBase[j]) // 如果后面取出来的数比前面最大的都大则位置不变
  67. break;
  68. else{
  69. pArr->pBase[j+1]=pArr->pBase[j]; // 移位操作
  70. }
  71. }
  72. pArr->pBase[j+1] = temp; // 插入合适的位置
  73. }
  74. }
  75. }
  76. /**
  77. * @name: inversion_arr(struct Arr * pArr)
  78. * @brief: 将数组元素反向
  79. * @param {struct Arr * pArr:结构体数组地址}
  80. * @return {无返回值}
  81. */
  82. void inversion_arr(struct Arr * pArr){
  83. int temp;
  84. for(int i = pArr->cnt-1;i>=pArr->cnt/2;i--){
  85. temp = pArr->pBase[i];
  86. pArr->pBase[i] = pArr->pBase[pArr->cnt-i-1];
  87. pArr->pBase[pArr->cnt-i-1] = temp;
  88. }
  89. return;
  90. }
  91. /**
  92. * @name: init_arr(struct Arr * pArr, int lenght)
  93. * @brief: 初始化结构体数组
  94. * @param {struct Arr * pArr:结构体数组地址}
  95. * @param {int lenght:数组初试长度}
  96. * @return {没有返回值}
  97. */
  98. void init_arr(struct Arr * pArr, int lenght){
  99. pArr->pBase = (int*)malloc(sizeof(int)*lenght); //pArr指针变量所指向的arr结构体变量中的pBase成员
  100. if(NULL == pArr->pBase){
  101. printf("动态内存分配失败");
  102. exit(-1); // 终止整个程序
  103. }else{
  104. pArr->len = lenght;
  105. pArr->cnt = 0;
  106. pArr->increment = lenght;
  107. }
  108. return;
  109. }
  110. /**
  111. * @name: is_enpty(struct Arr * pArr)
  112. * @brief: 判断结构体数组是否为空
  113. * @param {struct Arr * pArr:结构体数组地址}
  114. * @return {bool类型,数组为空返回true}
  115. */
  116. bool is_enpty(struct Arr * pArr){
  117. if(pArr->cnt == 0)
  118. return true;
  119. else
  120. return false;
  121. }
  122. /**
  123. * @name: show_arr(struct Arr * pArr)
  124. * @brief: 打印结构体数组
  125. * @param {struct Arr * pArr:结构体数组地址}
  126. * @return {无返回值,直接打印数组元素}
  127. */
  128. void show_arr(struct Arr * pArr){
  129. if(is_enpty(pArr)){
  130. printf("数组为空\n");
  131. }else{
  132. for(int i=0; i<pArr->cnt;i++)
  133. printf("%d ",pArr->pBase[i]);
  134. printf("\n");
  135. }
  136. }
  137. /**
  138. * @name: is_full(struct Arr * pArr)
  139. * @brief: 判断数组元素是否满
  140. * @param {struct Arr * pArr:结构体数组地址}
  141. * @return {bool类型,true:表示数组已满}
  142. */
  143. bool is_full(struct Arr * pArr){
  144. if(pArr->cnt == pArr->len)
  145. return true;
  146. else
  147. return false;
  148. }
  149. /**
  150. * @name: append_arr(struct Arr * pArr, int val)
  151. * @brief: 向数组末尾追加一个元素,如果数组满了则自动增长长度
  152. * @param {struct Arr * pArr:结构体数组地址}
  153. * @param {int val:需要追加的元素}
  154. * @return {bool类型值,判断数据追加是否成功}
  155. */
  156. bool append_arr(struct Arr * pArr, int val){
  157. if(is_full(pArr)){
  158. // 数组满了则自动增加数组长度并追加数据
  159. pArr->len = pArr->len+pArr->increment;
  160. pArr->pBase = (int*)realloc(pArr->pBase,sizeof(int)*pArr->len);
  161. }
  162. // 不满追加数据
  163. if(pArr->pBase == NULL){
  164. printf("数组扩容失败,不能追加数据\n");
  165. return false;
  166. }else{
  167. pArr->pBase[pArr->cnt] = val;
  168. pArr->cnt++;
  169. return true;
  170. }
  171. }
  172. /**
  173. * @name: insert_arr(struct Arr * pArr, int pos, int val)
  174. * @brief: 在数组的第pos个位置上插入一个元素,pos计数从1开始,如果超过数组元素长度则添加在末尾
  175. * @param {struct Arr * pArr:结构体数组变量}
  176. * @param {int pos:在数组中需要插入数据的位置,pos从1开始,数组元组下标从0开始}
  177. * @param {int val:被插入的数}
  178. * @return {bool类型值,判断插入成功与否}
  179. */
  180. bool insert_arr(struct Arr * pArr, int pos, int val){
  181. int i;
  182. if(is_full(pArr)){
  183. // 数组满了则自动增加数组长度并追加数据
  184. pArr->len = pArr->len+pArr->increment;
  185. pArr->pBase = (int*)realloc(pArr->pBase,sizeof(int)*pArr->len);
  186. }
  187. if(pArr->pBase == NULL){
  188. printf("数组扩容失败,插入数据失败\n");
  189. return false;
  190. }else{
  191. if(pos<1){
  192. printf("越界异常,插入数据失败\n");
  193. return false;
  194. }else{
  195. if(pos>pArr->cnt){ // pos位置落在数组真实元素个数之后,直接追加
  196. append_arr(pArr,val);
  197. return true;
  198. }else{ // pos位置落在数组真实元素之间
  199. for(i=pArr->cnt;i>=pos;i--){ // 移位操作
  200. pArr->pBase[i] = pArr->pBase[i-1];
  201. }
  202. pArr->pBase[i] = val; // 插入pos位置元素val
  203. pArr->cnt++; // 数组长度加一
  204. return true;
  205. }
  206. }
  207. }
  208. }
  209. /**
  210. * @name: delete_arr(struct Arr * pArr, int pos, int * pVal)
  211. * @brief: 删除数组中pos位置的元素
  212. * @param {struct Arr * pArr:结构体数组的地址}
  213. * @param {int pos:被删除元素在数组中的位置,pos计数从1开始,数组元素计数从0开始}
  214. * @param {int * pVal:返回被删除的数}
  215. * @return {bool 类型值,表示删除成功与否}
  216. */
  217. bool delete_arr(struct Arr * pArr, int pos, int * pVal){
  218. if(is_enpty(pArr) || (pos<1 || pos>pArr->len)){
  219. printf("数组为空或越界异常,删除失败\n");
  220. return false;
  221. }else{
  222. if(pos >= pArr->cnt){ // 如果pos大于数组中实际元素的个数,小于数组长度,则删除最后一个元素
  223. *pVal = pArr->pBase[pArr->cnt-1]; // 返回被删除的数
  224. pArr->cnt--; // 数组元素减一
  225. return true;
  226. }else{ // pos落在数组实际元素中间
  227. *pVal = pArr->pBase[pos-1]; // 返回被删除的数
  228. for(int i = pos-1; i<pArr->cnt-1; i++){ // 移位操作
  229. pArr->pBase[i] = pArr->pBase[i+1];
  230. }
  231. pArr->cnt--; // 数组元素减一
  232. return true;
  233. }
  234. }
  235. return false;
  236. }