python数组和链表结构_数据结构--python实现链表结构

在c++中,我们以指针的形式直接访问数据的地址,在这些较为现代的预言中,单链表结构中的一个节点,包含了一个数据项和指针值。一个特殊的空值(或nil),表示指针值是一个空链接。我们并不使用数组来构建不连续的内存,而是直接向计算机请求一个指针指向一个新的节点,这个节点来自于名为对象堆的一个内建的不连续内存区域。然后,我们在该节点中设置了指向另一个节点的指针,由此建立了到结构中的其他数据的一个链接。然而,c++中得通过一种特殊的处理或删除操作,来向其返回那些不再使用的节点。

python程序员使用对 对象的引用建立起了节点和链表结构。在Python中,任何变量都可以引用任何内容,包括None值,它意味着一个空的链接。由此。Python程序员通过定义包含两个字段的一个对象,从而定义了一个单链表节点。这两个字段是:数据项的一个引用和到另一个节点的一个引用。Python为每一个新的节点对象提供了动态分配的非连续的内存,并且当对象不再被引用程序引用的时候,会自动把内存返回给系统(垃圾收集)。

定义一个单链表节点类。

如下是一个简单的、单链表节点类的代码,代码放在模块node.py中。

"""

File: node.py

定义一个单链表节点类

"""

class Node(object):

def __init__(self,data,next = None):

self.data = data

self.next = next

创建一个单链表结构,并且访问输出其内容:

"""

File: testnode.py

测试节点类。

"""

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

#输出节点内容,输出完后,单链表结构也销毁了

while head != None:

print(head.data) #输出:5, 4, 3, 2, 1

head = head.next

单链表结构创建好后其结构如下图:168101489_1_20190809073954788

head为头指针,指向第一个节点对象(head为变量,是第一个节点对象的引用),最后一个节点对象的字段值next为None值。

单链表结构上的操作

1. 遍历

遍历操作需要一个临时变量,这个变量先初始化为链表结构的head指针,然后控制一个循环,如下所示:

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

probe = head

#输出节点内容,输出完后,单链表结构依然存在

while probe != None:

print(probe.data) #输出:5, 4, 3, 2, 1

probe = probe.next

通常,遍历一个单链表结构会访问每一个节点,并且当遇到一个空链接的时候终止。因此,值None充当负责停止这个过程的哨兵。

遍历在时间上是线性的,并且不需要额外的内存。

2. 搜索

在这个例子中,会出现两个可能的哨兵:

空链接,表明不再有要检查的数据。

等于目标项的一个数据项,表明一次成功的搜索。

如下是搜索一个给定项的代码:

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

probe = head

targetItem = 3 #搜索链表结构中是否存在数据项为3的节点

while probe != None and targetItem != probe.data:

probe = probe.next

if probe != None:

print("目标数据项targetItem已搜索到")

else:

print("目标数据项targetItem不存在于当前链表结构中")

若 nn 是链表结构中节点数目,访问第 ii 项的代码如下,其中 0 <= i < n。

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

probe = head

index = 2 #第2个数据项,数据项从0开始

while index > 0:

probe = probe.next

index -= 1

print(probe.data) #输出3

3. 替换

替换一个给定的项,代码如下:

# -*- coding: utf-8 -*-

"""

Created on Sun Jul 1 20:44:10 2018

@author: aoanng

"""

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

probe = head

targetItem = 3 #搜索链表结构中是否存在数据项为3的节点,并替换

newItem = 20 #替换搜索到的目标项

while probe != None and targetItem != probe.data:

probe = probe.next

if probe != None:

probe.data = newItem

print(probe.data) #输出20

else:

print("该链表结构中不存在目标项targetItem")

还有一个替换第 ii 项的操作,它假设 0 <= i < n。其代码如下:

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

probe = head

index = 3 #搜索链表结构中第3个数据项,并替换

newItem = 20 #替换搜索到的目标项

while index > 0:

probe = probe.next

index -= 1

probe.data = newItem

print(probe.data) #20

4. 插入

1、在开始处插入

代码如下:

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

newItem = 20

head = Node(newItem,head) #在开始处插入

2、在末尾插入

对于单链表结构来说,在末尾插入一项必须考虑如下两种情况:

head指针为None,此时,将head指针设置为新的节点

head指针不为None,此时,代码将搜索最后一个节点,并将其next指针指向新的节点。

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

newItem = 20

newNode = Node(newItem) #节点

if head is None:

head = newNode

else:

probe = head

while probe.next != None:

