python链表结构_Python数据结构-链表

数据结构-链表

链表是实现了数据之间保持逻辑顺序,但存储空间不必按顺序的方法。可以用一个图来表示这种链表的数据结构:

1320444-20191224090359034-1085167336.png

链表中的基本要素:

结点(也可以叫节点或元素),每一个结点有两个域,左边部分叫:值域,用于存放用户数据;右边叫:指针域,一般是存储着到下一个元素的指针

head结点,head是一个特殊的结节,head结点永远指向第一个结点

tail结点,tail结点也是一个特殊的结点,tail结点永远指向最后一个节点

None,链表中最后一个结点指针域的指针指向None值,因也叫:接地点,所以有些资料上用电气上的接地符号代表None

链表的常用方法:

LinkedList() 创建空链表,不需要参数,返回值是空链表

is_empty() 测试链表是否为空,不需要参数,返回值是布尔值

append(data) 在尾部增加一个元素作为列表最后一个。参数是要追加的元素,无返回值

iter() 遍历链表,无参数,无返回值,此方法一般是一个生成器

insert(idx,value) 插入一个元素,参数为插入元素的索引和值

remove(idx)移除1个元素,参数为要移除的元素或索引,并修改链表

size() 返回链表的元素数,不需要参数,返回值是个整数

search(item) 查找链表某元素,参数为要查找的元素或索引,返回是布尔值

节点类

python用类来实现链表的数据结构,节点(Node)是实现链表的基本模块,每个节点至少包括两个重要部分。首先,包括节点自身的数据,称为“数据域”(也叫值域)。其次,每个节点包括下一个节点的“引用”(也叫指针)

下边的代码用于实现一个Node类:

1 classNode:2 '''定义一个节点类'''

3 def __init__(self, data):4 self.data =data5 self.next = None

此节点类只有一个构建函数,接收一个数据参数,其中next表示指针域的指针,实例化后得到一个节点对象,如下:

1 node = Node(4)

此节点对象数据为4,指针指向None。

这样一个节点对象可以用一个图例来更形象的说明,如下:

1320444-20191224091631157-1713680547.png

链表类

先来看LinkedList类的构建函数:

1 classLinkedList:2 '''构建LinkedList类'''

3 def __init__(self):4 self.head =None5 self.tail = None

此类实例后会生成一个链表对象,初始化了head和tail节点,且两节点都指向None,实例化代码如下:

1 link_list = LinkedList()

也可以用图形象的表示这个链表对象,如下:

1320444-20191224092327416-707092089.png

is_empty方法实现

is_empty方法检查链表是否是一个空链表,这个方法只需要检查head节点是否指向None即可,代码如下:

1 defis_empty(self):2 return self.head is None

如果是空列表返回True,否则返回False

append方法实现

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

1 defappend(self, data):2 node =Node(data)3 if self.head isNone:4 self.head =Node5 self.tail =Node6 else:7 self.tail.next =node8 self.tail = node

既然要新增加节点,首先把Node类实例化得到一个node对象。这里有两种情况需要考虑,一是链表是一个空链表时怎样append一个节点;二是当链表不是空链表时又怎样append一个节点?

当if self.head is None: -> True时,把链表的head和tail都指向了node,假如我们执行了

1 link_list(append(4))

此时的链表结构如下图:

1320444-20191224095546544-1715164807.png

当if self.head is None: -> False时,说明链表已经增加了一个节点了,再增加一个节点时head已经指向了第一个节点,所以不为None,比如增加的第二个节点为:

1 link_list(append(5))

增加第二个节点的操作需要分两步完成,第一步:self.tail.next = node,即把上一个节点的next指针指向当前node;第二步:self.tail = node,把tail移动到node,如下图:

1320444-20191224100106685-1540803595.png

移动完成后就成这样了:

1320444-20191224100201142-1442755174.png

当增加第三个、第四个等节点时,按照上边的操作依次类推。

iter方法实现

iter方法表示遍历链表。在遍历链表时也要首先考虑空链表的情况。遍历链表时从head开始,直到一个节点的next指向None结束,代码如下:

1 defiter(self):2 if notself.head:3 return

4 cur =self.head5 yieldcur.data6 whilecur.next:7 cur =cur.next8 yield cur.data

当是遍历一个空链表时,if not self.head : -> True,直接返回None;如果不是空链表就让一个局部变量cur指向head,并把head的data属性yield出来,再对cur的next指针指向的对象做while循环,直到next指向None,这样就遍历了链表。

insert方法实现

假如采取append方法又增加了两个节点,增加完成后如下图:

1320444-20191224101141775-642886311.png

如果想在数据域为6的那节点处插入一个节点,需要做的操作有两步:

把新节点的next指针指向数据域为6的这个节点,即为数据域为5节点的next指向指向的对象

把数据域为5节点的next指针指向新加的节点

注: 这两个步骤不能颠倒,如果颠倒,数据域为6的节点会被丢失,数据域为7的节点不再是链表的节点。

示意图如下:

1320444-20191224101559835-2068202828.png

还要额外考虑两种情况:

空链表时

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

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

当是在链表最后一个节点插入时,示意图如下:

