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

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(使用前将#替换为@)

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

  • Asp.net core默认路由

    简化版Startup code public void ConfigureServices IServiceCollection services services AddMvc public void Configure IApplica
  • 虚拟并行端口模拟器

    在我的计算机网络课程中 我们应该通过使用本机寄存器 例如使用 outportb 等命令 来学习并行端口编程 我没有并行端口 因为我住在 2011 年 但想练习这些程序 我使用 dosbox 安装了旧的 Turboc 3 IDE 有没有一个程
  • PrivateObject 找不到属性

    我的结构基本上如下所示 abstract class A protected string Identificator get set private void DoSomething DoSomethingSpecific protect
  • 是否可以在Linux上将C转换为asm而不链接libc?

    测试平台为Linux 32位 但也欢迎 Windows 32 位上的某些解决方案 这是一个c代码片段 int a 0 printf d n a 如果我使用 gcc 生成汇编代码 gcc S test c 然后我会得到 movl 0 28 e
  • 如果在代码中添加元素,“FindName”将不起作用

    在 WPF 应用程序中 如果在 XAML 中声明 ContentControl
  • 在 C++ 代码 gdb 中回溯指针

    我在运行 C 应用程序时遇到段错误 在 gdb 中 它显示我的一个指针位置已损坏 但我在应用程序期间创建了 10 万个这样的对象指针 我怎样才能看到导致崩溃的一个 我可以在 bt 命令中执行任何操作来查看该指针的生命周期吗 谢谢 鲁奇 据我
  • 如何对STL向量进行排序?

    我想排序一个vector vector
  • C++ 模板可以提供 N 个给定类的公共父类吗?

    我正在寻找一个 C 模板 它可以找到一组给定类的共同父级 例如 class Animal class Mammal public Animal class Fish public Animal class Cat public Mammal
  • WPF DataGrid - 在每行末尾添加按钮

    我想在数据网格的每一行的末尾添加一个按钮 我找到了以下 xaml 但它将按钮添加到开头 有人知道如何在所有数据绑定列之后添加它吗 这会将按钮添加到开头而不是末尾
  • 使用 Unity 在 C# 中发送 http 请求

    如何使用 Unity 在 C 中发送 HTTP GET 和 POST 请求 我想要的是 在post请求中发送json数据 我使用Unity序列化器 所以不需要 新的 我只想在发布数据中传递一个字符串并且能够 将 ContentType 设置
  • 如何测试某些代码在 C++ 中无法编译? [复制]

    这个问题在这里已经有答案了 可能的重复 单元测试编译时错误 https stackoverflow com questions 605915 unit test compile time error 我想知道是否可以编写一种单元测试来验证给
  • 用数组或向量实现多维数组

    我想使用单个数组或向量实现多维数组 可以像通常的多维数组一样访问它 例如 a 1 2 3 我陷入困境的是如何实施 操作员 如果数组的维数为 1 则 a 1 应该返回位于索引 1 处的元素 但是如果维数大于一怎么办 对于嵌套向量 例如 3 维
  • 与 Entity Framework Core 2.0 的一对零关系

    我正在使用 C 和 NET Framework 4 7 将 Entity Framework 6 1 3 Code First 库迁移到 Entity Framework Core 我一直在用 Google 搜索 Entity Framew
  • 当 Verb="runas" 时设置 ProcessStartInfo.EnvironmentVariables

    我正在开发一个 C 应用程序 我需要创建变量并将其传递给新进程 我正在使用ProcessStartInfo EnvironmentVariables 新进程必须提升运行 因此我使用 Verb runas var startInfo new
  • 在二进制数据文件的标头中放入什么

    我有一个模拟 可以读取我们创建的大型二进制数据文件 10 到 100 GB 出于速度原因 我们使用二进制 这些文件依赖于系统 是从我们运行的每个系统上的文本文件转换而来的 所以我不关心可移植性 当前的文件是 POD 结构的许多实例 使用 f
  • 使用 boost 异步发送和接收自定义数据包?

    我正在尝试使用 boost 异步发送和接收自定义数据包 根据我当前的实现 我有一些问题 tcpclient cpp include tcpclient h include
  • 初始化列表在 VC10 中不起作用

    我在 VC 2010 中编写了这个程序 class class1 public class1 initializer list
  • 使用 IdentityDbContext 和 Code First 自动迁移表位置和架构的实体框架?

    我正在尝试使用 IdentityDbContext 类设置自动迁移更新 并将更改传播到整个数据库的实际 DbContext 在进入代码之前 在使用自动迁移实现 IdentityDbContext 时 我收到此错误 影响迁移历史系统表位置的自
  • 如何在c中断言两个类型相等?

    在 C 中如何断言两种类型相等 在 C 中 我会使用 std is same 但搜索 StackOverflow 和其他地方似乎只能给出 C 和 C 的结果 在C中没有办法做到这一点吗 请注意 这不是询问变量是否具有某种类型 而是询问两个类
  • 是否可以使用 Dapper 流式传输大型 SQL Server 数据库结果集?

    我需要从数据库返回大约 500K 行 请不要问为什么 然后 我需要将这些结果保存为 XML 更紧急 并将该文件通过 ftp 传输到某个神奇的地方 我还需要转换结果集中的每一行 现在 这就是我正在做的事情 TOP 100结果 使用 Dappe

随机推荐

  • 关于代码评审

    代码评审实际是编写代码的开发人员在被复查 它是最小化缺陷的有效方法 无论公司实行代码评审的额外动机是什么 代码评审都是工业化的最优方法 一 代码评审目的 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 线性表一般操作的介绍 线性表一般包含如下