一、链表和数组

在编写代码中,我们储存的数据是存储于内存当中,内存就像一块块并列排序的小方盒,每个小方盒都有自己地址,我们储存的数据就在这样一个个小方盒当中。

这些数据存放的结构有两种基本方式,数组和链表。

1,数组

数组在内存中是按顺序,内存地址来存储的,就好似上图的抽屉,从上到下,按顺序存放物品。这一特征也就意味着数据在内存中是相连的,紧紧不分开的,小的内存空间可能会装不下较多的数据,造成了内存空间浪费。

世界上许多事情有好有坏,有利有弊,数组也是如此,数据在内存中紧密相连,也就意味着牵一发而动全身,比如你想在数组中添加一项数据,这就好比一排已经排好队的士兵,每个人都有自己的编号,而此时你突然要插入其中。

你:“兄弟方便让个位置吗?”

你后面的士兵都一脸凶神恶煞地看着你,如果不是排长强力要求你插入其中,他们肯定不会让你入队,因为你的入队,让你身后的士兵的编号都要往后挪。

数组也是一样,当新加入一个数据时,这就意味着它后面的数据内存地址都要往后稍一稍,删除亦如此。

2,链表 和赋值原理

链表和在内存中排列整齐的数组不同,它们像一堆散兵游勇,散布于内存中,只要哪里有空隙就往哪里钻,链表高效地运用了内存空间。虽然它们看起来杂乱无章,但其实它们井然有序,暗号让它们紧紧相连。数据与数据之间有一条“暗号”的链子相连接,那个数据在首位,那个数据在第二位……在末尾都非常清楚。

这种“暗号”其实就是内存地址,如下图,长方形就是节点,一个节点包含了两个方面的内容,数据和“暗号”,这个“暗号”其实就是下一个节点的引用信息。

链表的第一个和最后一个节点最重要和最特殊,最后一个节点则意味着后面没有数据了,所以它指向None,第一个节点的内存地址需要一个地方来保存,所以设立一个head属性对第一个节点应用。

下面来实现节点代码,一个节点需要存放数据和对下一个数据的引用:


class Node:
def __init__(self,x):
self.data = initdata #存放数据
self.next = None #对下一个节点的引用 def getData(self): #返回数据
return self.data def getNext(self): #返回下一个节点
return self.next def setData(self,newdata):
self.data = newdata def setNext(self,newnext):
self.next = newnext
 

相信很多人都有疑问,为什么把下一个节点赋给上一个节点的next就实现了内存的引用呢?这与Python的特性有关,Python没有专门的指针,所有变量即是指针。

举一个例子,a = 6,一个简单的赋值,它在内存中是怎样实现的呢?

首先在内存中会创建数据6,数据6在内存中有自己的内存地址,然后再把变量标签a指向6,如上图a这个长方形中,实际是数据6的内存地址。再比如,a,b = b,a,  这实际就是a指向原来b指向的地址,b指向原来a指向的地址。明白了内存中赋值的原理,那么对Python链表中,next  = 下一个节点,就会很清晰了,next指向下一个节点的内存地址。

三,单链表的实现

1,链表的优点和缺点

链表插入和删除数据非常快,但读取数据非常慢

  数组 链表
读取 O(1) O(N)
插入 O(N) O(1)
删除 O(N) O(1)

数组的读取非常快,因为它在内存中连续存储,插入和删除慢,是因为插入和删除都要改变相应的内存地址。

链表的插入和删除都很快,因为只要相应的改变节点中next的指向即可,链表访问一个特定数据时,必须沿着链表一个一个数据访问,所以读取很慢、

2,链表的方法

from node import Node
class UnorderedList: def __init__(self):
self.head = None def add(self,item): #添加数据
temp = Node(item)
temp.setNext(self.head) #next指向表头,head为引用表头的信息
self.head = temp #在把head指向新增加的节点 def size(self): #返回链表的size
current =self.head
count = 0
while current != None:
count +=1
current = current.getNext() return count def search(self,item): #数据是否在链表中
current = self.head
found = False
while current != None and not found:
if current.getData() == item:
found = True
else:
current = current.getNext() return found def remove(self): #删除某个数据
current = self.head
previous = None
found = False
while not found:
if current.getData == item:
found = True
else:
previous = current
current = current.getNext() if previous == None:
self.head = current.getNext() else:
            previous.setNext(current.getNext())

