链表基本原理

news2024/12/23 8:50:21

链表基本原理

  • 1.链表
    • 1.1 基本原理
    • 1.2 链表大O记法表示
  • 2. 链表操作
    • 2.1 读取
    • 2.2 查找
    • 2.3 插入
    • 2.4 删除
  • 3.链表代码实现

1.链表

1.1 基本原理

  • 节点
    • 组成链表的数据格子不是连续的。可以分布在内存的各个位置。这种不相邻的格子就叫结点。
    • 每个结点保存数据还保存着链表里的下一结点的内存地址。
  • 链表(Linkedlist)
    • 链表结构相对于顺序表可以充分利用计算机内存空间。
    • 实现灵活的内存动态管理且进行扩充时不需要进行数据搬迁。
    • 是一种常见的基础数据结构,是一种线性表

1.2 链表大O记法表示

操作大O记法表示【最坏情况】默认采用大O记法表示【最好情况】
读取O( N N N)O(1)
查找O( N N N)O(1)
插入O( N N N)O(1)
删除O( N N N)O(1)

2. 链表操作

2.1 读取

  • 链表的结点可以分布在内存的任何位置。
  • 根据索引读取
  • 读取值:必须先读取索引为0的链,顺着该链去找索引1。根据索引 1 的链去找索引 2…最终找到自己要读取的值。
    在这里插入图片描述

2.2 查找

  • 根据值查找是否存在
  • 根据读取一样,在读取每个索引节点时,读取值判断是否与查找的值相等,否则读取下一个节点,直到末尾未找到值。
    在这里插入图片描述

2.3 插入

  • 开头插入:创建新节点,将新节点链表指向的下一个内存地址为原先链表头部即可
  • 中间插入:创建新节点,读取链表索引0,根据索引0找到下一个节点,依此类推找到要插入的位置,将插入索引前面的索引节点链表指向的下一个内存地址为新节点位置,将新节点指向的下一个内存地址为插入索引后面的索引节点
  • 末尾插入:创建新节点,读取链表索引0,根据索引0找到下一个节点,依此类推找到末尾位置,将末尾内存节点null设置为新节点的内存地址,将新节点指向的下一个内存地址设为null
    在这里插入图片描述

2.4 删除

  • 开头删除:将链表的第二个节点设置为第一个节点即可
  • 中间删除:遍历链表,遍历到要删除的索引,将删除的前一个节点指向下一个内存地址重新指向删除节点的后一个节点即可
  • 末尾删除:遍历链表,遍历到倒数第二个节点,将此节点指向的下一个节点地址设为null即可
    在这里插入图片描述

3.链表代码实现

# 节点封装
class Node():
    def __init__(self, item):
        self.item = item
        self.next = None


