一.代码实现功能说明
在C语言中,数组长度一旦被定义,就不能再改变,使得对于数组元素的增删变的十分麻烦,本文将使用一些C语言常见的函数来实现数组的动态扩容,增删功能
这段代码一共设计了九个函数,分别实现初始化动态数组.扩容动态数组.销毁数组空间.获取数组长度.数组往指定索引位置添加元素.数组往尾部插入元素.数组删除指定索引位置的元素.数组删除指定索引位置的元素.遍历数组元素九个功能.
// 动态数组案例 -> 手敲数据结构代码 #include <stdlib.h> #include <stdio.h> // 定义动态数组结构体 typedef struct { // 属性 int *data; // 指向连续空间的第一个地址 size_t length; // 动态数组中真实数据的个数 size_t capacity; // 动态数组中数组空间大小 } DynamicArray; // 初始化动态数组,参数(结构体,初始化数组大小) void initDynamicArray(DynamicArray *array, size_t init_capacity) { // 动态分配内存 array->data = (int *)calloc(init_capacity, sizeof(int)); // 判断是否开辟成功 if (array->data == NULL) { printf("空间开辟失败"); return; } // 开辟成功,需要对结构体实例的长度和容量属性赋值[初始值] array->length = 0; // 将初始化数组大小 赋给 结构体的数组大小 array->capacity = init_capacity; } // 扩容动态数组 void resizeDynamicArray(DynamicArray *array, size_t newCapacity) { // 用realloc函数对动态分配的空间扩大 // 将扩大后的地址仍然赋给原指针 array->data = realloc(array->data, newCapacity * sizeof(int)); // 将新的容量也要重新赋值 array->capacity = newCapacity; } // 销毁内存空间 void destroyDynamicArray(DynamicArray *array) { // 直接用free函数销毁原来开辟的内存 free(array->data); // 虽然内存释放了,但数组依然存在,所以要将数组置为NULL array = NULL; } // 获取长度 int getLength(DynamicArray *array) { return array->length; } // 往指定索引位置添加元素 void insertElement(DynamicArray *array, int index, int element) { // 先判断是否数组已满,或者数组为空 if (index > array->capacity) { // 索引越界 return; } // 考虑扩容问题 if (array->length == array->capacity) { // 数组已满 扩容 int oldcapacity = array->capacity; int newcapacity = oldcapacity + oldcapacity >> 1; resizeDynamicArray(array, 1.5 * array->capacity); } for (int i = array->length; i > index; i--) { array->data[i] = array->data[i - 1]; } // 插入元素 array->data[index] = element; array->length++; } // 往尾部插入元素 void addElement(DynamicArray *array, int element) { insertElement(array, array->length, element); } // 删除指定索引位置的元素 void deleteAtElement(DynamicArray *array, int index) { // 判断删除的索引位置是否合理 if (index >= array->capacity) { return; } for (int i = index; i < array->length - 1; i++) { array->data[i] = array->data[i + 1]; } array->length--; } // 删除数组尾部的元素 void deleteElement(DynamicArray *array) { // array->length--(可以); deleteAtElement(array, array->length - 1); } // 遍历数组元素 void printElements(DynamicArray *array) { // 非空校验 if (array == NULL) { return; } // 无元素 if (array->length == 0) { return; } for (int i = 0; i < array->length; i++) { // printf("%d\t",*(array + i)); printf("%d\t", (array->data)[i]); } printf("\n"); } int main() { DynamicArray array; // 初始化长度为3测试 initDynamicArray(&array, 3); // 插入元素 addElement(&array, 1); addElement(&array, 2); addElement(&array, 3); // 将原来索引为2的位置查插入4 insertElement(&array, 2, 4); // 删除元素 deleteElement(&array); // 删除指定索引位置 deleteAtElement(&array, 1); printElements(&array); return 0; }
二.动态扩容数组逻辑
这里我们重点解释如何实现数组扩容.由于我们的数组内存初始化是使用calloc函数实现的,当我们的开辟的内存已满,可以用realloc函数实现不改变内存地址而扩大内存的目的.
// 扩容动态数组
void resizeDynamicArray(DynamicArray *array, size_t newCapacity)
{
// 用realloc函数对动态分配的空间扩大
// 将扩大后的地址仍然赋给原指针
array->data = realloc(array->data, newCapacity * sizeof(int));
// 将新的容量也要重新赋值
array->capacity = newCapacity;
}
三.插入和删除元素逻辑
插入逻辑
我设计的插入逻辑,是先判断插入后,数组是否能装得下,如果装不下,则需要先调用扩容函数再插入元素.
当开始插入时,先将插入的索引位置之后的元素全部向后平移一位,用倒着遍历循环的方式,将数组的前一个元素赋给后一个元素,代码如下段:
for (int i = array->length; i > index; i--)
{
array->data[i] = array->data[i - 1];
}
并且扩容时,按照原数组的1.5倍(扩容因子,可修改)扩容,当数组内元素已满时扩容,代码如下:
// 考虑扩容问题
if (array->length == array->capacity)
{
// 数组已满 扩容
int oldcapacity = array->capacity;
int newcapacity = oldcapacity + oldcapacity >> 1;
resizeDynamicArray(array, 1.5 * array->capacity);
}
删除逻辑
删除元素并不需要对数组扩容,所以要比插入更简单,不过也需要在删除之前判断要删除的元素索引合不合理.这里我们使用顺序遍历,用删除索引的后一个元素值覆盖前一个元素值,代码如下:
for (int i = index; i < array->length - 1; i++)
{
array->data[i] = array->data[i + 1];
}
array->length--;
880

被折叠的 条评论
为什么被折叠?



