-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlinkedlist.py
167 lines (114 loc) · 4.05 KB
/
linkedlist.py
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
"""Implementation of a linked list."""
from node import Node
class LinkedList(object):
"""A doubly linked list, consisting of Nodes that track next and prev.
Let's make a list. I'm hungry, so it's gonna be fruits.
>>> fruits = LinkedList()
Add a node to be the head:
>>> fruits.append("apple")
>>> fruits.head
<Node apple>
>>> fruits.tail
<Node apple>
Now let's add some more:
>>> fruits.append("berry")
>>> fruits.tail
<Node berry>
>>> fruits.head.next
<Node berry>
>>> fruits.tail.prev
<Node apple>
>>> fruits.append("cherry")
>>> fruits.append("dragonfruit")
>>> fruits.append("eggplant")
>>> fruits.append("fig")
I think I want to eat the apple first. (Remove the head.)
>>> fruits.remove("apple")
What's left?
>>> fruits.display()
berry
cherry
dragonfruit
eggplant
fig
Now a fig. (Remove the tail.)
>>> fruits.remove("fig")
What's left?
>>> fruits.display()
berry
cherry
dragonfruit
eggplant
Okay, cherries are awesome.
>>> fruits.remove("cherry")
What's left?
>>> fruits.display()
berry
dragonfruit
eggplant
Let's do a couple more...
>>> fruits.remove("berry")
>>> fruits.remove("dragonfruit")
What if there's just one fruit?
>>> fruits.remove("eggplant")
>>> fruits.display()
This linked list is empty.
"""
def __init__(self):
"""Initialize an empty LL."""
self.head = None
self.tail = None
def __repr__(self):
"""A human-readable representation of the linked list."""
return "<LinkedList Head: {head_data} Tail: {tail_data}>".format(
head_data=self.head.data, tail_data=self.tail.data)
def append(self, data):
"""Add a new node to the end of the list."""
new_node = Node(data)
# Do we have a head yet?
if self.head is None:
self.head = new_node
# Do we have a tail yet? If so, we have to make the new node its
# next and make the new node's previous the current tail, before
# updating tail to the new node.
if self.tail is not None:
self.tail.next = new_node
new_node.prev = self.tail
self.tail = new_node
def remove(self, data):
"""Remove the node with the given data from the linked list.
Only remove first occurrence seen.
"""
# Start at the head.
current = self.head
# Iterate over the linked list. If we've hit the end, we can just
# adjust the tail. Otherwise, we have to move pointers for both
# nodes around the node to remove.
while current is not None:
if current.data == data:
# Remove the head when other nodes follow it.
if current is self.head and current.next is not None:
self.head = self.head.next
self.head.prev = None
# Remove the tail when other nodes preceed it.
elif current is self.tail and current.prev is not None:
current.prev.next = None
self.tail = current.prev
# Remove a node if it's the only one in the list.
elif current is self.head and current is self.tail:
self.head = None
self.tail = None
# Typical case: remove from middle.
else:
current.prev.next = current.next
current.next.prev = current.prev
current = current.next
def display(self):
"""Blat the contents of the list."""
if self.head:
current = self.head
while current is not None:
print(current.data)
current = current.next
else:
print "This linked list is empty."