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位置元素val
pArr->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;
else
return 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;
else
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)){
// 数组满了则自动增加数组长度并追加数据
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位置元素val
pArr->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;
}