线性表
线性表是由相同数据类型的n 个数据元素a0,a l…an-1组成的有限序列。一个数据元素可以由若干个数据项组成。若用工命名线性表,则其一般表示如下:
其中,an是唯一的“第一个”数据元素,又称为表头元素;an-1是唯一的“最后一个”数据元素,又称为表尾元素。线性表按照存储结构,可以分为顺序表和链表两种类型。
1. 结构声明
size: 顺序表容量 length: 顺序表当前元素个数
#define ERROR 0
#define OK 1
typedef struct Vector {
int size,length;
int *data;
} Vector;
2. 初始化
为数据域分配空间,并且初始化size和length
void init(Vector *vector, int size){
vector->data = (int *)malloc(sizeof(int) * size);
vector->length = 0;
vector->size = size;
}
3. 扩容
由于数据域的长度是有限的的,当超出相应的容量size后,需要进行动态扩容
默认扩容为原来容量的两倍
void expand(Vector *vector){
int *old_data = vector->data; //动态扩容需要保留原来的数据
vector->size *= 2;
vector->data = (int *)malloc(sizeof(int) * vector->size); //重新分配内存空间
for (int i = 0; i < vector->length; i++) {
vector->data[i] = old_data[i];
}
free(old_data);
}
注意:
- 这里不建议重新在创建一个顺序表,而是直接重新分配一个新的 data域(数据域),因为每一次的重新申请都会有系统开销。
- old_data指向原顺序表的数据域。在我们进行数据的转移后。我们需要手动释放掉这块内存,避免造成内存泄漏(memory leak)。
4. 插入
在插入的时候我们需要判断插入位置的合法性以及当前空间是否充足两个边界条件
int insert(Vector *vector, int loc , int value) {
if (loc < 0 || loc > vector->length) return ERROR; //插入位置合法性
if (vector->length >= vector->size) expand(vector); //空间是否充足
for (int i = vector->length; i > loc; i--) {
vector->data[i] = vector->data[i - 1]; //依次向后移动,将待插入的位置空出。
}
vector->data[loc] = value;
vector->length++;
return OK;
}
5. 查找
传入要查找的值,返回相应的位序
int research(Vector *vector,int value) {
for (int i = 0; i < vector->length; i++) {
if (vector->data[i] == value) return i;
}
return -1;
}
6. 删除
传入要删除节点的位序
int delete_node(Vector *vector, int loc) {
if (loc < 0 || loc >= vector->length) return ERROR;
for (int i = loc + 1; i < vector->length; i++)
vector->data[i - 1] = vector->data[i]; //依次往前覆盖
vector->length--;
return OK;
}
7. 销毁(置空)
释放数据域和整个结构体
void destroy(Vector *vector) {
free(vector->data);
free(vector);
}