Skip to content

Commit 1690a40

Browse files
committed
add doubly linked list
1 parent 6aeab4f commit 1690a40

File tree

3 files changed

+177
-1
lines changed

3 files changed

+177
-1
lines changed

Linked_list/doubly_linked_list.py

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
3+
# Created by imoyao at 2019/9/19 16:02
4+
5+
class Link:
6+
"""
7+
定义单个节点
8+
"""
9+
next = None
10+
prev = None
11+
12+
def __init__(self, val):
13+
self.val = val
14+
15+
def display_link(self):
16+
print(f'{self.val}', end=' ')
17+
18+
19+
class DoublyLinkedList:
20+
"""
21+
定义双链表类
22+
"""
23+
24+
def __init__(self):
25+
self.head = None
26+
self.tail = None
27+
28+
def __iter__(self):
29+
_temp = self.head
30+
while _temp is not None:
31+
yield _temp.val
32+
_temp = _temp.next
33+
34+
def is_empty(self):
35+
return self.head is None
36+
37+
def insert_head(self, val):
38+
"""
39+
从头插入值
40+
:param val:
41+
:return:
42+
"""
43+
new_node = Link(val) # 初始化
44+
if self.is_empty():
45+
self.tail = new_node # 第一个的尾指向新节点
46+
else:
47+
self.head.prev = new_node # 原来的链表头的前驱指向新节点
48+
49+
new_node.next = self.head # 新节点指向原来的链表头
50+
self.head = new_node # 新节点作为链表头
51+
52+
def insert_tail(self, val):
53+
"""
54+
从尾部插入值
55+
:param val:
56+
:return:
57+
"""
58+
new_node = Link(val) # 初始化节点
59+
new_node.next = None # 新节点的后域指向空
60+
self.tail.next = new_node # 原来的尾的后域指向新节点
61+
new_node.prev = self.tail # 新节点的前驱指向原来的尾
62+
self.tail = new_node # 改节点成为链表的尾
63+
64+
def delete_head(self):
65+
"""
66+
从头部删除
67+
:return:
68+
"""
69+
_temp = self.head
70+
self.head = self.head.next # 原来的头指向的变成新头
71+
self.head.prev = None # 原来头的前驱指向空
72+
if self.head is None: # 如果头是空
73+
self.tail = None # 则尾变空
74+
return _temp # 返回删除节点
75+
76+
def delete_tail(self):
77+
"""
78+
从尾部删除
79+
:return:
80+
"""
81+
_temp = self.tail # 拿到原来的尾
82+
self.tail = self.tail.prev # 现在的尾是原来的尾前驱所指
83+
self.tail.next = None # 现在的尾的后域指向空
84+
return _temp # 返回原来的尾
85+
86+
def delete(self, data):
87+
"""
88+
删除指定值
89+
:param data:
90+
:return:
91+
"""
92+
# 先找到要删除的节点的位置
93+
current = self.head # 拿到链表的头
94+
try:
95+
while current.val != data: # 头不等于要删除值继续向后找
96+
current = current.next
97+
except AttributeError:
98+
print(f'The linked list has not data equals {data}')
99+
return
100+
101+
if current == self.head: # 如值等于链表头,则删除值就是删除头
102+
self.delete_head()
103+
elif current == self.tail: # 如果头等于链表尾,则是删除尾
104+
self.delete_tail()
105+
else: # 否则删除中间值
106+
current.prev.next = current.next # 删除中间某节点,就是该值的前一个节点的后域指向当前节点的下一个节点
107+
current.next.prev = current.prev # 当前节点的后面一个节点的前驱指向当前节点的前驱
108+
109+
def show_data_of_link(self):
110+
"""
111+
显示节点值
112+
:return:
113+
"""
114+
_temp = self.head
115+
while _temp is not None:
116+
_temp.display_link()
117+
_temp = _temp.next
118+
print('\n')
119+
120+
def reverse(self):
121+
"""
122+
翻转链表
123+
:return:
124+
"""
125+
current = self.head
126+
prev_node = None
127+
while current is not None:
128+
_temp = current.next
129+
current.next = prev_node
130+
prev_node = current
131+
current = _temp
132+
133+
self.head = self.tail
134+
self.tail = current
135+
136+
137+
def main():
138+
link = DoublyLinkedList()
139+
for i in range(5):
140+
link.insert_head(i)
141+
142+
link.show_data_of_link()
143+
144+
for i in range(5):
145+
link.insert_tail(i)
146+
147+
link.show_data_of_link()
148+
149+
link.delete(3)
150+
link.delete(3)
151+
link.show_data_of_link()
152+
link.delete(1)
153+
link.show_data_of_link()
154+
link.delete_head()
155+
link.show_data_of_link()
156+
link.delete_tail()
157+
link.show_data_of_link()
158+
print('===before reverse===')
159+
link.insert_head('haha')
160+
link.insert_tail('hehe')
161+
link.reverse()
162+
link.show_data_of_link()
163+
164+
165+
if __name__ == '__main__':
166+
main()
2.88 KB
Loading

Linked_list/readme.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,15 @@ data|next
4343
![原来的链表头最后移动到表尾](./img/reverse_linked_list_head_last.gif)
4444

4545
3. 递归(相信我们都熟悉的一点是,对于树的大部分问题,基本可以考虑用递归来解决。但是我们不太熟悉的一点是,对于单链表的一些问题,也可以使用递归。可以认为单链表是一颗永远只有左(右)子树的树,因此可以考虑用递归来解决。或者说,因为单链表本身的结构也有自相似的特点,所以可以考虑用递归来解决)
46+
---
47+
# 双向链表
48+
## 概念
4649

47-
- []()
50+
双向链表,又称为双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。当此节点为第一个节点时,前驱指向空值,后继指向下一个节点,最后一个节点反之。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。
51+
## 结构模型
52+
指针域|数据域|指针域
53+
完整结构如下
54+
![双向链表](img/Doubly-linked-list.svg.png)
55+
56+
## 代码实现
57+
- [双向链表](./doubly_linked_list.py)

0 commit comments

Comments
 (0)