1. 连续存储【数组】
1.1 什么叫做数组
元素类型相同,大小相等(数组传参,只要传进去首地址和长度就行)
1.2 数组的优缺点:
1.2.1 优点:
-
1.2.2 缺点:
事先必须知道数组的长度
- 插入删除元素很慢
- 空间通常是有限制的
- 需要大块连续的内存块
- 插入删除元素的效率很低
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;
init_arr(&arr, 3);append_arr(&arr,2);append_arr(&arr,1);insert_arr(&arr,3,5);//delete_arr(&arr, 3, &val);inversion_arr(&arr);sort_arr(&arr);show_arr(&arr);// printf("%d",val);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)) // 单个元素或空不用排序
else{return;
}int temp,j; // temp哨兵和j前面拍好序的编辑for (int i = 1; i < pArr->cnt; i++){ //后面乱序部分temp = pArr->pBase[i]; // 取一个后面乱序的数与前面已经拍好序的比较for(j = i-1;j>=0;j--){if(temp>=pArr->pBase[j]) // 如果后面取出来的数比前面最大的都大则位置不变break;else{pArr->pBase[j+1]=pArr->pBase[j]; // 移位操作}}pArr->pBase[j+1] = temp; // 插入合适的位置}
}
/**
- @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—){
} return; }temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[pArr->cnt-i-1];pArr->pBase[pArr->cnt-i-1] = temp;
/**
- @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){
}else{printf("动态内存分配失败");exit(-1); // 终止整个程序
} return; }pArr->len = lenght;pArr->cnt = 0;
/**
- @name: is_enpty(struct Arr * pArr)
- @brief: 判断结构体数组是否为空
- @param {struct Arr * pArr:结构体数组地址}
- @return {bool类型,数组为空返回true}
/
bool is_enpty(struct Arr pArr){
if(pArr->cnt == 0)
elsereturn true;
}return false;
/**
- @name: show_arr(struct Arr * pArr)
- @brief: 打印结构体数组
- @param {struct Arr * pArr:结构体数组地址}
- @return {无返回值,直接打印数组元素}
/
void show_arr(struct Arr pArr){
if(is_enpty(pArr)){
}else{printf("数组为空\n");
} }for(int i=0; i<pArr->cnt;i++)printf("%d ",pArr->pBase[i]);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)
elsereturn true;
}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)){
}else{// 不满追加数据printf("数组已满,追加数据失败\n");return false;
} }pArr->pBase[pArr->cnt] = val;pArr->cnt++;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)){
}else{printf("越界异常,插入数据失败\n");return false;
}if(pos>pArr->cnt){ // pos位置落在数组真实元素个数之后,直接追加append_arr(pArr,val);return true;}else{ // pos位置落在数组真实元素之间for(i=pArr->cnt;i>=pos;i--){ // 移位操作pArr->pBase[i] = pArr->pBase[i-1];}pArr->pBase[i] = val; // 插入pos位置元素valpArr->cnt++; // 数组长度加一return true;}
}
/**
- @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)){
}else{printf("数组为空或越界异常,删除失败\n");return false;
} return false; }if(pos >= pArr->cnt){ // 如果pos大于数组中实际元素的个数,小于数组长度,则删除最后一个元素*pVal = pArr->pBase[pArr->cnt-1]; // 返回被删除的数pArr->cnt--; // 数组元素减一return true;}else{ // pos落在数组实际元素中间*pVal = pArr->pBase[pos-1]; // 返回被删除的数for(int i = pos-1; i<pArr->cnt-1; i++){ // 移位操作pArr->pBase[i] = pArr->pBase[i+1];}pArr->cnt--; // 数组元素减一return true;}
<a name="PVetJ"></a>## 1.4 数组的实现-可自动增长版code```c/** @Descripttion: 线性数据结构-数组-可自动增长版* @version: Beta-v1.0.0* @Author: jhong.tao* @Date: 2020-11-28 16:38:42*/# include <stdio.h> // 包含了printf()# include <stdbool.h> // 包含了bool# include <malloc.h> // 包含了malloc()# include <stdlib.h> // 包含了exit()/*** @name: struct Arr* @brief: 定义 struct Arr 结构体数据类型* @param {int * pBase:数组第一个元素的地址}* @param {int len:数组的长度,从一开始计数,数组下标从0开始}* @param {int cnt:数组中实际元素的个数,从1开始计数,数组下标从0开始}* @param {int increment:数组长度不够时,自动增长因子}*/struct Arr{int * pBase; // 存储数组第一个元素的地址int len; // 数组元素的长度int cnt; // 当前数组有效元素的个数int increment; // 自动增长因子 realloc()};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;init_arr(&arr, 2);append_arr(&arr,2);append_arr(&arr,1);insert_arr(&arr,1,5);//delete_arr(&arr, 3, &val);inversion_arr(&arr);sort_arr(&arr);show_arr(&arr);// printf("%d",val);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)) // 单个元素或空不用排序return;else{int temp,j; // temp哨兵和j前面拍好序的编辑for (int i = 1; i < pArr->cnt; i++){ //后面乱序部分temp = pArr->pBase[i]; // 取一个后面乱序的数与前面已经拍好序的比较for(j = i-1;j>=0;j--){if(temp>=pArr->pBase[j]) // 如果后面取出来的数比前面最大的都大则位置不变break;else{pArr->pBase[j+1]=pArr->pBase[j]; // 移位操作}}pArr->pBase[j+1] = temp; // 插入合适的位置}}}/*** @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--){temp = pArr->pBase[i];pArr->pBase[i] = pArr->pBase[pArr->cnt-i-1];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){printf("动态内存分配失败");exit(-1); // 终止整个程序}else{pArr->len = lenght;pArr->cnt = 0;pArr->increment = lenght;}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)return true;elsereturn false;}/*** @name: show_arr(struct Arr * pArr)* @brief: 打印结构体数组* @param {struct Arr * pArr:结构体数组地址}* @return {无返回值,直接打印数组元素}*/void show_arr(struct Arr * pArr){if(is_enpty(pArr)){printf("数组为空\n");}else{for(int i=0; i<pArr->cnt;i++)printf("%d ",pArr->pBase[i]);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)return true;elsereturn 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)){// 数组满了则自动增加数组长度并追加数据pArr->len = pArr->len+pArr->increment;pArr->pBase = (int*)realloc(pArr->pBase,sizeof(int)*pArr->len);}// 不满追加数据if(pArr->pBase == NULL){printf("数组扩容失败,不能追加数据\n");return false;}else{pArr->pBase[pArr->cnt] = val;pArr->cnt++;return true;}}/*** @name: insert_arr(struct Arr * pArr, int pos, int val)* @brief: 在数组的第pos个位置上插入一个元素,pos计数从1开始,如果超过数组元素长度则添加在末尾* @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)){// 数组满了则自动增加数组长度并追加数据pArr->len = pArr->len+pArr->increment;pArr->pBase = (int*)realloc(pArr->pBase,sizeof(int)*pArr->len);}if(pArr->pBase == NULL){printf("数组扩容失败,插入数据失败\n");return false;}else{if(pos<1){printf("越界异常,插入数据失败\n");return false;}else{if(pos>pArr->cnt){ // pos位置落在数组真实元素个数之后,直接追加append_arr(pArr,val);return true;}else{ // pos位置落在数组真实元素之间for(i=pArr->cnt;i>=pos;i--){ // 移位操作pArr->pBase[i] = pArr->pBase[i-1];}pArr->pBase[i] = val; // 插入pos位置元素valpArr->cnt++; // 数组长度加一return true;}}}}/*** @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)){printf("数组为空或越界异常,删除失败\n");return false;}else{if(pos >= pArr->cnt){ // 如果pos大于数组中实际元素的个数,小于数组长度,则删除最后一个元素*pVal = pArr->pBase[pArr->cnt-1]; // 返回被删除的数pArr->cnt--; // 数组元素减一return true;}else{ // pos落在数组实际元素中间*pVal = pArr->pBase[pos-1]; // 返回被删除的数for(int i = pos-1; i<pArr->cnt-1; i++){ // 移位操作pArr->pBase[i] = pArr->pBase[i+1];}pArr->cnt--; // 数组元素减一return true;}}return false;}
