python 标准库并没有实现链表,所以我们得自己实现链表。

什么是链表

链表是计算机科学中最常用的数据结构之一。它也是最简单的结构之一,也是更高层结构(如堆栈、循环缓冲区和队列)的基础。

一般来说,列表是通过引用连接的单个数据元素的集合。C程序员知道这是指针。例如,数据元素可以由地址数据、地理数据、几何数据、路由信息或事务细节组成。通常,链接列表的每个元素都具有特定于列表的相同数据类型

单个列表元素称为节点。节点不同于顺序存储在内存中的数组。相反,它可能会在不同的内存段中找到它们,您可以通过跟踪从一个节点到下一个节点的指针找到这些内存段。通常使用nil元素标记列表的结尾,该元素由python等效的None表示。

链表类型

单链表

有两种列表-单链接列表和双链接列表。单个链接列表中的节点只指向列表中的下一个元素,而双链接列表中的节点也指向上一个节点。数据结构占用更多的空间,因为您需要一个额外的变量来存储链表的引用。

@单链列表

双链表

一个链表可以从头到尾遍历,而反向遍历则比较难。相反,双链接列表允许以相同的成本在两个方向上遍历节点,无论从哪个节点开始。此外,添加和删除节点以及拆分单个链接列表的步骤不超过两个。在双链接列表中,必须更改四个指针。(详情可见添加删除方法)

@双链表

这篇博文,我们将一步步建立自己的链表。首先,我们为节点创建一个对应的数据结构。其次,您将学习如何实现和使用一个单链接列表,最后是一个双链接列表。

Step 1: Node as a Data Structure

我们建立一个Node 的节点类。该类有两个属性变量存储数据的data和指向下一个节点的引用next。

__init_(): 初始化节点的方法

self.data: 储存在节点中的数据

self.next: 下个节点的引用

has_value(): 是否包含这个值的节点

# 1。__init_(): initialize the node with the data

# 2。self.data: the value stored in the node

# 3。self.next: the reference pointer to the next node

# 4。 has_value(): compare a value with the node value

class Node:

def __init__(self, data):

"constructor to initiate this object"

# store data

self.data = data

# store reference (next item)

self.next = None

return

def has_value(self, value):

"method to compare the value with the node data"

if self.data == value:

return True

else:

return False

Step 2: Creating a Class for a Single-Linked List

这一步我们建立一个叫 SingleLinkedList 的类。该类包含一下方法

__init__(): 初始化方法

list_length():返回节点数

output_list(): 打印方法

add_list_item(): 添加一个节点到list 中

unordered_search(): 在列表中查找具有指定值的节点

remove_list_item_by_id(): 通过节点id 移除节点

初始化方法

定 head 和tail属性

class SingleLinkedList:

def __init__(self):

"constructor to initiate this object"

self.head = None

self.tail = None

return

添加

def add_list_item(self, item):

"add an item at the end of the list"

#如果不是 Node,构建为Node

if not isinstance(item, Node):

item = Node(item)

#如果头节点是空,则当前节点就是 item

if self.head is None:

self.head = item

else:

#如果已经有头节点,则加到尾部

self.tail.next = item

#尾部就是当前绩点item了

self.tail = item

return

定义返回节点长度方法

def list_length(self):

"returns the number of list items"

count = 0

current_node = self.head

while current_node is not None:

# increase counter by one

count = count + 1

# jump to the linked node

current_node = current_node.next

return count

定义输出方法

def output_list(self):

"outputs the list (the value of the node, actually)"

current_node = self.head

while current_node is not None:

print(current_node.data)

# jump to the linked node

current_node = current_node.next

return

查询

查询列表,返回指定值的node 位置list

def unordered_search(self, value):

"search the linked list for the node that has this value"

# define current_node

current_node = self.head

# define position

node_id = 1

# define list of results

results = []

while current_node is not None:

if current_node.has_value(value):

results.append(node_id)

# jump to the linked node

current_node = current_node.next

node_id = node_id + 1

return results

删除

def remove_list_item_by_id(self, item_id):

"remove the list item with the item id"

current_id = 1

current_node = self.head

previous_node = None

while current_node is not None:

#当前这个node 就是需要移除的node

if current_id == item_id:

# if this is the first node (head)

#如果这个node 前面还有node ,那需要把前面node 的next,指向当前node 的下一个node(原来前一个node 的next 是当前node)。

# 就已经从这个链路里移除了,因为没有node 指向它了。

if previous_node is not None:

previous_node.next = current_node.next

else:

#需要移除的是第一个node,只要把当前的head 指向下一个node 即可

self.head = current_node.next

# we don't have to look any further

return

# needed for the next iteration

# 如果还不是当前node,上一个node 变成当前node

# 当前node 变成当前node 的下一个。当然id 要加1

previous_node = current_node

current_node = current_node.next

current_id = current_id + 1

return

测试以上方法

我们使用一下代码,测试下以上方法。

# create three single nodes

node1 = ListNode(15)

node2 = ListNode(8.2)

node3 = ListNode("Berlin")

node4 = ListNode(15)

track = DoubleLinkedList()

print("track length: %i" % track.list_length())

for current_node in [node1, node2, node3, node4]:

track.add_list_item(current_node)

print("track length: %i" % track.list_length())

track.output_list()

results = track.unordered_search(15)

print(results)

track.remove_list_item_by_id(4)

track.output_list()

Step 3: Creating a Double-Linked List

本来我们可以通过继承的方式,复用 Node 方法。但为了更清晰。我们再建立一个Node2 作为基本节点。

class Node2:

def __init__(self, data):

"constructor class to initiate this object"

# store data

self.data = data

# store reference (next item)

self.next = None

# store reference (previous item)

self.previous = None

return

def has_value(self, value):

"method to compare the value with the node data"

if self.data == value:

return True

else:

return False

建立 DoubleLinkedList

from Add_Two_Numbers.Node2 import Node2

class DoubleLinkedList:

def __init__(self):

"constructor to initiate this object"

self.head = None

self.tail = None

return

def list_length(self):

"returns the number of list items"

count = 0

current_node = self.head

while current_node is not None:

# increase counter by one

count = count + 1

# jump to the linked node

current_node = current_node.next

return count

def output_list(self):

"outputs the list (the value of the node, actually)"

current_node = self.head

while current_node is not None:

print(current_node.data)

# jump to the linked node

current_node = current_node.next

return

def unordered_search (self, value):

"search the linked list for the node that has this value"

# define current_node

current_node = self.head

# define position

node_id = 1

# define list of results

results = []

while current_node is not None:

if current_node.has_value(value):

results.append(node_id)

# jump to the linked node

current_node = current_node.next

node_id = node_id + 1

return results

#略有不同

def add_list_item(self, item):

"add an item at the end of the list"

if isinstance(item, Node2):

#如果还没有Node,则首尾都是item,而且该node 的前一个没有,后一个也没有

if self.head is None:

self.head = item

item.previous = None

item.next = None

self.tail = item

else:

#如果有Node 元素了,则当前尾部的node的下一个node 就是item,item的前一个元素就是当前的tail node。现在把item 放到尾部。

self.tail.next = item

item.previous = self.tail

self.tail = item

return

#根据node id 移除node

def remove_list_item_by_id(self, item_id):

"remove the list item with the item id"

current_id = 1

current_node = self.head

#当前node 不为空

while current_node is not None:

previous_node = current_node.previous

next_node = current_node.next

#当前node 就是需要移除的node

if current_id == item_id:

# if this is the first node (head)

#当前node 不是第一个head node

if previous_node is not None:

#前一个node的 next 指向 下个node

previous_node.next = next_node

# 如果当前node 不是tail node

if next_node is not None:

# next_node 前一个node 指向 当前node 的前一个node(原来next_node 的前一个node 是 当前node)

next_node.previous = previous_node

else:

#如果需要移除的是head node,则把head 指向 next_node

self.head = next_node

# 如果 head node 不是最后一个node ,则还要把下一个node 的 previous 指向为None(原来为当前node)

if next_node is not None:

next_node.previous = None

# we don't have to look any further

return

# needed for the next iteration

current_node = next_node

current_id = current_id + 1

return

总结

链表作为数据结构易于实现,并且提供了很大的使用灵活性。这是用几行代码完成的。作为改进,您可以添加一个节点计数器(count),它只保存列表中节点的数量。这样可以把查询列表长度复杂度降低到 O(1),您不必遍历整个列表。

