实现线性表 增删改查 等基本操作
当数据结构是线性结构时,我们可以用顺序表或者是链表实现,此处我们先讨论顺序表的一些基本操作
首先为了便于程序的演示以及说明,我们先定义相应的数据结构如下:
typedef struct Vector {
int size, length; //顺序表的总体大小以及现有长度
int *data; //data指向存储数据数组的首地址
} Vector; //因类似于C++中的vector向量,因此我们以vector为名
一 线性表的初始化以及删除
- 在初始化时,我们首先初始化线性表的大小和长度并以此大小申请内存数组空间
- 删除时操作更简单,直接释放对应的数组空间以及Vector结构体空间
对应代码如下:
#include <iostream>
using namespace std;
typedef struct Vector {
int size, length;
int *data;
} Vector;
void init(Vector *vector, int size) {
vector->size = size;
vector->length = 0;
vector->data = (int*)malloc(sizeof(int) * size);
}
void clear(Vector *vector) {
free(vector->data);
free(vector);
}
int main() {
Vector *a = (Vector *)malloc(sizeof(Vector));
init(a, 100); //这里我们先初始化线性表的大小为100
clear(a);
return 0;
}
二 线性表的插入及扩容操作
在插入元素时需要提前进行两方面的预判
- 当前插入元素的位置是否合法?
- 顺序表是否已满?若已满,此时需要先进性扩容操作,增大顺序表的大小
此外 需要注意的是:应从后向前逐步将元素后移,顺序不可颠倒,否则将覆盖有效数字,破坏顺序表
对应代码如下:
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);
}
bool insert(Vector *vector, int loc, int value) { //将数字value插入顺序表的第value号位置 (下标从0开始)
if (loc < 0 || loc > vector->length) return false; //插入位置非法,返回false,插入失败
if (vector->length >= vector->size) expand(vector); //若顺序表已满,执行扩容操作
for (int i = vector->length; i > loc; i--)
vector->data[i + 1] = vector->data[i];
vector->data[loc] = value;
vector->length++;
return true;
}
代码说明:
- 在插入元素时,可以在顺序表的最前最后或者中间位置插入,所以合法的 location ∈\in∈ [0, vector->length]
- 当vector->length == vector->size时,顺序表满;扩容时,先暂存元顺序表数组首地址,之后申请一片新的大小为原来两倍的数组空间,将原来的元素依次复制过来即可,vector->size更新为原来的两倍。
- 设将要插入的位置为iii,顺序表的长度为nnn,则原来第 iii 号到最后的第 n−1n-1n−1号元素都要向后移动一个单位。
总共有n + 1个位置可以插入,每个位置插入元素的可能性相同均为1n+1{\frac{1} {n + 1}}n+11,在第iii位插入元素,需要移动元素的次数为n−in - in−i,因此插入一个元素,需要移动元素的次数为:1n+1∗∑i=0ni{\frac{1} {n + 1}} * {\sum_{i = 0}^{n}} in+11∗∑i=0ni = 1n+1{\frac{1} {n + 1}}n+11 * n(n+1)2{\frac{n(n + 1)}{2}}2n(n+1) = n2\frac{n} {2}2n
换句话说,插入一个元素,平均下来需要移动一半元素 !
三 线性表的查找以及删除操作
线性表中元素的查找,直接遍历顺序表即可,若当前元素等于要查找的元素值,返回元素对应下标。
删除元素时,输入元素在顺序表中的下标,删除对应位置元素即可。由此可见元素的查找以及删除操作一般是配套使用的。
对应代码如下:
//删除loc处的元素
bool delete_node(Vector *vector, int loc) {
if (loc < 0 || loc >= vector->length) return false;
for (int i = loc; i < vector->length - 1; i--)
vector->data[i] = vector->data[i + 1];
vector->length--;
return true;
}
//找到值为value元素的位置
int search(Vector *vector, int value) {
for (int i = 0; i < vector->length; i++) {
if (vector->data[i] == value) return i;
}
return -1;
}
代码说明:
- 删除元素之前同样要判断删除元素的位置是否合法,删除元素所处的合法位置 loc ∈\in∈ [0, vector->length - 1]
- 设将要删除的位置为iii,顺序表的长度为nnn,则原来第 i+1i + 1i+1 号到最后的第 n−1n-1n−1号元素都要向前移动一个单位。
总共有nnn个位置可以删除,每个位置删除元素的可能性相同均为1n{\frac{1} {n}}n1,删除第iii位元素,需要移动元素的次数为n−i−1n - i - 1n−i−1,因此插入一个元素,需要移动元素的次数为:1n∗∑i=0n−1i{\frac{1} {n}} * {\sum_{i = 0}^{n - 1}} in1∗∑i=0n−1i = 1n{\frac{1} {n}}n1 * n(n−1)2{\frac{n(n - 1)}{2}}2n(n−1) = n−12\frac{n - 1} {2}2n−1
同样,换句话说,删除一个元素,平均下来也需要移动一半元素 !
四 线性表的遍历输出
线性表的线性输出比较简单,直接展示代码如下:
//打印输出顺序表中的元素,行末不要输出多余的空格
void print(Vector *vector) {
for (int i = 0; i < vector->length; i++) {
if (i) printf(" ");
printf("%d", vector->data[i]);
}
printf("\n");
}
五 线性表基本操作练习题
题意如下:

对应实现代码如下:
#include <iostream>
using namespace std;
//顺序表结构体
typedef struct Vector {
int length, size; //顺序表的长度以及大小
int *data; //指向数组的指针
}Vector;
//顺序表的初始化以及删除
void init(Vector *vector, int init_size) {
vector->length = 0;
vector->size = init_size;
vector->data = (int *)malloc(sizeof(int) * init_size);
}
void clear(Vector *vector) {
free(vector->data);
free(vector);
}
//插入操作以及顺序表的扩建
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);
}
bool insert(Vector *vector, int loc, int value) {
if (loc < 0 || loc > vector->length) return false;
if (vector->length >= vector->size) expand(vector);
for (int i = vector->length; i > loc; i--)
vector->data[i + 1] = vector->data[i];
vector->data[loc] = value;
vector->length++;
return true;
}
//删除loc处的元素
bool delete_node(Vector *vector, int loc) {
if (loc < 0 || loc >= vector->length) return false;
for (int i = loc; i < vector->length - 1; i--)
vector->data[i] = vector->data[i + 1];
vector->length--;
return true;
}
//找到值为value元素的位置
int search(Vector *vector, int value) {
for (int i = 0; i < vector->length; i++) {
if (vector->data[i] == value) return i;
}
return -1;
}
//打印输出顺序表中的元素
void print(Vector *vector) {
for (int i = 0; i < vector->length; i++) {
if (i) printf(" ");
printf("%d", vector->data[i]);
}
printf("\n");
}
int main() {
Vector *a = (Vector *)malloc(sizeof(Vector));
init(a, 20);
int m = 0;
scanf("%d", &m);
while (m--) {
int t;
scanf("%d", &t);
switch(t) {
case 1: {
int loc, value;
scanf("%d %d", &loc, &value);
if (insert(a, loc, value)) printf("insert success\n");
else printf("insert failed\n");
break;
}
case 2: {
int loc;
scanf("%d", &loc);
if (delete_node(a, loc)) printf("delete success\n");
else printf("delete failed\n");
break;
}
case 3: {
int value;
scanf("%d", &value);
int index = search(a, value);
if (index + 1) printf("find success, index = %d\n", index);
else printf("find failed\n");
break;
}
case 4: {
print(a);
break;
}
default: {
printf("something wrong\n");
}
}
}
clear(a);
return 0;
}
/* 对应输入输出
9
1 0 1
insert success
1 5 2
insert failed
1 1 2
insert success
1 2 3
insert success
3 2
find success, index = 1
2 2
delete success
2 9
delete failed
3 3
find failed
4
1 2
*/
加油! 路漫漫其修远兮,吾将上下而求索!
最后,对于这次的武汉肺炎,希望科学家们早点找到新型冠状病毒的疫苗,天佑中华,天佑武汉!! 祈祷!!
本文详细介绍了线性表的基本操作,包括初始化、删除、插入、查找、删除和遍历输出。通过具体代码示例,解释了如何使用顺序表实现这些操作,并分析了插入和删除操作的平均效率。
1543

被折叠的 条评论
为什么被折叠?