链表(python)的更多相关文章

  1. 从尾到头打印链表(python)

    题目描述 输入一个链表,按链表值从尾到头的顺序返回一个ArrayList. # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, ...

  2. 单链表-Python实现-jupyter->markdown 格式测试

    单链表引入 顺序表 理解Python变量的本质: 变量存储的不是值,是值的地址 理解Python的 "="表示的是指向关系 案例: 交换a,b的值, a=10, b=20 a, b ...

  3. 链表(python)

    链表1.为什么需要链表顺序表的构建需要预先知道数据大小来申请连续的存储空间,而在进行扩充时又需要进行数据的搬迁,所以使用起来并不是很灵活.链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理. ...

  4. 【数据结构】单链表介绍及leetcode206题反转单链表python实现

    题目传送门:https://leetcode-cn.com/problems/reverse-linked-list/ 文章目录 单链表介绍 链表 概念 种类 优缺点 单链表(slist) leetc ...

  5. 数据结构中的顺序表和链表(Python语言)

    转载:https://blog.csdn.net/weixin_43187669/article/details/96426362 算法是为了解决实际问题而设计的,数据结构是算法需要处理的问题载体. ...

  6. 牛客网:将两个单调递增的链表合并为一个单调递增的链表-Python实现-两种方法讲解

    方法一和方法二的执行效率,可以大致的计算时间复杂度加以对比,方法一优于方法二   1. 方法一: 思路: 1. 新创建一个链表节点头,假设这里就叫 head3: 2. 因为另外两个链表都为单调递增,所 ...

  7. 合并两个排序的链表(python)

    题目描述 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则. # -*- coding:utf-8 -*- # class ListNode: # def _ ...

  8. 反转链表(python)

    题目描述 输入一个链表,反转链表后,输出新链表的表头. # -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self ...

  9. leetcode 奇偶链表 python

    要求空间复杂度O(1) 那就只能用指针不断改链表的指针, 不能建立新的内存 时间复杂度O(1) 一遍遍历 不能嵌套循环 我的思想是: 1 如果链表元素数量小于等于2个,那就无法操作 2 能操作的情况下 ...

  10. leetcode 相交链表 python实现

    这道题 要想解决其实不难, 开两层循环进行遍历就能实现,但是会超时 如果想要O(n) 的时间复杂度, 我考虑用哈希表来存储遍历过的元素,如果发现当前遍历的元素在哈希表里,那说明交叉点就在这 这里利用了 ...

随机推荐

  1. pom.xml文件中的parent标签

    基本概念 maven的核心就算pom.xm,使用maven是为了更好地帮项目管理包依赖.如果要引入一个jar包,需要在pom文件中加上 <dependency> <groupId&g ...

  2. 搞定 CompletableFuture,并发异步编程和编写串行程序还有什么区别?你们要的多图长文

    你有一个思想,我有一个思想,我们交换后,一个人就有两个思想 If you can NOT explain it simply, you do NOT understand it well enough ...

  3. 05 ES6模块化规范基础详解

    ES6模块规范 1.1 ES6规范说明 历史上,JavaScript 一直没有模块(module)体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来.其他语言都有这项功能,比如 Ru ...

  4. Linux常用命令(学习笔记)

    命令编写以遇到的生产问题的前后为顺序进行记录 虚拟机的镜像是centos6.5版本,在这个版本下,我个人整理记录了一些在linux上常用的命令以及一些项目部署需要的jdk.tomcat.mysql等的 ...

  5. 深入理解JVM(一)Java内存区域

    运行时数据区 程序计数器 当前线程执行的字节码的行号指示器 每条线程都有独立的程序计数器,各线程之间计数器互不影响,独立存储. 如果执行的是java方法,计数器记录正在执行的虚拟机字节码指令的位置: ...

  6. CSMA/CD ,现在的交换式以太网还用吗?谈全双工,半双工与CSMA/CD的关系

    我们知道:以太网访问控制用的是CSMA/CD,即载波侦听多点接入/ 冲突检测,是以广播的方式将数据发送到所有端口: 我们还知道:交换机能主动学习端口所接设备的MAC地址,在获知该端口的MAC 地址后, ...

  7. Docker 挂载

    简介   集群当中挂载数据卷的方式采用--mount标志.而且-mount标记相比于-v意图更明确.   如果不进行数据挂载的话,当容器不在时,对应的数据也不会持久存在 存储方式 卷存储,由docke ...

  8. 让你的GitHub下载飞速提升到2M/s以上

    2020年7月27日整理发布多种GitHub加速方式! 转载自:https://code.pingbook.top/blog/2020/How-To-Speed-Github.html 1. GitH ...

  9. MySQL在同一个表上,删除查询出来的结果

    背景 有一个程序员员工表(code_user),包含用户id.姓名.掌握的语言. 表数据如下: +---------+-----------+----------+ | user_id | user_ ...

  10. PHP imageaffine - 返回经过仿射变换后的图像

    imageaffine — 返回经过仿射变换后的图像,剪切区域可选.高佣联盟 www.cgewang.com 语法 resource imageaffine ( resource $image , a ...