-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlinked_list.py
More file actions
226 lines (203 loc) · 5.86 KB
/
Copy pathlinked_list.py
File metadata and controls
226 lines (203 loc) · 5.86 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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
"""
Node and LinkedList class definitions with encapsulation.
"""
class _Node:
"""Private class: Node for the linked list"""
def __init__(self, value):
self.value = value
self.next = None
class LinkedList:
"""
A singly linked list with properties for safe access.
Uses private attributes and exposes read-only properties.
"""
def __init__(self, value):
new_node = _Node(value)
self._head = new_node
self._tail = new_node
self._length = 1
@property
def head(self):
"""Get the head node"""
return self._head
@property
def tail(self):
"""Get the tail node"""
return self._tail
@property
def length(self):
"""Get the length"""
return self._length
def print_list(self):
"""Prints the linked list"""
if not self._head:
print("empty list")
return
values = []
temp = self._head
while temp:
values.append(str(temp.value))
temp = temp.next
values.append("None")
print(" -> ".join(values))
def make_empty(self):
"""Empties the list"""
self._head = None
self._tail = None
self._length = 0
def append(self, value):
"""Append node to end"""
new_node = _Node(value)
if self._length == 0:
self._head = new_node
self._tail = new_node
else:
self._tail.next = new_node
self._tail = new_node
self._length += 1
def pop(self):
"""Pop node from end"""
if self._length == 0:
return None
temp = self._head
pre = self._head
while temp.next:
pre = temp
temp = temp.next
self._tail = pre
self._tail.next = None
self._length -= 1
if self._length == 0:
self._head = None
self._tail = None
return temp
def prepend(self, value):
"""Prepend node to start"""
new_node = _Node(value)
if self._length == 0:
self._head = new_node
self._tail = new_node
else:
new_node.next = self._head
self._head = new_node
self._length += 1
def pop_first(self):
"""Pop node from start"""
if self._length == 0:
return None
temp = self._head
self._head = self._head.next
temp.next = None
self._length -= 1
if self._length == 0:
self._tail = None
return temp
def get(self, index):
"""Get node at index"""
if index < 0 or index >= self._length:
return None
temp = self._head
for _ in range(index):
temp = temp.next
return temp
def set_value(self, index, value):
"""Set value of node at index"""
temp = self.get(index)
if temp:
temp.value = value
return True
return False
def find_middle_node(self):
"""Find the middle node"""
fast = slow = self._head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
return slow
def has_loop(self):
"""Check for loop"""
fast = slow = self._head
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if fast == slow:
return True
return False
def find_kth_from_end(self, k):
"""Find k-th node from end"""
slow = fast = self._head
for _ in range(k):
if not fast:
return None
fast = fast.next
while fast:
slow = slow.next
fast = fast.next
return slow
def remove_duplicates(self):
"""Remove duplicate values"""
current = self._head
seen = set()
prev = None
while current:
if current.value in seen:
prev.next = current.next
else:
seen.add(current.value)
prev = current
current = current.next
def binary_to_decimal(self):
"""Convert binary linked list to decimal"""
decimal = 0
current = self._head
while current:
decimal = decimal * 2 + current.value
current = current.next
return decimal
def partition_list(self, x):
"""Partition list around x"""
if not self._head:
return
dummy1 = _Node(0)
dummy2 = _Node(0)
prev1 = dummy1
prev2 = dummy2
current = self._head
while current:
if current.value < x:
prev1.next = current
prev1 = prev1.next
else:
prev2.next = current
prev2 = prev2.next
current = current.next
prev1.next = dummy2.next
prev2.next = None
self._head = dummy1.next
def reverse_between(self, left, right):
"""Reverse sublist between left and right"""
if not self._head or left == right:
return
dummy = _Node(0)
dummy.next = self._head
prev = dummy
for _ in range(left):
prev = prev.next
current = prev.next
for _ in range(right - left):
move = current.next
current.next = move.next
move.next = prev.next
prev.next = move
self._head = dummy.next
def swap_pairs(self):
"""Swap nodes in pairs"""
dummy = _Node(0)
dummy.next = self._head
prev = dummy
while prev.next and prev.next.next:
first = prev.next
second = prev.next.next
prev.next, first.next, second.next = second, second.next, first
prev = first
self._head = dummy.next