回顾上节
上节是在动态数组的尾部添加一个元素
方式是再申请一个更大的空间,代替原空间
现在要在中间插入元素,该怎么办呢?
添加步骤
基于上一步的操作添加步骤
1)创建在中间添加节点的函数
传参的话,首先必传的是结构体指针
其次,要添加节点,所以一定还要传添加的中间值
最后,在中间添加一个元素的下标还要有,不然不知道加在哪
//MidNum是中间值,Index是要添加在的位置
void AddMid(struct DynamicArr *pArr,int MidNum,int Index){}
2)首先,要进行指针判断,万一传回来的是NULL
怎么办。
其次,在中间添加元素是要将原添加位置的值及后面的值都往后移,万一后面的空间不够怎么办。需要之前的步骤
if (NULL == pArr)
{
return;
}
//同样也是先判断空间是否已满
if (pArr->Cap == pArr->Num)
{
//先将原空间扩容
pArr->Cap += 10;
//中间指针变量定义新空间
int *ptemp = (int*)malloc(sizeof(int)*pArr->Cap);
//将原空间元素赋值到新空间
for (int i = 0; i<pArr->Num; i++)
{
ptemp[i] = pArr->Head[i];
}
//赋值完后释放原空间
free(pArr->Head);
//将释放的空间重新指向现在的空间
pArr->Head = ptemp;
}
3)这一步就要实现将元素往后移。因为不只是后移一个元素,所以要用到循环,整体往后移
//将Index之后的元素后移
for (int i = pArr->Num ;i>Index;i--)
pArr->Head[i] = pArr->Head[i - 1];
int i = pArr->Num
是从后往前循环赋值,到Index
的位置结束
4)后移之后,位置就空出来了,添加元素就好了
//将MidNum插入Index的位置
pArr->Head[Index] = MidNum;
5)此时,元素个数增加了
//元素个数+1
pArr->Num++;
6)主函数调用添加中间变量的函数
//元素个数+1
pArr->Num++;
整体代码如下:
#include<stdio.h>
#include<stdlib.h>
//定义动态数组结构体
struct DynamicArr
{
//定义指针指向数组头
int *Head;
//定义记录容量
int Cap;
//记录数量
int Num;
};
//初始化数组
void IniArr(struct DynamicArr *pArr)
{
pArr->Cap = 5;
pArr->Head = (int*)malloc(sizeof(int)*pArr->Cap );
pArr->Num = 0;
}
//在尾部增加节点
void AddLast(struct DynamicArr *pArr,int LastNum)
{
//先判断空间是否已满
if (pArr->Cap == pArr->Num )
{
//先将原空间扩容
pArr->Cap += 10;
//中间指针变量定义新空间
int *ptemp = (int*)malloc(sizeof(int)*pArr->Cap );
//将原空间元素赋值到新空间
for (int i = 0;i<pArr->Num ;i++)
{
ptemp[i] = pArr->Head[i];
}
//赋值完就释放原空间
free(pArr->Head );
//将释放的空间重新指向现在的空间
pArr->Head = ptemp ;
}
//在最后添加
pArr->Head[pArr->Num] = LastNum;
//增加数量
pArr->Num++;
}
//输出
void print(struct DynamicArr *pArr)
{
if (NULL == pArr)
return;
printf("%d %d\n",pArr->Cap ,pArr->Num );
for (int i = 0; i < pArr->Num;i++)
printf("%d ",pArr->Head [i]);
}
//在中间增加位置
void AddMid(struct DynamicArr *pArr,int MidNum,int Index)
{
if (NULL == pArr)
return;
//同样也是先判断空间是否已满
if (pArr->Cap == pArr->Num)
{
//先将原空间扩容
pArr->Cap += 10;
//中间指针变量定义新空间
int *ptemp = (int*)malloc(sizeof(int)*pArr->Cap);
//将原空间元素赋值到新空间
for (int i = 0; i<pArr->Num; i++)
ptemp[i] = pArr->Head[i];
//赋值完就释放原空间
free(pArr->Head);
//将释放的空间重新指向现在的空间
pArr->Head = ptemp;
}
//将Index之后的元素后移
for (int i = pArr->Num ;i>Index;i--)
pArr->Head[i] = pArr->Head[i - 1];
//将MidNum插入Index的位置
pArr->Head[Index] = MidNum;
//元素个数+1
pArr->Num++;
}
int main()
{
struct DynamicArr Arr;
IniArr(&Arr);
AddLast(&Arr, 1);
AddLast(&Arr, 2);
AddLast(&Arr, 3);
//调用插入节点的函数
AddMid(&Arr,1,1);
print(&Arr);
free(Arr.Head);
system("pause");
return 0;
}
输出:
5 4
1 1 2 3
特殊情况
如果要传入的下标不在数量的范围内,就会在最后赋值,但是要经过挪元素的代码,可以定义个判断语句,如果大于数量就直接在最后赋值,这样就更好了
//下标太大,不在范围内,判断语句,插后面
if (Index>pArr->Num )
{
pArr->Num = Index;
}
注意:一定要在挪之前判断,否则都挪完了,再写,也没啥效果了。
重改代码
把重复的代码封装成函数
重复的代码:
//同样也是先判断空间是否已满
if (pArr->Cap == pArr->Num)
{
//先将原空间扩容
pArr->Cap += 10;
//中间指针变量定义新空间
int *ptemp = (int*)malloc(sizeof(int)*pArr->Cap);
//将原空间元素赋值到新空间
for (int i = 0; i<pArr->Num; i++)
{
ptemp[i] = pArr->Head[i];
}
//赋值完就释放原空间
free(pArr->Head);
//将释放的空间重新指向现在的空间
pArr->Head = ptemp;
}
封装:直接调用就好了
void AddLast(struct DynamicArr *pArr, int LastNum)
{
ArrP(pArr);
//在最后添加
pArr->Head[pArr->Num] = LastNum;
//增加数量
pArr->Num++;
}
整体代码如下:
#include<stdio.h>
#include<stdlib.h>
void IniArr(struct DynamicArr *pArr);
void AddLast(struct DynamicArr *pArr, int LastNum);
void print(struct DynamicArr *pArr);
void AddMid(struct DynamicArr *pArr, int MidNum, int Index);
void ArrP(struct DynamicArr *pArr);
//定义动态数组结构体
struct DynamicArr
{
//定义指针指向数组头
int *Head;
//定义记录容量
int Cap;
//记录数量
int Num;
};
//初始化数组
void IniArr(struct DynamicArr *pArr)
{
pArr->Cap = 5;
pArr->Head = (int*)malloc(sizeof(int)*pArr->Cap);
pArr->Num = 0;
}
//在尾部增加节点
void AddLast(struct DynamicArr *pArr, int LastNum)
{
ArrP(pArr);
//在最后添加
pArr->Head[pArr->Num] = LastNum;
//增加数量
pArr->Num++;
}
//输出
void print(struct DynamicArr *pArr)
{
if (NULL == pArr)
{
return;
}
printf("%d %d\n", pArr->Cap, pArr->Num);
for (int i = 0; i < pArr->Num; i++)
{
printf("%d ", pArr->Head[i]);
}
}
//在中间增加位置
void AddMid(struct DynamicArr *pArr, int MidNum, int Index)
{
if (NULL == pArr)
{
return;
}
ArrP(pArr);
//下标太大,不在范围内,判断语句,插后面
if (Index>pArr->Num )
{
pArr->Num = Index;
}
//将Index之后的元素后移
for (int i = pArr->Num; i>Index; i--)
{
pArr->Head[i] = pArr->Head[i - 1];
}
//将MidNum插入Index的位置
pArr->Head[Index] = MidNum;
//元素个数+1
pArr->Num++;
}
void ArrP(struct DynamicArr *pArr)
{
//同样也是先判断空间是否已满
if (pArr->Cap == pArr->Num)
{
//先将原空间扩容
pArr->Cap += 10;
//中间指针变量定义新空间
int *ptemp = (int*)malloc(sizeof(int)*pArr->Cap);
//将原空间元素赋值到新空间
for (int i = 0; i<pArr->Num; i++)
{
ptemp[i] = pArr->Head[i];
}
//赋值完就释放原空间
free(pArr->Head);
//将释放的空间重新指向现在的空间
pArr->Head = ptemp;
}
}
int main()
{
struct DynamicArr Arr;
IniArr(&Arr);
AddLast(&Arr, 1);
AddLast(&Arr, 2);
AddLast(&Arr, 3);
//调用插入节点的函数
AddMid(&Arr, 1, 1);
AddMid(&Arr, 1, 4);
AddMid(&Arr, 1, 3);
print(&Arr);
free(Arr.Head);
system("pause");
return 0;
}