2.2 顺序表与链表特性对比

news2024/10/5 14:24:47

1. 插入删除操作对比

1. 顺序表插入删除元素

        插入策略: 

        在某个位置插入元素时, 把从该位置开始的所有元素都往后挪一个位置, 规定顺序表最后一个元素后面的位置也是一个可插入位置. 后面的元素先往后挪动位置

        删除策略: 

        在某位置删除元素, 把从该位置之后的所有元素都往前挪一个位置, 把要删除的元素覆盖掉即可. 前面的元素先往前挪动位置

#include <iostream>

const int MAX_SIZE = 10;

//在C++中,整型数组是值类型。这意味着当你创建一个整型数组时,实际上会在内存中分配一块连续的内存来存储数组的元素。
//当你将整型数组分配给另一个变量或传递给函数时,会发生数组的拷贝,新数组的修改不会影响原始数组。

//在 C++ 中,不能直接返回整型数组。这是因为数组是一个连续的内存块,无法直接通过返回值的方式来传递。

/// <summary>
/// 初始化数组
/// </summary>
void initArr(int *arr, int length) {
    if (length > MAX_SIZE) {
        printf("数组长度超过最大长度!");
        return;
    }

    for (int i = 0; i < length; i++)
    {
        arr[i] = i;
    }

}

/// <summary>
/// 打印数组元素
/// </summary>
/// <param name="arr"></param>
void printArr(int *arr, int length) {
    //在 C++ 中,指针变量的初始值为 nullptr,而不是 NULL。
    //因此,应该将判断条件修改为 arr == nullptr,以检查数组是否为空。
    //if (arr[0] == NULL)
    if (arr == nullptr) {
        printf("数组为空!\n");
        return;
    }

    //另外,计算数组长度的方式也是错误的。在 C++ 中,数组作为函数参数传递时会被转换为指针,
    //因此无法通过 sizeof 运算符来获取数组的长度。你可以通过传递数组的长度作为额外的参数来解决这个问题。
    //int length = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < length; i++)
    {
        printf("数组元素: %d\n", arr[i]);
    }
}

/// <summary>
/// 数组插入元素
/// </summary>
/// <param name="arr">要插入的数组</param>
/// <param name="length">数组插入元素前的长度</param>
/// <param name="index">要插入的位置</param>
/// <param name="data">要插入的值</param>
void insertElement(int arr[], int &length, int index, int data) {
    if (index < 0 || index > length) {
        printf("索引越界!\n");
        return;
    }

    if (length >= MAX_SIZE) {
        printf("数组元素已满!\n");
        return;
    }

    for (int i = length + 1; i > index; i--)
    {
        arr[i] = arr[i - 1];
    }
    arr[index] = data;
    length++;
}

/// <summary>
/// 数组删除元素
/// </summary>
/// <param name="arr">要删除的数组</param>
/// <param name="length">数组删除元素前的长度</param>
/// <param name="index">要删除的元素的索引</param>
/// <returns></returns>
int deleteElement(int arr[], int &length, int index) {
    if (index < 0 || index >= length) {
        printf("索引越界!\n");
        return -1;
    }

    if (length <= 0) {
        printf("数组长度为空\n");
        return-1;
    }
    int temp = arr[index];
    for (int i = index; i < length; i++)
    {
        arr[i] = arr[i + 1];
    }
    length--;
    return temp;
}

int main()
{
    int arr[MAX_SIZE];              //为数组开辟的存储空间的大小为MAX_SIZE
    int length = 6;
    initArr(arr, length);
    printArr(arr, length);

    insertElement(arr, length, 1, 9999);
    printf("--------------插入元素后--------------\n");
    printArr(arr, length);

    int element = deleteElement(arr, length, 5);
    if (element != -1) {
        printf("--------------删除元素后--------------\n");
        printf("删除的元素: %d\n", element);
        printArr(arr, length);
    }
    
}

代码1: 顺序表(数组)的插入删除操作

2. 单链表插入删除操作

        插入策略: 

 单链表的插入操作

        删除策略: 

 单链表的删除操作

#include <iostream>

typedef struct LNode {
    int data;
    struct LNode* next;
}LNode;


/// <summary>
/// 判断链表是否非空
/// </summary>
/// <param name="p"></param>
bool linkedListIsNotNull(LNode* p) {
    if (p == NULL) {
        return false;
    }
    return true;
}

/// <summary>
/// 遍历输出链表各个结点的值
/// </summary>
/// <param name="firstNode"></param>
void traverseLinkedList(LNode* p) {
    while (p != NULL) {
        // 对当前节点进行操作,打印节点的数据
        printf("%d\n", p->data);

        // 移动到下一个节点
        p = p->next;
    }
}

/// <summary>
/// 插入元素
/// </summary>
/// <param name="p">插入位置前面的元素</param>
/// <param name="q">要插入的元素</param>
void insertElement(LNode *p, LNode *q) {
    q->next = p->next;
    p->next = q;
}

/// <summary>
/// 删除元素
/// </summary>
/// <param name="p">要删除的元素的前一个元素</param>
/// <returns></returns>
LNode* deleteElement(LNode* p) {
    LNode* q = p->next;
    p->next = q->next;
    q->next = NULL;
    return q;
}

int main()
{
    LNode* A;
    A = new LNode;
    LNode* B;
    B = new LNode;
    LNode* C;
    C = new LNode;

    A->data = 10;
    B->data = 20;
    C->data = 30;

    A->next = B;
    B->next = NULL;
    C->next = NULL;

    LNode* p = A;        
    LNode* q = C;
    bool isNotNull = linkedListIsNotNull(p);
    if (isNotNull) {
        insertElement(p, q);
        traverseLinkedList(p);
        printf("---------------------------\n");
        LNode* q =deleteElement(p);
        free(q);
        traverseLinkedList(p);
    }
    else {
        printf("链表为空!");
    }
}

代码2: 单链表的插入删除操作

        对比: 

        在顺序表中 和删除元素可能(不是一定)会移动大量元素的连带操作(插入或删除操作发生在表尾位置例外), 而链表不会, 链表只需修改指针, 元素无需移动. 

2. 元素的定位问题

        顺序表元素定位只要知道某个元素的下标, 就定位到了该元素; 链表元素定位需要一个搜索的过程. 

        在单链表中找到任意一个结点的位置不像顺序表那么简单, 因为顺序表支持随机存取(任意存取), 而单链表不支持. 

        为了尽可能弥补单链表不能随机存取的不足, 开发了双链表, 循环单链表和循环双链表等存储结构, 这些存储结构可以在仅知道链表中任一个结点地址的情况下推知其余所有结点的地址, 但仍然不支持随机存取. 

        有时还会给链表定义一个额外的指针, 最常见的是表尾指针, 它指向链表中最后一个结点. 可以借助它来提高某些常用操作的执行效率. (尾指针始终指向尾结点)

3. 存储空间相关问题

        如果为顺序表分配存储空间, 必须一次性把存储空间划分完, 不能分批次划分.

        从整体来看, 顺序表在很多情况下都会比链表的空间利用率低一些, 因为顺序表划分的存储空间可能没有完全利用. 

        而对于存储单元, 顺序表的存储空间利用率大于链表的存储空间利用率, 因为链表中有指针, 它我们要存储的数据信息. 

        线性表采用顺序存储结构, 必须占用一片连续的存储单元, 而采用链式存储结构则不需要这样. 

        从表整体来看, 一般顺序表存储空间利用率低于链表; 而从单个存储单元来看, 顺序表存储空间利用率要高于链表. 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/748765.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【技术篇】• 饮用水除硝酸盐的技术解析

​​​​​​​ 近年来由于农业活动及排污物的影响&#xff0c;部分地表水源水中硝酸盐含量呈现明显的增加趋势&#xff0c;硝酸盐污染成为地下水和饮用水领域关注的热点问题之一。 硝酸盐是有氧环境中稳定的含氮化合物形式&#xff0c;也是含氮有机物通过无机化分解的产物&am…

搭建archetype骨架工程

搭建archetype骨架工程 一、archetype概念1、archetype简介2、archetype组成结构3、archetype生命周期4、archetype使用 二、构建我们自定义的骨架工程1、创建一个自定义的项目2、修改pom的build插件3、生成archetype资源文件4、将生成的资源文件制作成archetype jar包5、生成a…

Java中不同变量声明类型

今天在学习分层解耦-三层架构的过程中&#xff0c;具体文章参照&#xff1a;写文章-CSDN创作中心 在Servie层创建Dao对象时&#xff0c;以及在Controller层创建Service对象时&#xff0c;发现与我之前了解的声明变量的方法不一样。具体关键代码如下&#xff1a; 其中EmpServic…

简要介绍 | 边缘计算:原理,研究现状与未来展望

注1&#xff1a;本文系“简要介绍”系列之一&#xff0c;仅从概念上对边缘计算进行非常简要的介绍&#xff0c;不适合用于深入和详细的了解。 边缘计算&#xff1a;原理&#xff0c;研究现状与未来展望 What is Edge Computing? | Moving Intelligence to the Edge 一、背景介…

小平板 大智慧-嵌入式方案满足教育市场多元需求

线上教育观念的深入和技术的更新&#xff0c;直接拉动了教育类硬件及相关终端设备的市场需求。 产品框图 IDO-SBC3566采用瑞芯微RK3566&#xff0c; CPU采用4核A55架构处理器&#xff0c;集成G52图形处理器&#xff0c;内置独立NPU&#xff0c;算力高达1Tops&#xff0c;可满足…

如何在 Windows 中免费合并 PDF 文件 [在线和离线]

PDF是一种广泛使用的文件格式&#xff0c;具有兼容性好、安全性高、易于打印、方便浏览等众多优点。在工作和学习过程中&#xff0c;经常需要将同一类型的PDF文件合并起来&#xff0c;以方便传输和查看&#xff0c;使得合并PDF文件成为一种重要的数据整合方法。 如果您想知道如…

Es存储和查询

基本概念 Cluster 集群&#xff0c;一个ES集群是由多个节点(Node)组成的&#xff0c;每个集群都有一个cluster name 作为标识&#xff0c; 在同一网段下的Es实例会通过cluster name 决定加入哪个集群下。 node 节点&#xff0c;一个ES实例就是一个node&#xff0c;一个机器可以…

电气控制与PLC之间的本质区别是什么?

电气控制和PLC&#xff08;可编程逻辑控制器&#xff09;之间的最实质的区别是它们的实现方式和应用范围。 我这里刚好有嵌入式、单片机、plc的资料需要可以私我或在评论区扣个6 实现方式&#xff1a; 电气控制&#xff1a;电气控制是通过使用电气元件&#xff08;如继电器、…

数据库多表连接查询练习

数据库多表连接查询练习 一、创建数据库dept、emp 二、插入数据 1.找出销售部门中年纪最大的员工的姓名 mysql> select name,age from emp inner join dept on dept.dept1emp.dept2 where dept_name销售 order by age desc limit 1;2.求财务部门最低工资的员工姓名…

探索AI大模型:现状、挑战与未来

导言&#xff1a; 近年来&#xff0c;AI大模型如GPT&#xff08;生成对抗网络&#xff09;在自然语言处理领域崭露头角&#xff0c;引发广泛关注和讨论。这些模型能够生成各种类型的文本内容&#xff0c;展现出惊人的语言处理能力。然而&#xff0c;AI大模型的发展也面临着挑战…

