2.2_顺序表

一. 顺序表概念

一言蔽之: 顺序结构的线性表/ 线性表的顺序结构
1. 特点
  1. 元素集中存储
  2. 首元素地址, 即顺序表首地址, 亦即底层数组地址
  3. 基于数组实现
    在这里插入图片描述

二. 顺序表实现

基于数组实现 ~ (顺序表集中存储的物理结构和数组数据类型完全一致)

  • 存储结构
    • 底层动态数组
    • len + cap 实时记录长度 + 容量
struct Table {
    int *head;
    int len;
    int cap;
};

typedef struct Table {
    int *head;
    int len;
    int cap;
} table;

typedef struct {
    int *head;  //底层动态数组
    int len;    //长度
    int cap;    //容量
} Table;

三. 创建顺序表

  • 即初始化顺序表
    • 底层动态数组初始化
    • len + cap 初始化
Table initTab(cap) {
    Table tab;
    tab.head = malloc(cap * sizeof(int));   //底层动态数组分配内存
    tab.len = 0;    //长度
    tab.cap = cap;  //容量

    return tab;
}

四. 操作 = 查找 + 修改

  • 查找

查找算法: 顺序查找/ 二分查找/ 插值/ 斐波那契/ etc. 基于时空复杂度择优选择

int getEle(Table tab, int ele) {
    for (int i = 0; i < tab.len; ++i) { //查找算法: 顺序查找 etc.
        if (tab.head[i] == ele) {
            return i;
        }
    }

    return -1;
}
  • 修改

1. 修改元素值: 调用查找算法定位并修改

Table updateEle(Table tab, int ele, int newEle) {
    tab.head[getEle(tab, ele)] = newEle;    //修改元素值
    return tab;
}

2. 修改表结构(增/ 删元素)

  • 插入元素
  1. 表头插入
  2. 中间
  3. 尾追加
Table insertEle(Table tab, int i, int ele) {
    for (int j = tab.len - 1; j >= i; j--) {    //元素移民
        tab.head[j + 1] = tab.head[j];
    }
    tab.head[i] = ele;  //插入
    tab.len++;

    return tab;
}
  • 删除元素
  1. 表头删除
  2. 中间
  3. 表尾
Table delEle(Table tab, int ele) {
    for (int i = getEle(tab, ele) + 1; i < tab.len; ++i) {  //覆盖删除
        tab.head[i - 1] = tab.head[i];
    }
    tab.len--;

    return tab;
    /*
     覆盖删除
        1. 元素从顺序表而不是底层数组删除, 通过底层数组仍可访问
     */
}

六. 完整程序

代码

#include <stdio.h>
#include <stdlib.h>

//顺序表物理结构
typedef struct {
    int *head;  //底层动态数组
    int len;    //长度
    int cap;    //容量
} Table;

//初始化顺序表
Table initTab(int cap) {
    Table tab;
    tab.head = malloc(cap * sizeof(int));   //底层动态数组分配内存
    if (!tab.head) {
        printf("底层数组初始化失败!\n");
        /*
         可能因素
            1. 申请内存过大
         */
    } else {
        tab.len = 0;    //长度
        tab.cap = cap;  //容量
    }

    return tab;
}

/*
操作
    1. 查找
    2. 修改
        1. 修改元素值
        2. 修改表结构
            1. 插入元素
            2. 删除元素
*/
//1. 查找
int getEle(Table tab, int ele) {
    for (int i = 0; i < tab.len; i++) {   //查找算法: 顺序查找 etc.
        if (tab.head[i] == ele) {
            return i;
        }
    }
    return -1;
}

//2.1 修改/ 更新元素值
Table updateEle(Table tab, int ele, int newEle) {
    int i = getEle(tab, ele);
    if (i == -1) {
        printf("元素 %d 不存在\n", ele);
        return tab;
    }

    tab.head[i] = newEle;   //更新
    return tab;
}

//2.2.1 插入元素
Table insertEle(Table tab, int i, int ele) {
    if (i < 0 || tab.len < i) {
        printf("插入元素索引%d异常\n", i);
        return tab;
    } else if (tab.cap <= i) {
        tab.head = realloc(tab.head, (tab.cap + 2) * sizeof(int));    //扩容算法
        if (!tab.head) {
            printf("底层数组扩容失败!\n");
            return tab;
        }

        tab.cap *= 2;
    }

    for (int j = tab.len; j > i; j--) {    //元素移民
        tab.head[j] = tab.head[j - 1];
    }
    tab.head[i] = ele;  //插入
    tab.len++;
    return tab;
}

//2.2.2 删除元素
Table delEle(Table tab, int ele) {
    int i = getEle(tab, ele);
    if (i == -1) {
        printf("待删除元素 %d 不存在\n", ele);
        return tab;
    }

    for (int j = i; j < tab.len - 1; j++) {   //元素移民: 覆盖删除
        tab.head[j] = tab.head[j + 1];
    }
    tab.len--;
    return tab;
}

测试

void day02() {
    Table tab = initTab(10);
    for (int i = 0; i < tab.cap; ++i) {
        tab = insertEle(tab, i, i+1);
    }


    /*查找元素
    printf("%d\n", getEle(tab, -1));
    printf("%d\n", getEle(tab, 3));
    printf("%d\n", getEle(tab, 11));*/

    /*修改/ 更新元素值
    tab = updateEle(tab, 222, 2);
    tab = updateEle(tab, 2, 222);*/

    /*插入元素
    tab = insertEle(tab, -1, 11);
    tab = insertEle(tab, 0, 22);
    tab = insertEle(tab, 3, 33);
    tab = insertEle(tab, 9, 44);
    tab = insertEle(tab, tab.len, 55);*/

    /*tab = delEle(tab, -1);
    tab = delEle(tab, 0);
    tab = delEle(tab, 4);
    tab = delEle(tab, 10);
    tab = delEle(tab, 11);*/

    for (int i = 0; i < tab.len; ++i) {
        printf("tab[%d] = %d\n", i, tab.head[i]);
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值