python链表_手把手实现 python 的链表数据结构相关推荐

  1. python卸载_手把手教Python环境安装

    Anaconda集成环境 Python3.7 如果是linux环境包括MacOs,系统环境中会默认安装python2.7. 尽量量不不要卸载linux环境中的默认python环境,直接安装Python ...

  2. python没有指针如何实现链表_[转]为什么python标准库没有实现链表

    实际上刚开始学习一些高级语言的时候我也有同样的疑问,而且即使有链表对应物的语言,链表常常也很少被实际使用. 如果是在国外听数据结构的课,老师一般会警告你这只是一个理论概念,实际应用应该实际考察,在通常 ...

  3. python编的俄罗斯方块游戏_手把手制作Python小游戏:俄罗斯方块(一)

    手把手制作Python小游戏:俄罗斯方块1 大家好,新手第一次写文章,请多多指教 A.准备工作: 这里我们运用的是Pygame库,因为Python没有内置,所以需要下载 如果没有pygame,可以到官 ...

  4. python图形小游戏代码_手把手制作Python小游戏:俄罗斯方块(一)

    手把手制作Python小游戏:俄罗斯方块1 大家好,新手第一次写文章,请多多指教 A.准备工作: 这里我们运用的是Pygame库,因为Python没有内置,所以需要下载 如果没有pygame,可以到官 ...

  5. python 多核并行计算_手把手 | 嫌Python太慢?并行运算Process Pools三行代码给你4倍提速!...

    大数据文摘作品,转载要求见文末 作者 | Adam Geitgey 编译 | 元元.Lisa.Saint.Aileen 原文链接 | https://medium.com/@ageitgey/quic ...

  6. python 切片_全面解读Python高级特性切片

    大家好,欢迎来到Crossin的编程教室! 众所周知,我们可以通过索引值(或称下标)来查找序列类型(如字符串.列表.元组-)中的单个元素,那么,如果要获取一个索引区间的元素该怎么办呢? 切片(slic ...

  7. python 堆排序_堆排序用python

    Python天天美味(30) - python数据结构与算法之快速排序 快速排序的原理是将取出第一个数,将整个数组分为两波,一拨都大于这个数,另一波都小于这个数,然后递归用同样的方法处理第一波数字和第 ...

  8. 学习python课程_想学习Python吗? 这是我们的免费4小时互动课程

    学习python课程 Python is a popular, versatile and easy-to-learn language. It's the go-to language for AI ...

  9. 2018年python薪资_最好的Python:2017和2018年至今我最喜欢的文章集

    2018年python薪资 我打算发布此收藏集 (My intention with publishing this collection) Last year I only used Medium ...

最新文章

  1. SAP零售:补货 Vs 多步骤补货
  2. 工控攻防演示——从外网到内网控制系统设备的入侵
  3. 计算机网络与影视多媒体技术 南京理工大学,计算机网络多媒体数学库和课件结构设计-计算机仿真论文-计算机论文(8页)-原创力文档...
  4. 台北到淡水版Firefox无法播放视频
  5. Servlet页面跳转实现方法的区别
  6. solr6.6+jetty+centos+mysql
  7. 黄聪:Delphi 日期格式问题 - is not a valid date
  8. endnote大客户版_Endnote软件的使用,有图有干货!
  9. RocketMQ安装使用
  10. Flask 框架 是 Python 中最流行的 Web 框架之一
  11. 苹果好还是华为好_苹果手机好还是华为手机好?专业手机测评师给出答复!
  12. 1、pandas使用sort_values排序
  13. UVC系列2-探索Android UVC协议
  14. word课程表设置符号与编号_小学生课程表word模板 小学生使用WORD.doc
  15. C语言实现简单 词法分析程序(编译原理)
  16. linux下运行workman,笔记:Linux(AWS Redhat)开机启动workman进程(/etc/rc.local必须是755权限)...
  17. html 正方形字符,HTML常用标签以及特殊符号
  18. 对象可以创建数组吗_企业微信活码如何创建?活码可以统计渠道来源吗?
  19. Process finished with exit code 134
  20. 永善县黄华镇大永高速通车了

热门文章

  1. linux 解压缩一个文件夹下所有的压缩文件
  2. 初学关键段容易忽略的问题
  3. 去除eclipse打开后不断update的问题
  4. 杭电1596find the safest road
  5. 给定单链表,检测是否有环等系列考题
  6. html 如何 创建目录,html - javascript:如何自动生成一篇文章的目录
  7. python编程(关于cocos2d)
  8. python编程(改进的线程同步方式)
  9. jq自动获取html的值,jquery如何获取class值?
  10. linux 多块硬盘 snmp,[技术干货] Zabbix使用snmp监控Linux硬盘大小不准问题