# 链表封装
class Link():
    def __init__(self):  # 构建一个空链表
        self._head = None  # _head永远要指向链表中的第一个节点,None表示链表没有节点

    # 读取操作
    def read(self,index):
        count = 0
        current = self._head
        while True:
            if count!=index:
                count += 1
                current = current.next
            else:
                item=current.item
                print(f'索引{index}的值为:{item}')
                break
        return item

    # 查找操作
    def search(self, item):  # 查找节点是否存在
        current = self._head
        find = False
        count=0
        while current:
            if current.item == item:
                find = True
                print(f'值为{item}的索引为:{count}')
                break
            else:
                current = current.next
                count+=1
        return find

    # 插入操作
    def add(self, item):  # 开头插入
        node = Node(item) # 实例化一个新的节点
        node.next = self._head
        self._head = node
    def insert(self, pos, item):  # 中间插入
        node = Node(item)
        current = self._head
        temp = None
        # 单独判断插入位置为0的节点
        if pos == 0:
            self.add(item)
            # node.next = self._head
            # self._head = node
            return
        for i in range(pos):
            temp = current
            current = current.next
        temp.next = node
        node.next = current
    def append(self, item):  # 尾部插入
        # 实例化一个新的节点
        node = Node(item)
        # 如果链表为空
        if self._head == None:
            self._head = node
            # 如果链表为非空
        temp = None
        current = self._head
        while current:
            temp = current
            current = current.next
        temp.next = node

    # 删除操作
    def delete(self, item):  # 将item对应的节点删除
        current = self._head
        temp = None
        if current.item == item:  # 删除的节点是第一个节点
            self._head = current.next
            return
        while current:
            temp = current
            current = current.next
            if current.item == item:
                temp.next = current.next
                return
    # 遍历整个链表
    def travel(self):
        # print(self._head.item)
        # print(self._head.next.item)
        # print(self._head.next.next.item)
        # current指向第一个节点
        # _head永远要指向第一个节点,轻易不要修改_head指向
        current = self._head
        while current:
            print(current.item,end='\t')
            current = current.next
        print('\n')

    def isEmpty(self):  # 链表是否为空
        return self._head == None


    def length(self):  # 返回列表中节点的个数
        count = 0
        current = self._head
        while current:
            count += 1
            current = current.next
        return count

    # 翻转
    def reverse(self):
        pre = self._head
        cur = pre.next
        next_node = cur.next
        pre.next = None
        while True:
            cur.next = pre
            pre = cur
            cur = next_node
            if next_node != None:
                next_node = next_node.next
            else:
                break
        self._head = pre
link = Link()
# 插入
# 头部
for i in range(1,6):
    link.add(i)
print('头部添加元素链表为:',end='')
link.travel()

# 中间
link.insert(1, 1234)
print('中间添加元素链表为【(1, 1234)】:',end='')
link.travel()

# 尾部
link.append(12)
print('尾部添加元素12链表为:',end='')
link.travel()

# 读取
link.read(1)

# 查找
link.search(4)

# 删除
link.delete(3)
print('删除元素3后链表为:',end='')
link.travel()

print("链表长度为:"+str(link.length()))
print("链表反转后值为:")
link.reverse()
link.travel()

在这里插入图片描述

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

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

相关文章

Leetcode—移除元素、删除有序数组中的重复项、合并两个有序数组

移除元素 此题简单,用双指针方法即可, 如果右指针指向的元素不等于val,它一定是输出数组的一个元素,我们就将右指针指向的元素复制到左指针位置,然后将左右指针同时右移; 如果右指针指向的元素等于 val&…

04 OpenCV位平面分解

1 基本概念 位平面分解的核心思想是将图像的每一个像素分解为多个二进制位,分别存储在不同的位平面上。例如,如果一个图像是8位深度的,则可以分解为8个位平面,每个位平面上存储一个二进制位。 位平面分解在图像压缩中有着重要的…

对Node.js 的理解?优缺点?应用场景?

一、是什么 Node.js 是一个开源与跨平台的 JavaScript 运行时环境 在浏览器外运行 V8 JavaScript 引擎(Google Chrome 的内核),利用事件驱动、非阻塞和异步输入输出模型等技术提高性能 可以理解为 Node.js 就是一个服务器端的、非阻塞式I/…

中国计算机设计大赛来啦!用飞桨驱动智慧救援机器狗

‍‍中国大学生计算机设计大赛是我国高校面向本科生最早的赛事之一,自2008年开赛至今,一直由教育部高校与计算机相关教指委等或独立或联合主办。大赛的目的是以赛促学、以赛促教、以赛促创,为国家培养德智体美劳全面发展的创新型、复合型、应…

保姆级Vue3+Vite项目实战多布局(下)

写在前面注:本文首发掘金签约专栏,此文为文章同步!本文为 Vue3Vite 项目实战系列教程文章第三篇,系列文章建议从头观看效果更佳,大家可关注专栏防走失!点个赞再看有助于全文完整阅读!此系列文章…

如何在 C++ 应用程序中集成 Spire.XLS for C++

