列表是一种支持增删查改的元素有序集合,通常基于动态数组实现,其保留了数组的优势,同时可以灵
活调整长度。
列表的出现大幅地提高了数组的实用性,但可能导致部分内存空间浪费。
/* 列表类简易实现 */
typedef struct {
int* arr; // 数组(存储列表元素)
int capacity; // 列表容量
int size; // 列表大小
int extendRatio; // 列表每次扩容的倍数
} MyList;
/* 构造函数 */
MyList* newMyList() {
MyList* nums = malloc(sizeof(MyList));
nums->capacity = 10;
nums->arr = malloc(sizeof(int) * nums->capacity);
nums->size = 0;
nums->extendRatio = 2;
return nums;
}
/* 析构函数 */
void delMyList(MyList* nums) {
free(nums->arr);
free(nums);
}
/* 获取列表长度 */
int size(MyList* nums) {
return nums->size;
}
/* 获取列表容量 */
int capacity(MyList* nums) {
return nums->capacity;
}
/* 访问元素 */
int get(MyList* nums, int index) {
assert(index >= 0 && index < nums->size);
return nums->arr[index];
}
/* 更新元素 */
void set(MyList* nums, int index, int num) {
assert(index >= 0 && index < nums->size);
//assert 宏可以用于在程序运行时进行断言检查,即对某个条件进行验证,并在条件为假时触发断言失败,中止程序执行并输出错误消息。
nums->arr[index] = num;
}
/* 尾部添加元素 */
void add(MyList* nums, int num) {
if (size(nums) == capacity(nums)) {
extendCapacity(nums); // 扩容
}
nums->arr[size(nums)] = num;
nums->size++;
}
/* 中间插入元素 */
void insert(MyList* nums, int index, int num) {
assert(index >= 0 && index < size(nums));
// 元素数量超出容量时,触发扩容机制
if (size(nums) == capacity(nums)) {
extendCapacity(nums); // 扩容
}
for (int i = size(nums); i > index; --i) {
nums->arr[i] = nums->arr[i - 1];
}
nums->arr[index] = num;
nums->size++;
}
/* 删除元素 */
// 注意:stdio.h 占用了 remove 关键词
int removeItem(MyList* nums, int index) {
assert(index >= 0 && index < size(nums));
int num = nums->arr[index];
for (int i = index; i < size(nums) - 1; i++) {
nums->arr[i] = nums->arr[i + 1];
}
nums->size--;
return num;
}
/* 列表扩容 */
void extendCapacity(MyList* nums) {
// 先分配空间
int newCapacity = capacity(nums) * nums->extendRatio;
int* extend = (int*)malloc(sizeof(int) * newCapacity);
int* temp = nums->arr;
// 拷贝旧数据到新数据
for (int i = 0; i < size(nums); i++)
extend[i] = nums->arr[i];
// 释放旧数据
free(temp);
// 更新新数据
nums->arr = extend;
nums->capacity = newCapacity;
}
/* 将列表转换为 Array 用于打印 */
int* toArray(MyList* nums) {
return nums->arr;
}
以下是对每个函数的代码解释:
newMyList:构造函数,用于创建一个新的 MyList 实例。在函数中,我们使用 malloc 函数为 MyList 结构体分配内存,并初始化 capacity、arr、size 和 extendRatio 字段,然后返回该实例。
delMyList:析构函数,用于释放 MyList 实例的内存。在函数中,我们先释放 arr 指针指向的数组内存,然后再释放 MyList 实例本身的内存。
size:获取列表的当前长度(元素个数),即 size 字段的值。
capacity:获取列表的容量,即 capacity 字段的值。
get:根据索引获取列表中的元素值。在函数中,我们首先使用 assert 断言确保索引值在有效范围内,然后返回 arr 数组中对应索引的元素值。
set:更新列表中指定索引的元素值。在函数中,我们首先使用 assert 断言确保索引值在有效范围内,然后将 num 值赋给 arr 数组中对应的索引位置。
add:在列表尾部添加元素。如果列表已满,则通过 extendCapacity 函数扩容。在函数中,我们将指定的 num 值赋给 arr 数组中下一个可用的位置,并将 size 值增加 1。
insert:在列表的指定索引位置插入元素。如果列表已满,则通过 extendCapacity 函数扩容。在函数中,我们通过后移元素的方式为新元素腾出空间,并将指定的 num 值插入到指定的索引位置,然后将 size 值增加 1。
removeItem:删除列表中指定索引位置的元素。在函数中,我们通过前移元素的方式删除指定的元素,并将 size 值减少 1。最后,返回被删除的元素值。
extendCapacity:列表扩容函数。在函数中,我们首先计算新的容量值,并使用 malloc 函数为新的数组分配内存。然后,我们将旧数据拷贝到新的数组中,并释放旧的数组内存。最后,我们更新 arr 和 capacity 字段的值。
toArray:将列表转换为数组的函数。在函数中,我们简单地返回列表结构体中的 arr 指针。
以上是对每个函数代码的解释,这些函数一起实现了列表的基本功能,包括构造和析构、获取长度和容量、访问和更新元素、添加和插入元素、删除元素、扩容以及转换为数组。