-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdoublylinkedlist.py
More file actions
211 lines (184 loc) · 6.37 KB
/
doublylinkedlist.py
File metadata and controls
211 lines (184 loc) · 6.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
"""双向列表 闭环的 有一个名为header的头部节点 定义上:第一个节点为header的next 最后一个节点为header的previous"""
from GoodToolPython.mybaseclasses.selfdelete import SelfDelete
class Node(SelfDelete):
"""
双向列表使用的节点
为了防止节点不知道自己被删除 继承了selfdelete类
使用时 不可在双向列表外实例化
"""
def __init__(self, data=None, previous=None, next=None, list=None):
self.previous = previous # type:Node
self.next = next # type:Node
self.data = data # 数据
self.list = list # type:DoublyLinkedList #所属双向链表
class _Iterator:
def __init__(self, lst, flag_reversed):
self.lst = lst
if flag_reversed is False:
self.direction = lambda x: x.next
else:
self.direction = lambda x: x.previous
def __iter__(self):
self.next_node = self.direction(lst.header)
return self
def __next__(self) -> Node:
if lst.header == self.next_node:
raise StopIteration
tmp = self.next_node
self.next_node = self.direction(tmp)
return tmp
class DoublyLinkedList:
def __init__(self):
self.header = Node(data='header') # type:Node #双向列表的头结点
self.header.previous = self.header
self.header.next = self.header
self.header.list = self
self._length = 0 # type:int #长度
@property
def length(self):
return self._length
def insert(self, data, mode='after', ref_node=None) -> Node:
"""
插入节点
默认插入到最后一个
可以选择在参考结点之前或者之后插入 算法在实现上都是转化为之后插入
:param data: 节点上挂载的数据
:param mode: 'after' 'before'
:param ref_node: 参考结点
:return: 生成的节点
"""
if ref_node is None:
ref_node = self.header.previous # 默认参考结点是最后一个节点
assert mode in ('after', 'before'), 'mode只能是after或者before'
assert ref_node in self, '参考结点必须在结点内部'
func = self.__insert_after if mode == 'after' else self.__insert_before
return func(data, ref_node)
def __insert_after(self, data, ref_node):
replaced = ref_node.next
tmp = Node(data=data, previous=ref_node, next=replaced, list=self)
ref_node.next = tmp
replaced.previous = tmp
self._length += 1
return tmp
def __insert_before(self, data, ref_node):
return self.__insert_after(data=data, ref_node=ref_node.previous)
def __contains__(self, item):
assert isinstance(item, Node), '必须为节点'
return item.list == self
def __str__(self):
return '长度:%d' % self._length
def print(self, expr=None) -> None:
"""
#详细打印列表信息
:param expr: 打印的变量名 默认为data
:return:
"""
if expr is None:
expr = lambda x: x.data
assert callable(expr)
print(self)
for n in self:
print(expr(n))
def __iter__(self):
"""
#迭代器 从第一个节点开始迭代 不含头部
调用iterator实现
:return:
"""
return self.iterator()
# tmp=_Iterator(self,False)
# tmp.__iter__()
# return tmp
def delete_node(self, node: Node):
assert isinstance(node, Node), '必须为节点对象'
assert node in self, '必须为链表内部节点'
assert node != self.header, '头部节点不能删除'
node.previous.next = node.next
node.next.previous = node.previous
node.delete()
self._length -= 1
def find_by_data(self, data) -> Node:
# 通过数据 查找节点 返回第一个满足data相等的节点 没找到返回none
for n in self:
if n.data == data:
return n
return None
def __len__(self):
return self._length
@property
def last_node(self) -> Node:
# 最后节点
if self._length == 0:
return None
return self.header.previous
@property
def first_node(self) -> Node:
# 第一个节点 不是头部
if self._length == 0:
return None
return self.header.next
def __getitem__(self, item) -> Node:
# 通过索引获取节点 支持负数索引
assert isinstance(item, int), '只支持数字索引'
if item >= 0: # 自然数时 正向索引
if item > self._length - 1:
raise Exception("索引超出范围")
it = self.header
for i in range(0, item + 1):
it = it.next
return it
else: # 负数
if -1 * item > self._length:
raise Exception("索引超出范围")
it = self.header
for i in range(-1, item - 1, -1):
it = it.previous
return it
def iterator(self, flag_reversed=False):
"""
遍历节点
不含头部
:param flag_reversed: true代表反方向遍历
:return:
"""
tmp = _Iterator(self, flag_reversed)
tmp.__iter__()
return tmp
def append(self,data):
#在末尾添加 使用insert方法实现
self.insert(data=data)
if __name__ == '__main__':
lst = DoublyLinkedList()
lst.print()
lst.insert('1')
lst.print(expr=lambda x: x.data)
assert len(lst) == 1
assert lst[0].data == '1'
assert lst[-1].data == '1'
t1 = lst.insert('2')
lst.insert('3')
lst.print()
assert len(lst) == 3
lst.insert(data='2.5', ref_node=t1)
assert len(lst) == 4
lst.print()
lst.insert(data='1.5', ref_node=t1, mode='before')
assert lst.last_node.data == '3'
assert lst[2].data == '2'
assert len(lst) == 5
lst.print()
lst.delete_node(t1)
assert lst.last_node.previous.data == '2.5'
assert len(lst) == 4
lst.print()
lst.delete_node(lst.find_by_data('2.5'))
lst.print()
assert len(lst) == 3
assert lst.last_node.data == '3'
assert lst[-1].data == '3'
assert lst[-2].data == '1.5'
for n in lst.iterator(True):
print(n.data)
assert n.data == '1'
lst.append('4')
assert lst[-1].data=='4'