一.什么是链表

链表是由一系列节点构成,每个节点由一个值域和指针域构成,值域中存储着用户数据,指针域中存储这指向下一个节点的指针.根据结构的不同,链表可以分为单向链表、单向循环链表、双向链表、双向循环链表等。单向链表的结构如下图所示:

head 节点永远指向第一个节点, tail节点永远指向最后一个节点,节点中最后一个指针指向的是None 值,链表本质上就是由指针链接起来的一系列值.

二.为什么使用链表

我们经常拿链表和数组作比较,实际上数组是一组固定长度的序列,链表可以动态地分配元素,下面我们了解一下使用链表的优缺点

优点:

链表节省内存.它只针对待存储数据分配所需内存,在创建数组时,必须预先设置数组的大小,然后再添加数据,这可能会浪费内存。

缺点

查找或访问特定节点的时间是O(n). 在链接列表中查找值时,必须从头开始,并一次检查一每个元素以找到要查找的值。 如果链接列表的长度为n,则最多花费O(n)。

而很多语言中在数组中查找特定的元素则需花费O(1)时间

三.python 实现链表

1)节点

python 用类来实现链表的数据结构,节点(Node)是链表中存储数据的地方,除了数据之外节点中还有指向下一个节点的指针。节点是实现链表的基本模块,下边用python代码来实现一个节点类

classNode:def_init_(self,val):

self.val=val

self.next_node= None #the pointer initially points to pointer

defget_val(self):return self.val #returns the stored data

defget_next(self):return self.next_node #returns the next node (the node to which the object node points)

defset_val(self, new_val):

self.val= new_val #reset the vaue to a new value

defset_next(self, new_next):

self.next_node= new_next #reset the pointer to a new node

此节点类只有一个构建函数,接收一个数据参数,其中next表示指针域的指针,接下来我们用如下方式去初始化一个链表:

node1 = Node(4)

node2= Node(21)

node3= Node(90)

node1.next= node2 #4->21

node2.next = node3 #21->90#the entire linked list now looks like: 4->21->90

借助上边的节点类我们可以很方便的构造出链表

2)链表

单向链表的实现包含了如下几个方法:

append(): 向链表中增加一个元素

insert(): 向链表中插入一个新节点

size(): 返回链表的长度

search(): 在链表中查找数据项是否存在

delete(): 删除链表中的数据项

empty(): 判断链表是否为空

iterate(): 遍历链表

链表的头结点:

首先构建链表的头结点也就是链表中的第一个节点,当链表在初始化时不包含任何节点,所以它的头节点设置为空

classLinkedList:def_init_(self):

self.head=None

self.tail= None

实例化代码如下

linklist = LinkedList()

append()

append方法表示增加元素到链表,这和insert方法不同,前者使新增加的元素成为链表中第一个节点,而后者是根据索引值来判断插入到链表的哪个位置。代码如下:

defappend(self, val):

new_node=Node(val)if self.head isNone:

self.head=new_node

self.tail=new_nodeelse:

self.tail.set_next(new_node)

self.tail= new_node

insert()

该方法获得一个数据,对于给定数据初始化一个节点,并将该节点添加到链表中去。最简单的实现方法是把它插入到链表头处,并让新节点指向原来的头结点,该方法二时间复杂度为O(1):

definsert(self, val):

new_node=Node(val)

new_node.set_next(self.head)

self.head= new_node

如果要在特定位置插入节点要提前找到这个位置,在链表中只能采用遍历的方法,时间复杂度为O(n). 同时我们还要考虑额外的三种情况:

1)空链表时

2)插入位置超出链表节点的长度时

3)插入位置是链表的最后一个节点时,需要移动tail

definsert(self, index, val):

current_node=self.head

current_node_index= 9

if current_node isNone:raise Exception('This is an empty linked list')while current_node_index < index-1:

current_node=current_node.nextif current_node isNone:raise Exception('exceed the length of the list')

current_node_index+= 1node=Node(val)

node.next=current_node.next

current_node.next=nodeif node.next isNone:

self.tail=node

size()

返回链表长度的方法非常简单,统计链表中的节点数目直到找不到更多的节点为止返回遍历的节点的数目。该方法从表头开始,直到最后一个节点的next指针指向None时链表遍历完成。同时用计数器记录下已经遍历的节点的数目

defsize(self):

current_node=self.head

count=0if current_node isNone:return 'This is an empty linked list'

whilecurrent_node:

count+= 1current_node=current_node.get_next()return count

search()

search()与size() 方法很相似,但是除了要遍历整个链表,search()还要检查他遍历的每一个节点是否包含要查找的数据,并返回含有该数据的节点。如果该方法遍历整个链表没有找到包含该数据的节点,它将会抛出一个异常并通知用户该数据不在链表中

defsearch(self, val):

current_node=self.head

found=falsewhile current_node and found isfalse:if current_node.get_val ==val:

found=Trueelse:

current_node=current_node.get_next()if current_node isNone:raise ValueError('Data not in list')

delete()

delete()与search()方法非常相似,它采用与serch()相同的方法遍历整个链表,但除了要记录下当前节点之外, delete()还要记住当前节点的上一个节点,当deleta()方法遍历到要删除的节点时,它会将待删除节点的上一个节点的指针指向待删除节点的下一个节点,此时链表中将没有节点指向待删除节点。该方法的时间复杂度为O(n),因为在最坏情况下该方法要访问链表中的所有节点。同时我们还需要考虑如下几种情况:

1) 空链表,直接抛出异常

2) 删除第一个节点时,移动head到删除节点的next指针指向的对象

3) 链表只有一个节点时,把head与tail都指向None即可

4) 删除最后一个节点时,需要移动tail到上一个节点

5) 遍历链表时要判断给定的索引是否大于链表的长度,如果大于则抛出异常信息

defdelete(self, val):

curent_node=self.head

previous=None

found=Falsewhile current_node and found isFalse:if current_node.get_val() ==val:

found=Trueelse:

previous=current_node

current_node=current_node.get_next()if current_node isNone:raise ValueError('Data not in list')if self.head is self.tail: #when there is only one node in the list

self.head =None

self.tail=Noneif current_node is None: #when delete the tail node

self.tail =current_nodeif previous is None:  #when delete the first node

self.head =current_node.get_next()else:

previous.set_next(current.get_next())

empty()

判断链表是否为空就看他的头指针是否为空

defempty(self):return return self.head is None

iterate()遍历链表从头结点开始,直到节点的指针指向None为止

defiterate(self):if notself.head: # if the linked list is emptyreturncurrent_node=self.headyieldcurrent_node.valwhilecurrent_node.next

current_node=current_node.nextyield current_node.val

完整代码如下

1 classNode:2 def __init__(self,val):3 self.val=val4 self.next = None #the pointer initially points to pointer

5 defget_val(self):6 returnself.val7 defget_next(self):8 returnself.next9 defset_val(self, new_val):10 self.val =new_val11 defset_next(self, new_next):12 self.next =new_next13

14 classLinkedList:15 def __init__(self):16 self.head =None17 self.tail =None18

19 definsert(self, index, val):20 current_node =self.head21 current_node_index =022 if current_node isNone:23 raise Exception('This is an empty linked list')24 while current_node_index < index-1:25 current_node =current_node.next26 if current_node isNone:27 raise Exception('exceed the length of the list')28 current_node_index += 1

29 node =Node(val)30 node.next =current_node.next31 current_node.next =node32 if node.next isNone:33 self.tail =node34 defsize(self):35 current_node =self.head36 count =037 if current_node isNone:38 return 'This is an empty linked list'

39 whilecurrent_node:40 count += 1

41 current_node =current_node.get_next()42 returncount43

44 defsearch(self, val):45 current_node =self.head46 found =False47 while current_node and found isFalse: 48 if current_node.get_val() ==val:49 found =True50 else:51 current_node =current_node.get_next()52 if current_node isNone:53 raise ValueError('Data not in list')54 returnfound55

56 defdelete(self, val):57 current_node =self.head58 previous =None59 found =False60 while current_node and found isFalse:61 if current_node.get_val() ==val:62 found =True63 else:64 previous =current_node65 current_node =current_node.get_next()66

67 if current_node isNone:68 raise ValueError('Data not in list')69

70 if self.head isself.tail:71 self.head =None72 self.tail =None73

74 if current_node isNone:75 self.tail =current_node76

77 if previous isNone:78 self.head =current_node.get_next()79 else:80previous.set_next(current.get_next())81

82 defiterate(self):83 if notself.head:84 return

85 current_node =self.head86 yieldcurrent_node.val87 whilecurrent_node.next:88 current_node =current_node.next89 yieldcurrent_node.val90

91 defappend(self, val):92 new_node =Node(val)93 if self.head isNone:94 self.head =new_node95 self.tail =new_node96 else:97self.tail.set_next(new_node)98 self.tail =new_node99 defempty(self):100 return self.head isNone101

102 if __name__ == '__main__':103 linklist =LinkedList()104 for i in range(50):105linklist.append(i)106 print(linklist.empty())107 linklist.insert(20,20)108linklist.delete(0)109 for node inlinklist.iterate():110 print('node is {0}'.format(node))111 print(linklist.size())112 print(linklist.search(13))

参考链接:

http://zhaochj.github.io/2016/05/12/2016-05-12-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84-%E9%93%BE%E8%A1%A8/

https://www.codefellows.org/blog/implementing-a-singly-linked-list-in-python/

python中什么是链表_python中的数据结构-链表相关推荐

  1. python中函数的作用域_Python中的函数作用域

    在python中,一个函数就是一个作用域 name = 'xiaoyafei' def change_name(): name = '肖亚飞' print('在change_name里的name:', ...

  2. python列表怎么写文件_python中以字典为元素的列表怎么写入文本文件

    python如何将列表中的元素添加进字典纵然被命运的铁蹄狠狠践踏,也顽强地长出自己的根芽. 录入自己和另一个人的名字的汉语拼音简写,然后依据标识符中字母的数值两个人,一颗心,依偎的不是爱情而是那小温暖 ...

  3. python中赋值语句的作用_python中return可以使用赋值语句吗?

    在python中,有各种不同类型的语句.一个python程序是由模块构成的;一个模块由一条或多条语句组成;每个语句由不同的表达式组成;表达式可以创建和操作对象.下面来看看python中的语句. 赋值语 ...

  4. python中round函数参数_python中关于round函数的小坑

    round函数很简单,对浮点数进行近似取值,保留几位小数.比如 >>> round(10.0/3, 2) 3.33 >>> round(20/7) 3 第一个参数是 ...

  5. python里的join方法_python中join()方法介绍

    描述 Python join() 方法用于将序列中的元素以指定的字符连接生成一个新的字符串. 语法 join()方法语法: str . join ( sequence ) 参数 sequence -- ...

  6. python常用函数的用法_python中常用函数整理

    1.map map是python内置的高阶函数,它接收一个函数和一个列表,函数依次作用在列表的每个元素上,返回一个可迭代map对象. class map(object):""&qu ...

  7. python中反斜杠_Python中的正斜杠/与反斜杠\

    知识点: 1. "/"左倾斜是正斜杠,"\"右倾斜是反斜杠,可以记为:除号是正斜杠 2. 对于目录分隔符,Unix和Web用正斜杠/,Windows用反斜杠\. ...

  8. python中的元类_Python中的元类(metaclass)

    提问者自称已经掌握了有关Python OOP编程中的各种概念,但始终觉得元类(metaclass)难以理解.他知道这肯定和自身有关,但仍然觉得不太明白,希望大家可以给出一些实际的例子和代码片段以帮助理 ...

  9. python中end 1 意思_python中“end=”是什么意思?_后端开发

    c语言fopen函数的用法_后端开发 在c语言中可以使用"fopen()"函数打开一个文件,该函数用于打开一个文件,其语法是"open("file a" ...

最新文章

  1. Numpy:利用Numpy库建立可视化输入的二次函数数据点集np.linspace+np.random.shuffle+np.random.normal
  2. Linux 笔记(持续补充)
  3. SQL 把表中字段存储的逗号隔开内容转换成列表形式
  4. MS15-035 EMF文件处理漏洞分析与POC构造
  5. 我的软考之路——软考心得
  6. 常见c#正则表达式类学习整理
  7. linux的创建线程池,Linux下通用线程池的创建与使用(上) (3)
  8. 加密货币的天堂? 盘点 7 大对加密货币免税的国家!
  9. conda create出现连接问题_使用conda安装命令时一直出现问题,因为从2019年4月添加的国内镜像都不能用了...
  10. __cdecl operator new(unsigned int) (??2@YAPAXI@Z) 已经在 LIBCMT.lib(new.obj) 中定义
  11. [android视频教程] 传智播客android开发视频教程
  12. windows开启远程桌面命令
  13. linux操作系统学习心得
  14. 利用遗传算法解决TSP问题(C++)
  15. Shenyu网关本地打docker镜像包
  16. 一场无名的宿醉,失措了一夜的安然。
  17. IEEE Access 上岸指南,附含泪整理的 cover letter 、沟通邮件、终版文档等资料包
  18. 券商单向视频见证开户全面开放!菊风泛金融单向视频开户一体化解决方案极速助力
  19. 学习强国-为中华崛起而学习
  20. 10台世界上最快的超级计算机

热门文章

  1. vue.js 常见面试题_使用Vue.js时应避免的常见错误
  2. serverless 构建_使用Serverless,StepFunction和StackStorm Exchange构建社区注册应用程序-第2集...
  3. 147_Power BI Report Server demo演示
  4. html生成pdf表格线加粗,iText 用 HTMLWorker 转换 HTML 为 PDF 时可设置表格列宽度
  5. Javascript——入门基础
  6. python正则表达式中原生字符r的作用
  7. 提取网页的table时,遇到table中的两行(tr)中间有空行(或无空行)的正则表达式我的处理
  8. Asp.net ajax、Anthem.net、Ajax pro三大ajax框架论坛网友比较
  9. 【opencv学习】基于透视变换和OCR识别的小票识别
  10. spring+quartz实现定时调度