CExercise_10_1动态数组Vector

题目:

动手自己实现动态数组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;
}

在这里插入图片描述


解决方案总结:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值