题目:
动手自己实现动态数组Vector,基于以下结构体定义和函数声明:
typedef int ElementType;
typedef struct {
ElementType *data; // 指向堆空间的数组
int size; // 元素的个数
int capacity; // 数组的容量 } Vector;// 请实现下面方法
// 初始化一个Vector动态数组 Vector *vector_create(void);
// 销毁一个Vector动态数组,释放内存。 void vector_destroy(Vector *v);
// 向动态数组末尾添加一个元素 void vector_push_back(Vector *v, ElementType val);
// 在动态数组最前面添加元素,所有元素依次后移 void vector_push_front(Vector *v, ElementType
val);// 将元素val添加到索引为idx的位置,idx后面的元素依次后移 void vector_insert(Vector *v, int
idx, ElementType val);// 遍历打印整个Vector动态数组 void vector_print(Vector *v); 注意:
你应该将上述代码放在头文件中,并且自己添加头文件保护语法。
提交时,你应该提交头文件,实现Vector的源文件,测试源文件三个文件的代码
关键点
#ifndef VECTOR_H + #define VECTOR_H 是一种经典的防止头文件重复包含的技术,确保头文件内容只被编译一次。
分析:
1 .
代码
//1.头文件
//#ifndef VECTOR_H + #define VECTOR_H 是一种经典的防止头文件重复包含的技术,
//确保头文件内容只被编译一次。
#ifndef VECTOR_H
#define VECTOR_Htypedef int ElementType;typedef struct {ElementType *data; // 指向堆空间的数组int size; // 元素的个数int capacity; // 数组的容量
} Vector;// 请实现下面方法// 初始化一个Vector动态数组
Vector *vector_create(void);// 销毁一个Vector动态数组,释放内存。
void vector_destroy(Vector *v);// 向动态数组末尾添加一个元素
void vector_push_back(Vector *v, ElementType val);// 在动态数组最前面添加元素,所有元素依次后移
void vector_push_front(Vector *v, ElementType val);// 将元素val添加到索引为idx的位置,idx后面的元素依次后移
void vector_insert(Vector *v, int idx, ElementType val);// 遍历打印整个Vector动态数组
void vector_print(Vector *v);#endif // !VECTOR_H
//2.实现源文件代码
#include "vector.h"
#include <stdio.h>
#include <stdlib.h>#define DEFAULT_CAPACITY 8
#define THRESHOLD 1024// 在C语言中,static修饰函数表示此函数仅在当前文件内部生效
// 类似于C++或Java中的访问权限修饰符private
static void vector_resize(Vector *v) {// 只要调用这个函数肯定就是需要扩容的int old_capacity = v->capacity;int new_capacity = (old_capacity < THRESHOLD) ?(old_capacity << 1) : // 容量还未超出阈值每次扩容2倍(old_capacity + (old_capacity >> 1)); // 容量超出阈值每次扩容1.5倍// 利用realloc重新分配动态数组// realloc惯用法ElementType *tmp = realloc(v->data, new_capacity * sizeof(ElementType)); if (tmp == NULL) {printf("realloc failed in resize_vector.\n");exit(1); // 扩容失败,退出整个程序。或者也可以做别的处理}// 扩容成功,重新赋值Vector成员v->data = tmp;v->capacity = new_capacity;
}// 初始化一个Vector动态数组
Vector *vector_create(void) {// 先在堆上申请结构体Vector *v = calloc(1, sizeof(Vector));if (v == NULL) {printf("calloc failed in vector_create.\n");return NULL; // 创建失败返回空指针}// 申请动态数组,并初始化Vector的data成员v->data = calloc(DEFAULT_CAPACITY, sizeof(ElementType));if (v->data == NULL) {printf("malloc failed in vector_create.\n");// 不要忘记free结构体Vector,否则会导致内存泄漏free(v);return NULL; // 创建失败返回空指针}// 继续初始化Vector的其它成员v->capacity = DEFAULT_CAPACITY;return v;
}// 销毁一个Vector动态数组,释放内存。
void vector_destroy(Vector *v) {free(v->data);free(v);
}// 向动态数组末尾添加一个元素
void vector_push_back(Vector *v, ElementType val) {// 先判断是否需要扩容if (v->capacity == v->size) {vector_resize(v);}// 扩容完成后或不需要扩容,即向末尾添加元素v->data[v->size] = val;v->size++;
}// 在动态数组最前面添加元素,所有元素依次后移
void vector_push_front(Vector *v, ElementType val) {// 先判断是否需要扩容if (v->capacity == v->size) {vector_resize(v);}// 扩容完成后或不需要扩容,即从首元素开始将所有元素向后移动// 倒着遍历数组方便向后移动元素for (int i = v->size - 1; i >= 0; i--) {v->data[i + 1] = v->data[i];}// 新增的元素成为首元素v->data[0] = val;v->size++;
}// 将元素val添加到索引为idx的位置,idx后面的元素依次后移
void vector_insert(Vector *v, int idx, ElementType val) {// 先做参数校验,避免传入非法索引if (idx < 0 || idx > v->size) { // 做插入操作时索引合法范围是[0, size]printf("Illegal argument: idx = %d, size = %d\n", idx, v->size);exit(1); // 直接退出进程,也可以用别的方式进行错误处理}// 判断是否需要扩容if (v->capacity == v->size) {vector_resize(v);}// 扩容完成后或不需要扩容,即从原本的idx元素开始将所有元素向后移动for (int i = v->size - 1; i >= idx; i--) {v->data[i + 1] = v->data[i];}// idx位置空出来,将它放进去v->data[idx] = val;v->size++;
}// 遍历打印整个Vector动态数组
void vector_print(Vector *v) {printf("[");for (int i = 0; i < v->size; i++){printf("%d, ", v->data[i]);}printf("\b\b]\n");
}
//测试用例代码
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include "vector.h"#define N 100
int main(void) {Vector *v = vector_create();if (v == NULL) {printf("error: vector_create failed in main.\n");exit(1);}// 测试自动扩容机制for (int i = 0; i < N; ++i) {vector_push_back(v, i + 1);}vector_print(v); // 期望打印结果: 1-100// 测试头部插入新元素vector_push_front(v, 0);vector_print(v); // 期望打印结果: 0, 1-100// 测试根据索引插入新元素vector_insert(v, 0, -1);vector_print(v); // 期望打印结果: -1, 0, 1-100vector_destroy(v);return 0;
}
解决方案总结:
: