使用循环链表实现一个通讯录的管理程序_【LeetCode链表题型总结】

点击上方蓝字,关注公众号f51c1164110821cd94c8caca7f060415.png

链表概念的讲解

链表是什么

链表是一种线性数据结构,每个节点都存有数据,通过指针将各个节点链接在一起。

链表的性质

  • 一致性: 每个节点有相同的数据结构,相同的数据大小,内存中占据相同的大小,存储相同的数据类型。
  • 有序性: 节点之间的相对顺序固定,排在某节点前面的节点就是它的前驱,后面的节点就是它的后继,所以定义里面有'线性'。

链表的分类

链接方式分类:单向链表,双向链表。

ps: 代码展示只用单链表举例。

单链表结构

c0137b08f78e15e0b8a2550d189184ba.png

单链表中的每个结点包含数据+指向后继节点的指针,通过这种方式,单链表将所有结点按顺序组织起来。

节点定义

class Node(object):"""单链表结构的Node节点"""
    def __init__(self, data, next_node=None):"""Node节点的初始化方法。
        data:存储的数据
        next:下一个Node节点的引用地址
        """
        self.data = data
        self.next = next_node

双链表结构

a617c5eb6b18b3f713757e2948ee1235.png

双链表中的每个节点包含数据+指向前驱和后继的指针。

链表的基本操作

链表基本操作:  插入,搜索,删除。以下分别讲每个操作是如何操作的,时间复杂度多少,为什么是那么多,根据时间复杂度判断链表的适合场景。

查找

按照索引/值查找: 遍历找到对应的位置/值,然后返回该节点。

# 按照值查找
node = head_nodewhile node.data != value:
    node = node.next_node# 按照索引查找
pos = 0while pos != index:
    node = node.next_node
    pos += 1

时间复杂度:是线性遍历的,所以时间复杂度是O(n)。因为时间复杂度相对较高,所以在大量数据需要经常用检索的时候就不要用链表了。

插入

按照index插入

1.先创建新节点new_node

2.找到要插入的位置的前驱节点pre

3.新节点new_node指向pre的后继节点

4.pre指向新节点

new_node.next = pred.next
pred.next = new_node

时间复杂度:由于第2步要线性遍历去找index位置,所以时间复杂度是O(n)。如果插入在头部,就不需要找位置,时间复杂度是O(1)。

删除

如何做删除的 

1.找到待删节点的前驱pred

2.把它的前驱节点的后继指向待删节点后继的后继

pred.next = pred.next.next

时间复杂度:因为要去找前驱,所以线性遍历,时间复杂度是O(n)。如果删除头部,就不需要找位置,时间复杂度是O(1)。

链表常见的考点: 哑节点(边界条件)- 用于简化边界情况,链表为空或链表的头结点和尾节点。解决办法,自己创建一个哑节点,然后把它的后继连接原节点。

链表的实际应用,通常用于顺序记录的存储,无需提前分配空间,仅适用小规模数据存储。

对于适用的操作属性来说,链表适合查找少,无需排序的使用场景,原因:是链表的查找效率不高,通过调整指针可以快速调节节点的相对位置。

业界应用: 小规模日志记录(通话记录或通讯录),读到内存中后可以以链表的方式进行存储;操作系统中内存快的缓存也可以用链表来实现,LRU缓存(利用了链表快速调整相对位置优势)。

模式识别

以下这些适用解决链表相关问题。

runner and chaser类型题目中有关键词: 要寻找每个特定位置/相对位置。就用后移速度不同的快慢指针来解决使以下文章用到这个方法:
  • 【LeetCode-19-Remove Nth Node From End of List】删除链表的倒数第N个节点

  • 【LeetCode-141-Linked List Cycle】环形链表

  • 【LeetCode-876-Middle of the Linked List】链表的中间节点

遍历并处理节点: 处理包括交换,改数值,改指针,删除等等这类问题的处理方式是每次操作都是当前节点或某类节点,每次处理单个或一对节点;处理的时候,先改变前驱指针,再改变当前节点指针,否则当前节点的next信息改变完之后就不对了,通过先改变前驱的指针到达一个保存状态的目的。要动一个元素的后继之前,先保存它的后继。
  • 【LeetCode24. Swap Nodes in Pairs】两两交换链表中的元素

  • 【LeetCode-25-Reverse Nodes in k-Group】K 个一组翻转链表

  • 【LeetCode-143-Reorder List】重排链表,次头条。

处理两个或多个链表处理方式是用while循环进行常规处理,循环条件是list1非空并且list2非空,当循环跳出后处理剩下的非空列表。循环至空,再处理剩余。
  • 【LeetCode-21. Merge Two Sorted Lists】合并两个有序链表 

应用递归处理(涉及链表倒序处理问题)解决当前问题依赖于存在的相似结构的子问题;利用调用函数本身,先解决子问题,再利用子问题的结果解决当前的问题,递归的出口通常是问题的初始条件n=1的情况。链表问题一旦需要倒序处理或与树之间的数据结构进行相互转换往往会用到递归,或者用栈来解决。LeetCode369,426,因为这两道题要会员才能做,我不能做,所以没有写题解。

自己实现一个单链表类

实现插入查找删除的功能。

class ListNode(object):
    def __init__(self, value):"""
        value: 节点的数据值
        next: 节点的后继
        """
        self.value = value
        self.next = None
class MyLinkedList(object):
    def __init__(self):"""
        Initialize your data structure here.
        """
        self.head = ListNode(0) # 用哑结点来当头节点,方便处理插入和删除的边界情况。
        self.size = 0
    def get(self, index):"""按照索引查找
        Get the value of the index-th node in the linked list. If the index is invalid, return -1.
        :type index: int
        :rtype: int
        """# 异常情况: 如果索引无效 | 索引超出范围if index = self.size:return -1
        node = self.headfor _ in range(index + 1): # 记得链表的头结点是哑结点,所以range后界要+1
            node = node.nextreturn node.value # 是返回节点值
    def addAtHead(self, val):"""添加到头节点
        Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
        :type val: int
        :rtype: None
        """
        self.addAtIndex(0, val)
    def addAtTail(self, val):"""添加到尾节点
        Append a node of value val to the last element of the linked list.
        :type val: int
        :rtype: None
        """
        self.addAtIndex(self.size, val)
    def addAtIndex(self, index, val):"""按照索引添加node
        :type index: int
        :type val: int
        :rtype: None
        """# 异常情况: 如果索引无效 | 索引超出范围if index = self.size + 1:return # 什么都不做# 找到要加入节点的前驱节点
        node = self.headfor _ in range(index): 
            node = node.next# 加入新节点
        new_node = ListNode(val) # 创建新节点
        new_node.next = node.next
        node.next = new_node# 链表的总数加1
        self.size += 1
    def deleteAtIndex(self, index):"""删除节点
        因为删除操作的流程是,待删节点node的前驱pre,改变pre后继节点到node的后继节点,所以找的节点应该是pre
        :type index: int
        :rtype: None
        """# 异常情况: 如果索引无效 | 索引超出范围if index = self.size:return # 什么都不做# 找到要删除的节点
        node = self.headfor _ in range(index): # 找到待删节点的前驱节点,因为我们已经在头部加了哑结点,所以真正的头部节点是不用单独处理的,按照常规删节点的方式处理
            node = node.next# 删除待删节点
        node.next =node.next.next# 链表的总数减1
        self.size -= 1

参考资料:

- 力扣

原创文章,欢迎转载,转载请在公众号菜单栏查看【联系我】。

6b084b543d17487936c6128c55c39819.png

              喜欢本文的小伙伴点【在看】分享给你的朋友?↓↓↓

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

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

相关文章

python的kite下载安装及使用_Kite下载|Kite Python编程工具 V1.2020.1203.0 最新版下载 - 下载银行...

Kite是一款专为Python打造的一款代码补全软件,如果你正在学习Python或是从事与Python相关的编程工作,那么这款软件绝对是你的好帮手!其会智能判断用户想要输入的每个代码字段,并在所有库中进行匹配相应的内容,如果看到…

Linux 升级 Python 至 3.x

原文链接:http://blog.csdn.net/liang19890820/article/details/51079633 -------------------------------------------- 简述 CentOS 7 中默认安装了 Python,版本比较低(2.7.5),为了使用新版 3.x,需要对…

Sublime Text 3 配置python交互运行环境的快捷键

2019独角兽企业重金招聘Python工程师标准>>> 使用Sublime Text 3能以轻量级的环境写python脚本,运行python代码。为了更加方便地调用python脚本,通过在Sublime Text 3中绑定快捷键的方式,实现一键调用python交互运行环境&#xff…

xftp如何搜索文件_头条搜索站长平台如何添加网站和sitemap文件?附图文教程

头条搜索站长平台已经上线了,目前我们广大站长都可以登录该平台后添加新网站和提交 sitemap 地图文件,建议大家可以前往尝试一下,多一个搜索平台就多一条路,认为倒是挺好的。下面就跟大家简单介绍头条搜索站长平台如何添加网站和提…

彩铅练习,花船

图片发自简书App图片发自简书App

我的女朋友漏电了–论C++中的失败(failure),缺陷(bug)和异常(exception)

先做个广告置入,如果喜欢这篇文章,你可以到 zhaoyan.website/blog 去查看于此类似的C/C文章。 我承认有点标题党了,不过这真的是一篇写软件的文章,所以如果你已经抽出了一张面巾纸,那么趁早再把它完美的放回去。这篇软…

SQLplus 和mysql区别_mysql和oracle的区别有哪些

MySQL和Oracle都是流行的关系数据库管理系统(RDBMS),在世界各地广泛使用;大多数数据库以类似的方式工作,但MySQL和Oracle的这里和那里总是存在一些差异的。本篇文章就给大家比较Oracle和MySQL,介绍Oracle和MySQL之间的区别&#x…

127.0.0.1与localhost的区别

2019独角兽企业重金招聘Python工程师标准>>> 区别1: localhost也叫local ,正确的解释是:本地服务器 127.0.0.1在windows等系统的正确解释是:本机地址(本机服务器) 他们的解析通过本机的host文件,windows自动将localhost解析为127.…

mysql 索引_MySQL之索引

索引查找算法BTREEBTREE查找算法演变B-TREE :普通 BTREE,平衡多路查找树(B-Tree)BTREE :叶子节点双向指针BTREE(B*TREE):枝节点的双向指针普通B-TREE增强版BTREE(B*TREE)总结:从上图看出,在BTree上有两个头…

java数学计算表达式_Java初学者:内建函数计算简单的数学表达式

这个应该在之前写的,忘记了,补上这次我们说一下如何用java计算数学表达式的值,比如,我们要计算sin(pi/3) cos(pi/6) 5.6^3,怎么计算呢?这里我们需要用到java的math的内建函数,所谓内建函数&am…

谷歌新作gVisor:VM容器融合技术已经到来

作者|秦承刚,吴启翾,喻望,杨伟 编辑|张婵 出处丨高效开发运维 5 月 2 日,谷歌发布了一款新型的沙箱容器运行时 gVisor,号称能够为容器提供更安全的隔离,同时比 VM 更轻量。容器基于共…

安卓androidstudio访问本地接口_安卓开发之数据存储在本地的四种方式

​安卓开发之数据存储在本地的四种方式本地数据存储,在安卓开发过程中是不可避免的一个话题。这些本地的数据可能是用户的设置,程序的设置,用户的数据图片, 也可能是网络传输的一些缓冲数据。基本上我们有4种方法可以存储安卓程序的数据。第1…

java vector 线程安全_关于Vector到底是不是 线程安全的 问题

线程安全,在java的多并发编程中是重要概念,意思是,多个线程同时操作一个对象,在各种不同情况下,都不会造成不同的后果。一个经典问题,Vector到底是不是线程安全的?很多人都会回答,是…

C# Winform使用Windows Media Player播放多媒体整理

一、简单使用示例步骤 1.添加Windows Media Player 组件当前是系统的 Com组件 工具箱》右键“选择项”》选择Com组件 2.控件拖拽到桌面,使用 private void button1_Click(object sender, EventArgs e) {//播放开始声音axWindowsMediaPlayer2.URL "start.mp3&q…

618选购手机正当时,好评率高达99%的手机了解一下!

一年一度的京东618年中购物狂欢节如火如荼的进行中,手机厂商们都使出了浑身解数,对消费者进行争夺。对于用户来说,618绝对是更换手机的好时机。不过,小伙伴们面对市场上的众多机型,也有可能挑花了眼,不知道…

IntelliJ IDEA 2017.2 x64 安装Scala

从官网下载好IntelliJ IDEA 和scala IntelliJ IDEA 安装scala插件 新建scala项目 建好后,发现src右键--新建---没有 .scala选项 解决方法

Django-ORM数据库操作

背景 Django框架功能齐全自带数据库操作功能,由于工作中设计巨量的api接口,需要一个很好的web后端服务框架,Django给了莫大的帮助。本文主要介绍Django的ORM框架我们一般对数据库的使用的认识是: 创建数据库,设计表结构…

Kingback小组冲刺博客

一、6月13日 1、今日完成的任务 李可欣 项目首页的框架设计 项目首页的导航栏部分 对于项目的配色进行了改进,并且设计了logo 杨帆 今天进行了数据库的设计,完成了数据库的增删改查,并建立了两个jsp页面,还学习了一些数据库设计的…

使用Git上传本地项目到oschina

原文地址:https://my.oschina.net/158/blog/530112 --------------------------------------------- 1.首先看一下自己是否有公钥, 在 我的资料-->SSH公钥 查看,如果没有,添加自己的SSH 公钥: SSH key 可以让你在…

整数数组按绝对值排序

2019独角兽企业重金招聘Python工程师标准>>> 题目: 给出一组整数数组,要求按照绝对值从小到大进行排序后输出。 可以用经典的冒泡排序法来计算此问题,计算过程: 1、比较相邻两个元素绝对值,如果第一个比第二…