线性表实现增删改查等基本操作

实现线性表 增删改查 等基本操作

当数据结构是线性结构时,我们可以用顺序表或者是链表实现,此处我们先讨论顺序表的一些基本操作

首先为了便于程序的演示以及说明,我们先定义相应的数据结构如下:

typedef struct Vector {
    int size, length;    //顺序表的总体大小以及现有长度
    int *data;				   //data指向存储数据数组的首地址
} Vector;					  //因类似于C++中的vector向量,因此我们以vector为名

一 线性表的初始化以及删除

  1. 在初始化时,我们首先初始化线性表的大小和长度并以此大小申请内存数组空间
  2. 删除时操作更简单,直接释放对应的数组空间以及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;
}

二 线性表的插入及扩容操作

在插入元素时需要提前进行两方面的预判

  1. 当前插入元素的位置是否合法?
  2. 顺序表是否已满?若已满,此时需要先进性扩容操作,增大顺序表的大小

此外 需要注意的是:应从后向前逐步将元素后移,顺序不可颠倒,否则将覆盖有效数字,破坏顺序表
对应代码如下:

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;
}

代码说明:

  1. 在插入元素时,可以在顺序表的最前最后或者中间位置插入,所以合法的 location ∈ \in [0, vector->length]
  2. 当vector->length == vector->size时,顺序表满;扩容时,先暂存元顺序表数组首地址,之后申请一片新的大小为原来两倍的数组空间,将原来的元素依次复制过来即可,vector->size更新为原来的两倍。
  3. 设将要插入的位置为 i i i,顺序表的长度为 n n n,则原来第 i i i 号到最后的第 n − 1 n-1 n1号元素都要向后移动一个单位。
    总共有n + 1个位置可以插入,每个位置插入元素的可能性相同均为 1 n + 1 {\frac{1} {n + 1}} n+11,在第 i i i位插入元素,需要移动元素的次数为 n − i n - i ni,因此插入一个元素,需要移动元素的次数为: 1 n + 1 ∗ ∑ i = 0 n i {\frac{1} {n + 1}} * {\sum_{i = 0}^{n}} i n+11i=0ni = 1 n + 1 {\frac{1} {n + 1}} n+11 * n ( n + 1 ) 2 {\frac{n(n + 1)}{2}} 2n(n+1) = n 2 \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;
}

代码说明:

  1. 删除元素之前同样要判断删除元素的位置是否合法,删除元素所处的合法位置 loc ∈ \in [0, vector->length - 1]
  2. 设将要删除的位置为 i i i,顺序表的长度为 n n n,则原来第 i + 1 i + 1 i+1 号到最后的第 n − 1 n-1 n1号元素都要向前移动一个单位。
    总共有 n n n个位置可以删除,每个位置删除元素的可能性相同均为 1 n {\frac{1} {n}} n1,删除第 i i i位元素,需要移动元素的次数为 n − i − 1 n - i - 1 ni1,因此插入一个元素,需要移动元素的次数为: 1 n ∗ ∑ i = 0 n − 1 i {\frac{1} {n}} * {\sum_{i = 0}^{n - 1}} i n1i=0n1i = 1 n {\frac{1} {n}} n1 * n ( n − 1 ) 2 {\frac{n(n - 1)}{2}} 2n(n1) = n − 1 2 \frac{n - 1} {2} 2n1
    同样,换句话说,删除一个元素,平均下来也需要移动一半元素 !

四 线性表的遍历输出

线性表的线性输出比较简单,直接展示代码如下:

//打印输出顺序表中的元素,行末不要输出多余的空格
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
*/

加油! 路漫漫其修远兮,吾将上下而求索!

最后,对于这次的武汉肺炎,希望科学家们早点找到新型冠状病毒的疫苗,天佑中华,天佑武汉!! 祈祷!!

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值