Spire.XLS for C 是一个 Excel 库,供开发人员在任何类型的 C 应用程序中操作 Excel 文档(XLS、XLSX、XLSB 和 XLSM)。 本文演示了如何以两种不同的方式将 Spire.XLS for C 集成到您的 C 应用程序中。 通过 NuGet 安装Spire.XLS for C通过手动…

一篇文章带你读懂HashMap

HashMap是面试中经常问到的一个知识点,也是判断一个候选人基础是否扎实的标准之一。可见HashMap的掌握是多重要。 一、HashMap源码分析 1、构造函数 让我们先从构造函数说起,HashMap有四个构造方法,别慌 1.1 HashMap() // 1.无参构造方法、// 构造一…

企业数字化转型和升级:架构设计方法与实践

企业架构整体结构图例:企业架构整体结构企业架构整体结构从战略层、规划层、落地层这三层来分别对应企业架构中业务、架构和实施的各种重要活动和产出。业务架构,数据架构,应用架构和技术架构之间的内在逻辑联系:图例:企业架构整体…

什么,Excel竟然听得懂人话!?!

Excel知道我们想干啥,不相信?看下面的案例。“数据格式”列中规定了各种数据元类型的长度、保留位数等,我们需要提取对应的数值作为“字段长度”列。比如an..100取100,n4取4,an..100,3取100,..ul取1000&…

C语言学习笔记-排序算法

选择排序 选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小&…

元宇宙营销面临的三大挑战

元宇宙的营销就像在早期的互联网建立一个网站一样,你没有多少可以向过去借鉴的,这个领域一切都是崭新的。对于一个实验性很强的项目而言,你很难知道要投入多少的时间和资源,而且这个项目也不一定能保障收益以及满足其他的一些关键…

[小记]注入服务进程/跨session注入

最近测试注入遇到一个问题:OpenProcess 失败,报错码:5,没有权限。 问题排查: 1,是否是管理员权限启动程序? 是 2,注入的目标进程有什么特殊? 目标进程是svchost.exe&…

【PyQt】PyQt学习(二)模块介绍+QObject学习

简介 PyQt API 是一组包含大量类和函数的模块。核心模块如下: QtGui:包含了窗口系统、事件处理(QEvent)、2D 图像(QImage)、基本绘画、字体(QFont)和文字类;QtCore&…

02.13:监督学习中的分类问题

今天首先学习了监督学习中的分类问题,跑了两个代码。现在学起来感觉机器学习有很多不同的定理建立了不同的分类器,也就是所谓不同的方法。具体的数学原理我不太清楚。然后不同的应用场景有一个最优的分类器。 值得一提的应该就是终于清晰的明白了精度&am…

IDEA 中使用 Git 图文教程详解

✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…

记录一次time_wait与close_wait的检查

框架与语言:php tp6swoole 原因:每隔几天就会出现,redis:Cannot assign requested address 开始想法,谷歌、百度。然后结果都是配置系统参数。比如下面例子 vi /etc/sysctl.confvm.overcommit_memory 1 net.core.somaxconn 6024 net.ip…

记录--数组去重的五种方法

这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 前言 您或许会疑惑,网上那么多去重方法,这篇文章还有什么意义? 别着急,这篇文章只节选了简单的,好玩的,古老的,有实际…

内网渗透(二十四)之Windows协议认证和密码抓取-Mimikatz读取sam和lsass获取密码

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

ILSSI国际研讨会将为您呈现六西格玛技术的未来与前景

ILSSI 欢迎世界各地的精益六西格玛专业人士参加即将举行的2023年国际精益六西格玛研讨会,这次研讨会将邀请到世界各地的专家学者,分享他们的专业知识和经验,并就精益六西格玛等相关议题进行探讨和交流。 这是一个绝佳的机会,让您…

Hudi-集成Flink

文章目录集成Flink环境准备sql-client方式启动sql-client插入数据查询数据更新数据流式插入code 方式环境准备代码类型映射核心参数设置去重参数并发参数压缩参数文件大小Hadoop参数内存优化读取方式流读(Streaming Query)增量读取(Increment…