CodeSalt | Python数据结构的实现 — 链表

范成
• 阅读 6727

Python数据结构实现—链表

1. 简单介绍

链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。—— 维基百科

链表的基本构造块是节点(Node)。我们将在文章的第2部分通过Python实现一个简单的Node类。

一个单向链表的构造如下图1所示包含两个域:

  1. 信息域:当前节点的值(Data or Value)
  2. 指针域:指向下一个节点的指针链接(Reference or Link)

CodeSalt | Python数据结构的实现 — 链表

注1:必须明确指定链表的第一项的位置。一旦我们知道第一项在哪里,第一项目可以告诉我们第二项是什么,依次类推。按照一个方向遍历,直到最后一项(最后一个节点),最后一项需要知道没有下一项。
注2:这些节点在逻辑上是相连的,但要知道它们在物理内存上并不相连。

2. 准备工作

2.1 Node类

我们先来实现Node类:

class Node(object):
    def __init__(self, initdata):
        self.data = initdata
        # 引用None代表没有下一节点
        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

创建一个Node对象试试:

>>> tmp = Node(33)
>>> tmp
<__main__.Node object at 0x1022699b0>
>>> tmp.getData()
33

2.2 Unordered List类

只要知道第一个节点(包含第一个项),那么之后的每个节点都可以通过指向下一个节点的链接 依次找到。
考虑到这样的情况,Unordered List类只要维护对第一个节点的引用就可以了。Unordered List类本身不包含任何节点对象,它只包含对链表结构中第一个节点的单个引用

class unOrderedList():
    def __init__(self):
        # 初始化None表示此时链表的头部不引用任何内容
        self.head = None

创建一个空的链表试试(如图2所示):

>>> myList = unOrderedList()

CodeSalt | Python数据结构的实现 — 链表

我们可通过下面的 isEmpty() 方法检查是否为空链表:

# 只有在链表中没有节点的时候为真
def isEmpty(self):
    return self.head == None

添加元素后的链表是这样的(如图3所示),稍后在文章第3部分实现添加方法:
CodeSalt | Python数据结构的实现 — 链表

3. 基本操作的实现

3.1 add()在链表前端添加元素

由于是在前端添加,因此最后添加的在最前端。

def add(self, item):
    temp = Node(item) # Step0:创建一个新节点并将新项作为数据
    temp.setNext(self.head) # Step1:更改新节点的下一个引用以引用旧链表的第一个节点
    self.head = temp # Step2:重新设置链表的头以引用新节点

添加元素——执行mylist.add(26)时候的图解如下:

>>> mylist.add(31)
>>> mylist.add(77)
>>> mylist.add(17)
>>> mylist.add(93)
>>> mylist.add(26)

CodeSalt | Python数据结构的实现 — 链表

3.2 size()求链表长度

def size(self):
    current = self.head
    count = 0
    while current != None:
        count += 1
        current = current.getNext()
    return count

通过current遍历链表并对节点计数。
图解如下:
CodeSalt | Python数据结构的实现 — 链表

3.3 search()查找

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

通过current遍历链表,使用found标记是否找到了正在寻找的项。
图解如下:
CodeSalt | Python数据结构的实现 — 链表

3.4 remove()删除

def remove(self, item):
    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:
    # 当要删除的项目恰好是链表中的第一个项,这时候prev是None,需要修改head以引用current之后的节点
        self.head = current.getNext()
    else:
        previous.setNext(current.getNext())
3.4.1 上面的特殊情况,即要删除的恰好是第一个节点的图解如下:

CodeSalt | Python数据结构的实现 — 链表

3.4.2 其他情况,即要删除的是链表中的节点(非第一个):

我们遍历链表,先搜索,再删除。
1.搜索:
使用previouscurrent进行移动,借助found标记是否找到。
一旦found为True,current就是对包含要删除的项的节点的引用。
2.删除(修改引用):
我们把previous的对下一节点的引用设为current的下一节点。

以上两过程的图解如下:
CodeSalt | Python数据结构的实现 — 链表
CodeSalt | Python数据结构的实现 — 链表

参考:
problem-solving-with-algorithms-and-data-structure-using-python
python-wikipedia

如有错误,还望指正~
完整实现及测试可在Github找到:Python-DataStructure-Implementation
感谢。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
22 22
4年前
【数据结构之链表】看完这篇文章我终于搞懂链表了
一览:本文从零介绍链式存储结构的线性表——单链表。包括以下内容:什么是链式存储存储结构?单链表的结构辨析头结点、头指针等易混淆概念基本的增删改查操作(不带头结点和带头结点)单链表与顺序表的对比线性表的链式存储结构在一文中我们介绍了一种“用曲线连接”的线性表,“曲线”是一种形象化的语言,实际上并不会存在所谓“曲线”的这种东西。所谓“曲线连
似梦清欢 似梦清欢
2年前
查找算法
顺序查找顺序查找又称为线性查找,对线性表和链表都适用。线性表可以通过数组下标递增来顺序扫描每个元素,链表可以通过next指针依次扫描每一个元素。:::tip指针实现顺序表时,顺序表中是指针时,在定义顺序表的结构体后,需要对顺序表初始化,初始化时为指针申请堆
Stella981 Stella981
3年前
Boost(1.69.0) windows入门(译)
<head<title缩进2字符</title<styletype"text/css".yindent,.yblock{padding:1em1em01em;marginright:0;}.yindent{margin:0.7em2em;border:mediumoutset;}.yblock{margin
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
Java实现单链表反转操作
单链表是一种常见的数据结构,由一个个节点通过指针方式连接而成,每个节点由两部分组成:一是数据域,用于存储节点数据。二是指针域,用于存储下一个节点的地址。在Java中定义如下:publicclassNode{privateObjectdata;//数据域privateNodenext;//指针域publicNo
Wesley13 Wesley13
3年前
D1
1\.数据结构  1.1线性结构  (1)最常用的数据结构,特点是数据元素之间存在一对一的线性关系  (2)有两种不同的存储结构,即顺序存储结构和链式存储结构    顺序存储的线性表称为顺序表,顺序表中的存储元素是连续的    链式存储的线性表称为链表,链表中的存储元素不一定是连续的,元素节点中存放数据元素以及相邻元素的地址信息
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
菜园前端 菜园前端
2年前
什么是链表?
原文链接:什么是链表?链表是有序的数据结构,链表中的每个部分称为节点。可以首、尾、中间进行数据存取,链表的元素在内存中不必是连续的空间,每个节点通过next指针指向下一个节点。优点链表的添加和删除不会导致其余元素位移。缺点无法根据索引快速定位元素。数组和链
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(