Perl web - Mojolicious 小记

文章目录 关于 Mojolicious安装 关于 Mojolicious Mojolicious是Perl语言比较流行的异步Web开发框架。 官网&#xff1a;https://mojolicious.orggithub : https://github.com/mojolicious/mojo示例&#xff1a;https://github.com/mojolicious/mojo/tree/main/examples 相关…

【雕爷学编程】Arduino动手做(138)---64位WS2812点阵屏模块8

37款传感器与执行器的提法&#xff0c;在网络上广泛流传&#xff0c;其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块&#xff0c;依照实践出真知&#xff08;一定要动手做&#xff09;的理念&#xff0c;以学习和交流为目的&am…

移动端 滚动穿透

文章目录 滚动穿透弹窗内容滚动到底部后带动底层页面滚动在弹窗出现时可以直接通过页面滚动条滚动 禁用底层页面滚动弹出层将覆盖整个视口禁用触摸事件监听弹出层滚动位置阻止弹出层的滚动事件冒泡 滚动穿透 当一个固定定位&#xff08;fixed&#xff09;或绝对定位&#xff0…

Windows10 网页版 上线!最具扩展性的webos

模仿Windows10 UI 框架 Vue3 点击进入github 链接: https://github.com/royalknight56/win10-vue3 本框架可以让你的页面像win10视窗系统一样&#xff0c;运行一个网页上的win10系统。 本框架可能是最具扩展性的webos 本框架相较于其他的特点是&#xff0c; 具有文件系统&am…

第二章:类与对象(上)

系列文章目录 文章目录 系列文章目录前言面向过程和面向对象初步认识类的引入类的定义类的两种定义方式成员变量命名规则的建议 类的访问限定符及封装访问限定符面试题 封装面试题 类的作用域类的实例化类对象模型如何计算类对象的大小类对象的存储方式猜测对象中包含类的各个成…

C语言字节序

C语言字节序分为大端序和小端序。 大端序&#xff1a; 高字节先存储&#xff0c;也就是数据的高字节存储在低地址中。 小端序&#xff1a; 低字节先存储&#xff0c;也就是数据的低字节存储在低地址中。 例如&#xff1a; short a 01234; char *p &a; printf(&qu…

基于Java+SpringBoot制作一个社区宠物登记小程序

制作一个社区宠物登记小程序,帮助社区居民登记和管理他们的宠物信息,以便更好地跟踪和维护社区中的宠物状况,通过社区宠物信息登记系统,社区居民可以更好地管理自己的宠物信息,并与其他宠物所有者共享资源和信息。这将有助于提高社区宠物的福利和安全,促进社区成员之间的…

业务流程管理系统是什么?企业业务流程有哪些?

随着企业规模的不断扩大和竞争的日益激烈&#xff0c;业务流程管理系统的重要性也越来越明显。通过对业务流程的全面管理和优化&#xff0c;企业可以提高工作效率、降低流程成本、优化流程质量&#xff0c;从而在市场竞争中获得更大的优势。 阅读本文您将了解&#xff1a; 一、…

【实战项目】c++实现基于reactor的高并发服务器

基于Reactor的高并发服务器&#xff0c;分为反应堆模型&#xff0c;多线程&#xff0c;I/O模型&#xff0c;服务器&#xff0c;Http请求和响应五部分 全局 反应堆模型 Channel 描述了文件描述符以及读写事件&#xff0c;以及对应的读写销毁回调函数&#xff0c;对应存储arg读…

查看某个三方依赖jar包是在哪个pom引入的(springboot+idea)

项目springboot1升级2版本&#xff0c;日志框架使用的是log4j&#xff0c;升级到springboot2版本某些依赖引入了logback依赖包&#xff0c;然后项目启动报错&#xff1a; 查看这个SLF4JLoggerContextFactory这个类是在哪个jar包下 使用idea的maven依赖图查看功能寻找是哪个p…