题目:
动手自己实现动态数组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_H
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);
#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-100
vector_destroy(v);
return 0;
}
解决方案总结:
: