顺序表在算法中的应用
1. Basic situation
1.1 Sample code
//
// Created by 16624 on 2022/9/26.
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_OP 20
/**
* @def 创建顺序表的数据结构
* @Crition0502
* @date 2022.9.26
*/
typedef struct vector{
int size;
int length;
int *data; // 连续的存储区
} Vector;
/**
* @def 初始化存储n个元素的顺序表
* @param n
* @return vec 分配好空间的顺序表的地址
*/
Vector *init(int n){
// 开拓顺序表
Vector *vec = (Vector *)malloc(sizeof(Vector));
// 给顺序表开辟存储n个整数的存储空间
vec->data = (int *)malloc(sizeof(int) * n);
// 初始化顺序表的长度size以及当前存储的数据的数目length
vec->size = n;
vec->length = 0;
return vec;
}
/**
* @def 进行数据表的销毁
* @param vec
*/
void Clear(Vector * vec){
// 传入顺序表为空
if(vec == NULL){
return ;
}
// 不为空,进入顺序表的销毁
free(vec->data);
free(vec);
return ;
}
/**
* @def 进行顺序表的插入操作
* @param vec
* @param value
* @param index
* @return 0 | 1 0为插入失败,1为插入成功
*/
int Insert(Vector * vec , int value , int index){
// 检测传入的参数是否合法
if(vec == NULL) return 0;
if(vec->length == vec->size) return 0;
if(index < 0 || index > vec->length) return 0;
// 进行插入操作
// A. 不能从前进行往后的移动,因为这样的话会覆盖后面的数据导致出现bug
// for(int i = index ; i < vec->length ; i++){
// vec->data[i + 1] == vec->data[i];
// }
// B. 应该从后往前直到index位进行向后的移动操作
for(int i = vec->length ; i > index ; i--){
vec->data[i] = vec->data[i - 1];
}
vec->data[index] = value;
vec->length += 1; // 记得给数组的当前存储数据的个数加个1哦!
return 1;
}
/**
* @def 进行顺序表的删除操作
* @param vec
* @param index
* @return 0 | 1 0为插入失败,1为插入成功
*/
int Delete(Vector * vec , int index){
// 检测传入的参数是否合法
if(vec == NULL) return 0;
if(vec->length == 0) return 0;
if(index < 0 || index >= vec->length) return 0;
// 进行顺序表的删除操作(循环向前)
for(int i = index + 1 ; i < vec->length ; i++){
vec->data[i - 1] = vec->data[i];
}
vec->length -= 1;
return 1;
}
/**
* @def 遍历顺序表打印出来
* @param vec
*/
void PrintVector(Vector *vec){
printf("Vector(%d) = [" , vec->length);
for(int i = 0 ; i < vec->length ; i++){
if(i != 0) printf(", ");
printf("%d" , vec->data[i]);
}
printf("]\n");
return ;
}
int showMain ()
{
// 生成随机时间种子
srand(time(0));
Vector *vec = init(MAX_OP);
int op , index , value = 0;
for(int i = 0 ; i < MAX_OP ; i++){
op = rand() % 2; // 产生的数字为0 | 1
index = rand() % (vec->length + 1);
value = rand() % 100;
switch(op){
case 0:
printf("Insert %d at %d to vector.\n" , value , index);
Insert(vec , value , index);
break;
case 1:
printf("Erase the value at %d from vector.\n" , index);
Delete(vec , index);
break;
}
PrintVector(vec);
}
return 0;
}
1.2 Disadvantage:
A. 避免了数组的限定长度的缺陷
B. 但还是不能在长度受限的时候进行动态的内存分配
2. Advanced code
2.1 对于内存动态分配进行了增强
//
// Created by 16624 on 2022/9/26.
//
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX_OP 20
/**
* @def 创建顺序表的数据结构
* @Crition0502
* @date 2022.9.26
*/
typedef struct vector{
int size;
int length;
int *data; // 连续的存储区
} Vector;
/**
* @def 初始化存储n个元素的顺序表
* @param n
* @return vec 分配好空间的顺序表的地址
*/
Vector *init(int n){
// 开拓顺序表
Vector *vec = (Vector *)malloc(sizeof(Vector));
// 给顺序表开辟存储n个整数的存储空间
vec->data = (int *)malloc(sizeof(int) * n);
// 初始化顺序表的长度size以及当前存储的数据的数目length
vec->size = n;
vec->length = 0;
return vec;
}
/**
* @def 进行数据表的销毁
* @param vec
*/
void Clear(Vector * vec){
// 传入顺序表为空
if(vec == NULL){
return ;
}
// 不为空,进入顺序表的销毁
free(vec->data);
free(vec);
return ;
}
/**
* @def 拓展顺序表的储存空间
* @param vec
* @return 0 | 1 0为插入失败,1为插入成功
*/
int Expand(Vector * vec){
vec->size *= 2;
vec->data = (int *)realloc(vec->data , sizeof(int) * vec->size);
return 1;
}
/**
* @def 进行顺序表的插入操作
* @param vec
* @param value
* @param index
* @return 0 | 1 0为插入失败,1为插入成功
*/
int Insert(Vector * vec , int value , int index){
// 检测传入的参数是否合法
if(vec == NULL) return 0;
// 扩容操作
if(vec->length == vec->size){
if(!Expand(vec)) return 0;
printf("Expand success! Now the size is %d\n" , vec->size);
}
if(index < 0 || index > vec->length) return 0;
// 进行插入操作
// A. 不能从前进行往后的移动,因为这样的话会覆盖后面的数据导致出现bug
// for(int i = index ; i < vec->length ; i++){
// vec->data[i + 1] == vec->data[i];
// }
// B. 应该从后往前直到index位进行向后的移动操作
for(int i = vec->length ; i > index ; i--){
vec->data[i] = vec->data[i - 1];
}
vec->data[index] = value;
vec->length += 1; // 记得给数组的当前存储数据的个数加个1哦!
return 1;
}
/**
* @def 进行顺序表的删除操作
* @param vec
* @param index
* @return 0 | 1 0为插入失败,1为插入成功
*/
int Delete(Vector * vec , int index){
// 检测传入的参数是否合法
if(vec == NULL) return 0;
if(vec->length == 0){
if(!Expand(vec)) return 0;
printf("Expand success! Now the sie is %d\n" , vec->size);
}
if(index < 0 || index >= vec->length) return 0;
// 进行顺序表的删除操作(循环向前)
for(int i = index + 1 ; i < vec->length ; i++){
vec->data[i - 1] = vec->data[i];
}
vec->length -= 1;
return 1;
}
/**
* @def 遍历顺序表打印出来
* @param vec
*/
void PrintVector(Vector *vec){
printf("Vector(%d) = [" , vec->length);
for(int i = 0 ; i < vec->length ; i++){
if(i != 0) printf(", ");
printf("%d" , vec->data[i]);
}
printf("]\n");
return ;
}
int showMain ()
{
// 生成随机时间种子
srand(time(0));
Vector *vec = init(1);
int op , index , value = 0;
for(int i = 0 ; i < MAX_OP ; i++){
op = rand() % 2; // 产生的数字为0 | 1
index = rand() % (vec->length + 1);
value = rand() % 100;
switch(op){
case 0:
printf("Insert %d at %d to vector.\n" , value , index);
Insert(vec , value , index);
break;
case 1:
printf("Erase the value at %d from vector.\n" , index);
Delete(vec , index);
break;
}
PrintVector(vec);
}
return 0;
}
--------------------------------------------------------------------------
Output:
Insert 77 at 0 to vector.
Vector(1) = [77]
Erase the value at 0 from vector.
Vector(0) = []
Insert 75 at 0 to vector.
Vector(1) = [75]
Insert 88 at 1 to vector.
Expand success! Now the size is 2
Vector(2) = [75, 88]
Insert 63 at 0 to vector.
Expand success! Now the size is 4
Vector(3) = [63, 75, 88]
Erase the value at 0 from vector.
Vector(2) = [75, 88]
Erase the value at 1 from vector.
Vector(1) = [75]
Insert 28 at 0 to vector.
Vector(2) = [28, 75]
Erase the value at 2 from vector.
Vector(2) = [28, 75]
Erase the value at 0 from vector.
Vector(1) = [75]
Insert 4 at 0 to vector.
Vector(2) = [4, 75]
Insert 2 at 0 to vector.
Vector(3) = [2, 4, 75]
Insert 7 at 3 to vector.
Vector(4) = [2, 4, 75, 7]
Erase the value at 2 from vector.
Vector(3) = [2, 4, 7]
Insert 80 at 2 to vector.
Vector(4) = [2, 4, 80, 7]
Erase the value at 0 from vector.
Vector(3) = [4, 80, 7]
Insert 31 at 1 to vector.
Vector(4) = [4, 31, 80, 7]
Insert 93 at 0 to vector.
Expand success! Now the size is 8
Vector(5) = [93, 4, 31, 80, 7]
Erase the value at 1 from vector.
Vector(4) = [93, 31, 80, 7]
Insert 37 at 2 to vector.
Vector(5) = [93, 31, 37, 80, 7]
进程已结束,退出代码0
2.2 但是内存分配的时候仍会出现内存泄漏的问题
改写了Expand函数的分配内存的逻辑关系
int Expand(Vector * vec){
int new_size = vec->size * 2;
int *p = (int *)realloc(vec->data , sizeof(int) * new_size);
if(p == NULL){
return 0;
}else{
vec->size = new_size;
vec->data = p;
return 1;
}
}
The end