列表是一种支持增删查改的元素有序集合,通常基于动态数组实现,其保留了数组的优势,同时可以灵
活调整长度。

列表的出现大幅地提高了数组的实用性,但可能导致部分内存空间浪费。

/* 列表类简易实现 */
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 指针。

以上是对每个函数代码的解释,这些函数一起实现了列表的基本功能,包括构造和析构、获取长度和容量、访问和更新元素、添加和插入元素、删除元素、扩容以及转换为数组。

posted on 2024-01-07 17:19  lulixiu  阅读(4)  评论(0编辑  收藏  举报