数据结构--线性表详解(一)

2023-11-11

这里写链接内容1、前言
线性表是最常用且是最简单的一种数据结构。形如:A1、A2、A3….An这样含有有限的数据序列,我们就称之为线性表。

2、线性表的两种表示形式

  1. 顺序表示(其实就是数组)
  2. 链表表示

3、线性表一般操作的介绍
线性表一般包含如下几种操作:

线性表的操作包括如下几种
  (1) InitList(& L)
        //构造一个空的线性表 
  (2) DestroyList(& L)
       //线性表存在了,消耗一个线性表
  (3) ClearList(&L )
       //清空线性表中的内容
  (4) ListEmpty(L)
       //判断线性表是否为空
  (5) ListLength(L)
        //返回线性表的长度
  (6) GetElem(L,i,& e)
        //返回线性表i位置上的元素值,通过e返回     
  (7) PriorElem(L,cur_e,&pre_e)
       //如果cur_e是线性表中的元素,而且不是第一个,那么我们就可以返回该元素前一个元素的值
  (8) NextElem(L,cur_e,&next_e)
       //如果cur_e是线性表中的元素,而且不是最后一个,就返回它下一个元素的值
  (9) Listinsert(&L,i,e)
        //如果线性表存在了,而且i符合条件,则在i位置插入一个元素
  (10)ListDelete(&L,i//删除i位置上的元素
 (11) ListDelete_data(&L,e,order)
      //删除指定的元素e,order决定是删除一个,还是全部。
 (12) Connect_two_List(L_a,L_b,& L_c)
      //连接两个线性表,除去重复的内容    
 (13)print(L)
       //打印线性表    

/如果不想看线性结构的读者,可以直接跳到下一篇博客看链式结构的线性表实现的操作/

4、线性表的顺序表示实现–表示的格式
我们在之后的那些操作的实现中,我们都是一直使用这些内容,作为我们通过线性表顺序结构表示实现线性表操作的一些基础。

//扩充容量的步伐
#define  sizestep 10
//开始的容量的大小
#define startsize 100

//为了便于扩展,我们这里使用类型别名,
//我们使用最简单的int型作为一个范例

typedef int Elemtype;
struct List {
    //数据
    Elemtype * data;
    //长度
    int length;
    //初始容量
    int size;
};

5、线性表顺序表示实现–initList函数
因为顺序表示就是对数组进行一些操作,我们在第四点已经给出了我们顺序表示线性表的一个结构体,我们要创建一个空表(没有元素的表),我们就是让表的长度为0,另外,还要对data进行堆内存的分配和初始容量的初始化。


//创建一个空的线性表
void InitList(List & newList) {
    //初始容量为startsize
    newList.size = startsize;
    //首先开辟空间
    newList.data = new Elemtype[newList.size];
    //空表,长度是0
    newList.length = 0;

}

6、线性表顺序表示实现–DestroyList函数

//线性表存在了,现在要销毁线性表
void DestroyList(List & newList) {
    newList.length = 0;
    newList.data = 0;
    //一定要先释放堆内存
    delete[] newList.data;
    //没此释放堆内存后,并将对应的指针赋予NULL是一个良好的习惯
    newList.data = NULL;
}

7、线性表顺序表示实现–ClearList函数

//线性表存在了,但是现在想清空整个线性表
void ClearList(List & newList) {
    newList.length = 0;
    //一定要先释放堆内存
    delete[] newList.data;
    //没此释放堆内存后,并将对应的指针赋予NULL是一个良好的习惯
    newList.data = NULL;
    //重新为存放元素的变量开辟一个新的堆内存
    newList.data = new Elemtype[newList.size];

}

8、线性表顺序表示实现–ListEmpty函数

//判读线性表是否为空
bool ListEmpty(List newList) {
    return newList.length;
}

9、线性表顺序表示实现–ListLength函数


//返回线性表的长度
int ListLength(List newList) {
    return newList.length;
}

10、线性表顺序表示实现–GetElem函数

//返回线性表上某个位置上的元素的值,记住我们的位置是从1开始计算的。
void GetElem(List newList, int i, Elemtype &e) {
    if (ListEmpty(newList)) {
        cout << "当前线性表是空表" << endl;
        return;
    }
    if (i<1 || i>newList.length) {
        cout << "当前位置超出了线性表的范围" << endl;
        return;
    }
    e = newList.data[i - 1];
}

我们需要考虑这个函数的时间复杂度:因为我们是通过下标进行查找对应的元素的,所以它是时间复杂度为:O(1),这个和我们后边说的链式结构的查找比起来,是占了很大优势的

11、线性表顺序表示实现–PriorElem函数
我们在执行这个函数的第一步就是判断我们的那个元素在不在线性表中且不是第一个元素,这样我们就可以直接返回该元素的前一个元素的值。


//判读元素的位置的函数
//我们这里直接返回该元素的下标
int LocationElem(List newList, Elemtype e){
    int i;
    for (i = 0; i < newList.length; i++) {
        if (newList.data[i] == e) {
            return i;
        }
    }
    return -1;
}
这个函数的时间复杂为:假定我们有n个元素,那么它的查找时间复杂为O(n),但是因为我们使用的是顺序结构,所以我们可以很方便的使用其他可以减低时间复杂的查找算法,例如二分查找,它的时间复杂度为:O(logn)

//获取前驱的元素
void PriorElem(List newList, Elemtype cur_e, Elemtype & pre_e) {
    int location = 0;
    location = LocationElem(newList, cur_e);
    //如果Location是-1,说明cur_e不在线性表中
    if (location == -1) {
        cout <<cur_e<< "不在线性表中" << endl;
        return;
    }
    //如果Location是0,说明cur_e在线性表第一个位置,没有前一个元素
    if (location == 0)
    {
        cout << cur_e << "是线性表的第一个元素,没有前驱" << endl;
        return;
    }
    pre_e = newList.data[location - 1];
}

这个函数的时间复杂主要是受LocationElem函数的影响,
12、线性表顺序表示实现–NextElem函数
这个函数和前面的函数是一样的,我们只要修改一个位置的参数就可以了,那就是判断第一个元素的变为判断最后一个元素

//获取后驱元素
void NextElem(List newList, Elemtype cur_e, Elemtype & next_e) {
    int location = 0;
    location = LocationElem(newList, cur_e);
    //如果Location是-1,说明cur_e不在线性表中
    if (location == -1) {
        cout << cur_e << "不在线性表中" << endl;
        return;
    }
    //如果Location是0,说明cur_e在线性表最后一个位置,没有后一个元素
    if (location == newList.length-1)
    {
        cout << cur_e << "是线性表的最后一个元素,没有后驱" << endl;
        return;
    }
    next_e = newList.data[location - 1];
}

这个函数的时间复杂为
13、线性表顺序表示实现–Listinsert函数

//向线性表中插入一个元素,这里我们需要判断插入位置是否合法
//除此之外,我们还需要检测元素的容量是否已经到达了最大值
void Listinsert(List & newList, int i, Elemtype e) {
    //插入的位置不合法
    if (i<1 || i>newList.length+1) {
        cout << "请检查插入位置是否正确" << endl;
        return;
    }
    int j = 0;
    //此时达到了线性表的最大容量,我们需要重新为线性表分配新的内存。
    if (newList.length == newList.size) {
        //先保存之前的内容。
        Elemtype * p =new Elemtype[newList.length];
        for (j = 0; j < newList.length; j++) {
            p[j] = newList.data[j];
        }
        //扩大容量
        newList.size += sizestep;
        delete[] newList.data;
        //重新分配内存
        newList.data = new Elemtype[newList.size];
        //恢复之前内容
        for (j = 0; j < newList.length; j++) {
            newList.data[j] = p[j];
        }
    }
    //插入内容
    for (int k = newList.length; k >i-1; k-- ){
        newList.data[k]=newList.data[k-1];
    }
    newList.data[i - 1] = e;
    ++newList.length;
}

线性表的顺序结构表示的时候,它的最大的缺点就是在插入和删除的时候,需要移动大量的元素,此时,我们插入一个元素的时间复杂为:O(n),时间复杂度虽然是线性的,但是由于它需要移动大量的元素,这也就早造成了它的时间效率的比较低的
14、线性表顺序表示实现–Listdelete函数

//线性表删除一个元素,我们需要判断删除的位置是否合法
void Listdelete(List & newList, int i) {
    //删除的位置不合法
    if (i<1 || i>newList.length) {
        cout << "请检查插入位置是否正确" << endl;
        return;
    }
    for (int j = i - 1; j < newList.length; j++) {
        newList.data[j] = newList.data[j + 1];
    }
    --newList.length;
}

线性表的删除和插入是差不多的意思,都是要对数组中的元素进行移动。
15、线性表顺序表示实现–Listdelete_data函数


//按照元素的值,来删除对应元素的内容,
//这个时候我们通过传个参数,来决定我们是删除第一个该元素,
//0,删除一个,1,删除所有
//还是把所有的元素都给删除了
//如果不存在该元素,就直接返回
void Listdelete_data(List & newList, Elemtype e,int order) {
   int flag=0;
    for (int i = 0; i < newList.length; i++) {
        if (newList.data[i] == e) {
            flag=1;
            //删除对应的位置上的元素,而且i也要减少一个
            Listdelete(newList, i + 1);
            --i;
            if (order == 0) {

                return;
            }
        }
    }
    if(flag==1)
    return ;
    cout << e << "不在线性表中" << endl;
}

16、线性表顺序结构表示实现–Connect_two_List函数
当我们要进行两个线性表的链接的时候,我们最好是希望这两个链表是有序的。

//连接两个线性表
void Connect_two_List(List a, List b, List & c) {
    //对c进行一些数据初始化
    c.length = c.size = a.length + b.length;
    c.data = new Elemtype[c.size];

    //这里采用指针的方式进行数据的移动,我们先把a和b数据第一个和最后一个元素的位置找出来
    int i = 0;
    int j = 0;
    int k = 0;

    while (i <= a.length-1 && j<= b.length-1) {
        if (a.data[i] < b.data[j])
        {
            c.data[k++] = a.data[i++];

        }
        else if(a.data[i] > b.data[j]) c.data[k++] = b.data[j++];
        else {
            c.data[k++] = b.data[j++]; i++; --c.length;
        }
    }
    while (i <= a.length - 1)
    {
        c.data[k++] = a.data[i++];
    }
    while (j <= b.length - 1)
    {
        c.data[k++] = b.data[j++];
    }
}

我们通过分析我们连接函数的代码,我们可以发现,我们将两个元素组合在一起的时候的时间复杂为O(a.lenght+b.lenght).

17、线性表顺序结构表示实现–print函数

void print(List & L) {
    for (int i = 0; i < L.length; i++) {
        cout << L.data[i] << " ";
    }
    cout << endl;
}

到这里,线性表顺序结构表示的实现方式已经全部完成,其中会有一点点小错误,希望大家可以指出来,让我去修正,我也把源代码上传到了,下载地址为:点击这里下载

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

数据结构--线性表详解(一) 的相关文章

随机推荐

  • 关于代码评审

    代码评审实际是编写代码的开发人员在被复查 它是最小化缺陷的有效方法 无论公司实行代码评审的额外动机是什么 代码评审都是工业化的最优方法 一 代码评审目的 1 确保要发布质量可靠的代码 代码评审能非常有效地发现所有类型的错误 包括那些由于不正
  • Java基础三

    表达式自动提升类型 在程序中出现直接写出来的数字 如果是整数默认类型为int 如果为小数默认类型为double 一个表达式中包含多种数据类型时 结果的数据类型会自动提升 规则如下 byte short char 自动提升为int 整个表达式
  • selenium 二维码登陆解决方案

    selenium与api 的结合 获取到 qr id 然后api 带这个qr id 调用 然后就ok了 实现方式看代码 coding utf 8 auth cy create 11 27 18 update from time import
  • 告别if else!试试这款轻量级流程引擎吧,跟SpringBoot绝配!

    之前同事用了一款轻量级的规则引擎脚本AviatorScript 我也跟着用了起来 真的挺香 能少写很多代码 这期就给大家介绍一下这款规则引擎 简介 AviatorScript是一门高性能 轻量级寄宿于 JVM 包括 Android 平台 之
  • Mysql实现局域网访问

    Mysql实现局域网访问 文章目录 Mysql实现局域网访问 找到MYSQL数据库中的User表 找到自己账号的那条数据 将Localhost 改为 号 代表所有ip都可以访问 Localhost代表只有自己可以访问 这样就实现了局域网访问
  • 详解Mysql主键

    主键 对于关系表 有个很重要的约束 就是任意两条记录不能重复 不能重复不是指两条记录不完全相同 而是指能够通过某个字段唯一区分出不同的记录 这个字段被称为主键 对主键的要求 最关键的一点是 记录一旦插入到表中 主键最好不要再修改 因为主键是
  • Schedulis 普通版环境部署

    Schedulis 普通版环境部署 一 使用前置 请基于 Linux 操作系统操作 建议 CentOS 创建新用户 hadoop 并为该用户赋予 root 权限 用于部署schedulis 准备好 MySQL 版本5 5 的客户端和服务端
  • String s = new String("abc");产生了几个对象?

    对于这个问题 老套路先上代码 public class StringTest public static void main String args String s1 Hello String s2 Hello String s3 new
  • ZooKeeper在Spark的使用

    摘抄一段 ZooKeeper 官网的一句话 大意就是 ZooKeeper 为分布式应用提供了高效可靠的分布式协调服务 提供了统一命名服务 配置管理和分布式锁等分布式的基础服务 ZooKeeper is a centralized servi
  • 数据结构实验6:二叉树的遍历,深度计算,度为1的个数

    题目 1 实现二叉树前序 中序 后序遍历的递归算法 2 计算二叉树的深度 递归和非递归算法 3 统计二叉树度为1的节点个数 递归和非递归算法
  • JS使用及mysql 查询语句

    目录 1 javascript的使用方式1 2 js的使用方式2 3 js中定义变量以及数据类型划分 4 Js之运算符 5 js之流程控制语句 6 js事件编程的三要素 7 javascript中如何定义函数以及调用函数 8 js中Date
  • 请问VARCHAR2(128)能存多少个汉字?

    Q 请问VARCHAR2 128 能存多少个汉字 A 看看什么字符集 或者看单个汉字几个字节lengthb Q 请问怎样查看你所提出的两个问题 A oracle中length 与lengthb 区别 SQL gt select length
  • 多个数计算最大公约数与最小公倍数的模板

    这是道计算两个数的最大公约数与最小公倍数的题目 辗转相除法实现计算最大公约数 多个数的最大公约数 计算多个数的最大公约数的算法思路 计算前两个数是最大公约数 记为gcd 再计算gcd与第三个数的最大公约数 更新gcd为本次计算的最大公约数
  • 如何检查 Docker 镜像是否存在漏洞

    Docker 可以将应用程序及其依赖项打包到一个虚拟容器中 该容器可以在任何 Linux Windows 或 macOS 计算机上运行 这使应用程序可以在各种位置运行 例如本地 公共 请参阅分散计算 分布式计算和云计算 或私有云 在 Lin
  • 正规式和正则表达式的异同

    正规式的定义及使用方法 转自正规式 设 是有穷字母表 并定义辅助字母表 都是 上的正规式 它们所表示的正规集为 任何a是一个正规式 若a 它所表示的正规集为 a 如果R1和R2是正规式 它们表示的正规集分别为L1和L2 则 R1 R2 R1
  • 滤波电容容值与所滤噪声频率的关系

    去耦电容的选择不存在与频率的精确对应关系 理论上越大越好 但现实中所有器件都不是理想器件 不论何种电容 ESL ESR都是必然存在的 于是实际电容的频响曲线明显呈非线性 仅在一定频率区间内基本符合纯电容的理论计算结果 超出一定界限后就与理论
  • Chaincode之间调用

    API InvokeChaincode 可以一个chaincode中调用另外一个chaincode中的函数 两个chaincode需要安装在相同的peer结点中 如果只需要查询被调链码的世界状态 可以在不同通道中进行 如果涉及更新操作 两个
  • QT中为生成的exe运行文件添加图标

    1 准备好ico图标文件名字为test ico 最好放在和 pro文件同一个文件夹中 2 创建一个叫icon rc的文件 里面写上文本信息IDI ICON1 ICON test ico 保存好 3 在pro文件中添加代码 RC FILE i
  • 09.Javascript设计模式之装饰器模式----Decorator

    09 Javascript设计模式之装饰器模式 Decorator 首先 我非常遗憾的要说一声 我花了两个小时整理的关于装饰器模式的笔记 因为一个不可预期的故障 ADoc文档上传到服务器后 文件损坏了 文件毫无备份 难道是我的笔记中包含法律
  • 数据结构--线性表详解(一)

    这里写链接内容1 前言 线性表是最常用且是最简单的一种数据结构 形如 A1 A2 A3 An这样含有有限的数据序列 我们就称之为线性表 2 线性表的两种表示形式 顺序表示 其实就是数组 链表表示 3 线性表一般操作的介绍 线性表一般包含如下