1320444-20191224101730504-1519185684.png

要在指定的索引位置插入一个节点,前提是需要找到这个位置,在链表中只有采用遍历的方式,具有O(n)的速度,最糟糕时会遍历链表的所有节点,而当找到插入点时,我们并不需要当前节点的信息,而是需要前一个节点的信息,所以代码中巧妙的使用了while cur_idx < idx-1:的方式,这样能使用cur这个变量能指向插入点上一个节点对象。

实现insert方法的代码如下:

1 definsert(self, idx, value):2 cur =self.head3 cur_idx =04 if cur isNone:5 raise Exception('The list is an empty list')6 while cur_idx < idx - 1:7 cur =cur.next8 if cur isNone:9 raise Exception('list length less than index')10 cur_idx += 1

11 node =Node(value)12 node.next =cur.next13 cur.next =node14 if node.next isNone:15 self.tail = node

remove方法实现

remove方法接收一个idx参数,表示要删除节点的索引,此方法要考虑以下几种情况:

空链表,直接抛出异常

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

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

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

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

请看下边图例:

1320444-20191224102537413-177450776.png

1320444-20191224102546966-1075758591.png

以下为remove函数的代码:

1 defremove(self, idx):2 cur =self.head3 cur_idx =04 if self.head is None: #空链表时

5 raise Exception('The list is an empty list')6 while cur_idx < idx - 1:7 cur =cur.next8 if cur isNone:9 raise Exception('list length less than index')10 cur_idx += 1

11 if idx == 0: #当删除第一个节点时

12 self.head =cur.next13 cur =cur.next14 return

15 if self.head is self.tail: #当只有一个节点的链表时

16 self.head =None17 self.tail =None18 return

19 cur.next =cur.next.next20 if cur.next is None: #当删除的节点是链表最后一个节点时

21 self.tail = cur

size函数实现

size函数不接收参数,返回链表中节点的个数,要获得链表的节点个数,必定会遍历链表,直到最后一个节点的next指针指向None时链表遍历完成,遍历时可以用一个累加器来计算节点的个数,如下代码:

1 defsize(self):2 current =self.head3 count =04 if current isNone:5 return 'The list is an empty list'

6 while current is notNone:7 count += 1

8 current =current.next9 return count

search函数实现

search函数接收一个item参数,表示查找节点中数据域的值。search函数遍历链表,每到一个节点把当前节点的data值与item作比较,最糟糕的情况下会全遍历链表。如果查找到有些数据则返回True,否则返回False,代码如下:

1 defsearch(self, item):2 current =self.head3 found =False4 while current is not None and notfound:5 if current.data ==item:6 found =True7 else:8 current =current.next9 return found

Node类与LinkedList类完整代码

最后把Node类和LinkerList类的完整代码整理如下:

Node类:

1 classNode:2 def __init__(self, data):3 self.data =data4 self.next = None

LinkedList类及调度代码:

1 classLinkedList:2 def __init__(self):3 self.head =None4 self.tail =None5

6 defis_empty(self):7 return self.head isNone8

9 defappend(self, data):10 node =Node(data)11 if self.head isNone:12 self.head =node13 self.tail =node14 else:15 self.tail.next =node16 self.tail =node17

18 defiter(self):19 if notself.head:20 return

21 cur =self.head22 yieldcur.data23 whilecur.next:24 cur =cur.next25 yieldcur.data26

27 definsert(self, idx, value):28 cur =self.head29 cur_idx =030 if cur is None: #判断是否是空链表

31 raise Exception('The list is an empty list')32 while cur_idx < idx-1: #遍历链表

33 cur =cur.next34 if cur is None: #判断是不是最后一个元素

35 raise Exception('list length less than index')36 cur_idx += 1

37 node =Node(value)38 node.next =cur.next39 cur.next =node40 if node.next isNone:41 self.tail =node42

43 defremove(self, idx):44 cur =self.head45 cur_idx =046 if self.head is None: #空链表时

47 raise Exception('The list is an empty list')48 while cur_idx < idx-1:49 cur =cur.next50 if cur isNone:51 raise Exception('list length less than index')52 cur_idx += 1

53 if idx == 0: #当删除第一个节点时

54 self.head =cur.next55 cur =cur.next56 return

57 if self.head is self.tail: #当只有一个节点的链表时

58 self.head =None59 self.tail =None60 return

61 cur.next =cur.next.next62 if cur.next is None: #当删除的节点是链表最后一个节点时

63 self.tail =cur64

65 defsize(self):66 current =self.head67 count =068 if current isNone:69 return 'The list is an empty list'

70 while current is notNone:71 count += 1

72 current =current.next73 returncount74

75 defsearch(self, item):76 current =self.head77 found =False78 while current is not None and notfound:79 if current.data ==item:80 found =True81 else:82 current =current.next83 returnfound84

85 if __name__ == '__main__':86 link_list =LinkedList()87 for i in range(150):88 link_list.append(i)89 #print(link_list.is_empty())

90 #link_list.insert(10, 30)

91

92 #link_list.remove(0)

93

94 for node inlink_list.iter():95 print('node is {0}'.format(node))96 print(link_list.size())97 #print(link_list.search(20))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值