probe = probe.next

probe.next = newNode

3、在任何位置插入

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

newItem = 20

index = 3 #在第3个节点插入,从0开始排序

#如果链表为空或者index小于等于0,即在链表头部插入

if head is None or index <= 0:

head = Node(newItem,head)

else:

probe = head

#不能超过链表结构的长度

while index > 1 and probe.next != None:

probe = probe.next

index -= 1

probe.next = Node(newItem,probe.next)

插入之后单链表结构如下图所示:

168101489_2_20190809073955210

5. 删除

1、在开始处删除

通常假设链表结构中至少有一个节点。其代码如下:

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

removeItem = head.data

head = head.next # 在开始处删除

print(removeItem) # 5

print(head.data) # 4

2、从末尾删除

只有一个节点。head指针设置为None

在最后一个节点之前没有节点。代码搜索倒数第2个节点并将其next指针设置为None。

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

removeItem = head.data

if head.next is None:

head = None

else:

probe = head

while probe.next.next != None:

probe = probe.next

removeItem = probe.next.data

probe.next = None

print(removeItem) # 1

3、 在任意位置删除

i <= 0———-使用删除第一项的代码

0 < i < n——-搜索位于i-1位置的节点,删除其后面的节点

i>=n————删除最后一个节点

from node import Node

head = None

#创建一个单链表结构

for count in range(1,6):

head = Node(count,head)

index = 2 # 待删除的项

if index <= 0 or head.next is None:

removeItem = head.data

head = head.next

print(removeItem)

else:

probe = head

while index > 1 and probe.next.next != None:

probe = probe.next

index -= 1

removeItem = probe.next.data

probe.next = probe.next.next # None

print(removeItem) # 3

6. 复杂度权衡:时间、空间和单链表结构

操作

运行时间

在第 i 个位置访问

O(n),平均情况

在第 i 个位置替换

O(n),平均情况

从开始处插入

O(1),最好情况和最差情况

从开始处删除

O(1),最好情况和最差情况

在第 i 个位置插入

O(n),平均情况

在第 i 个位置删除

O(n),平均情况

循环链表

在这个实现中,至少总是有一个节点。这个节点也就是哑头节点,它不包含数据,但是充当了链表结构的开头和结尾的一个标记。其结构如下图所示:

168101489_3_20190809073955350

对第 i 个节点的额搜索,从哑头节点之后的节点开始。假设这个空的链表的最初结构如下所示:

from node import Node

#创建一个空循环链表

head = Node(None,None)

head.next = head

如下是在第 i 个位置插入节点的代码,它使用了这个链表结构的新的表示:

from node import Node

#创建一个空循环链表,head指向哑头节点

head = Node(None,None)

head.next = head

probe = head

index = 10

newItem = 20

while index > 0 and probe.next != head:

probe = probe.next

index -= 1

probe.next = Node(newItem,probe.next)

这种实现的优点在于,插入和删除操作只需要考虑一种情况,即第 i 个节点位于当前的第 i 个节点和它的前一个节点之间的这种情况。

双链表结构

双链表结构比单链表结构更有优越性。它允许用户做如下的事情:

从给定的节点,向左移动到前一个节点。

直接移动到最后一个节点。

下图展示了包含3个节点的一个双向链表结构。注意,每个节点中有两个指针,通常称为next和previous。还要注意,有一个外部的tail指针,它允许直接访问结构中的最后一个节点。168101489_4_20190809073955632

双链表结构的节点类的python实现,通过给previous指针添加一个字段,扩展了前面所讨论的Node类。如下是这两个类的代码:

"""

File: node.py

定义单链表和双链表类

"""

class Node(object):

def __init__(self,data,next = None):

self.data = data

self.next = next

class TwoWayNode(Node):

def __init__(self,data,previous = None, next = None):

Node.__init__(self,data,next)

self.previous = previous

如下是测试程序,它通过在末尾添加项来创建一个双链表结构。然后,程序从最后一项开始朝着第一项处理,最终显示了整个链表结构的内容:

"""

File: testtwowaynode.py

测试双链表类

"""

from node import TwoWayNode

#创建一个节点的双链表结构

head = TwoWayNode(1)

tail = head

# 在之前创建的链表结构后面添加4个节点

for data in range(2,6):

tail.next = TwoWayNode(data,tail)

tail = tail.next

probe = tail

while probe != None:

print(probe.data) #5,4,3,2,1

probe = probe.previous

参考:

本篇博客整理于 《数据结构(python语言描述)》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值