1
1
from __future__ import annotations
2
2
3
+ from collections .abc import Iterable , Iterator
4
+ from dataclasses import dataclass
3
5
6
+
7
+ @dataclass
4
8
class Node :
5
- def __init__ (self , data = None ):
6
- self .data = data
7
- self .next = None
9
+ data : int
10
+ next_node : Node | None = None
11
+
12
+
13
+ class LinkedList :
14
+ """A class to represent a Linked List.
15
+ Use a tail pointer to speed up the append() operation.
16
+ """
17
+
18
+ def __init__ (self ) -> None :
19
+ """Initialize a LinkedList with the head node set to None.
20
+ >>> linked_list = LinkedList()
21
+ >>> (linked_list.head, linked_list.tail)
22
+ (None, None)
23
+ """
24
+ self .head : Node | None = None
25
+ self .tail : Node | None = None # Speeds up the append() operation
26
+
27
+ def __iter__ (self ) -> Iterator [int ]:
28
+ """Iterate the LinkedList yielding each Node's data.
29
+ >>> linked_list = LinkedList()
30
+ >>> items = (1, 2, 3, 4, 5)
31
+ >>> linked_list.extend(items)
32
+ >>> tuple(linked_list) == items
33
+ True
34
+ """
35
+ node = self .head
36
+ while node :
37
+ yield node .data
38
+ node = node .next_node
39
+
40
+ def __repr__ (self ) -> str :
41
+ """Returns a string representation of the LinkedList.
42
+ >>> linked_list = LinkedList()
43
+ >>> str(linked_list)
44
+ ''
45
+ >>> linked_list.append(1)
46
+ >>> str(linked_list)
47
+ '1'
48
+ >>> linked_list.extend([2, 3, 4, 5])
49
+ >>> str(linked_list)
50
+ '1 -> 2 -> 3 -> 4 -> 5'
51
+ """
52
+ return " -> " .join ([str (data ) for data in self ])
8
53
9
- def __repr__ (self ):
10
- """Returns a visual representation of the node and all its following nodes."""
11
- string_rep = []
12
- temp = self
13
- while temp :
14
- string_rep .append (f"{ temp .data } " )
15
- temp = temp .next
16
- return "->" .join (string_rep )
54
+ def append (self , data : int ) -> None :
55
+ """Appends a new node with the given data to the end of the LinkedList.
56
+ >>> linked_list = LinkedList()
57
+ >>> str(linked_list)
58
+ ''
59
+ >>> linked_list.append(1)
60
+ >>> str(linked_list)
61
+ '1'
62
+ >>> linked_list.append(2)
63
+ >>> str(linked_list)
64
+ '1 -> 2'
65
+ """
66
+ if self .tail :
67
+ self .tail .next_node = self .tail = Node (data )
68
+ else :
69
+ self .head = self .tail = Node (data )
17
70
71
+ def extend (self , items : Iterable [int ]) -> None :
72
+ """Appends each item to the end of the LinkedList.
73
+ >>> linked_list = LinkedList()
74
+ >>> linked_list.extend([])
75
+ >>> str(linked_list)
76
+ ''
77
+ >>> linked_list.extend([1, 2])
78
+ >>> str(linked_list)
79
+ '1 -> 2'
80
+ >>> linked_list.extend([3,4])
81
+ >>> str(linked_list)
82
+ '1 -> 2 -> 3 -> 4'
83
+ """
84
+ for item in items :
85
+ self .append (item )
18
86
19
- def make_linked_list (elements_list : list ):
87
+
88
+ def make_linked_list (elements_list : Iterable [int ]) -> LinkedList :
20
89
"""Creates a Linked List from the elements of the given sequence
21
90
(list/tuple) and returns the head of the Linked List.
22
91
>>> make_linked_list([])
@@ -28,43 +97,30 @@ def make_linked_list(elements_list: list):
28
97
>>> make_linked_list(['abc'])
29
98
abc
30
99
>>> make_linked_list([7, 25])
31
- 7-> 25
100
+ 7 -> 25
32
101
"""
33
102
if not elements_list :
34
103
raise Exception ("The Elements List is empty" )
35
104
36
- current = head = Node (elements_list [0 ])
37
- for i in range (1 , len (elements_list )):
38
- current .next = Node (elements_list [i ])
39
- current = current .next
40
- return head
105
+ linked_list = LinkedList ()
106
+ linked_list .extend (elements_list )
107
+ return linked_list
41
108
42
109
43
- def print_reverse ( head_node : Node ) -> None :
110
+ def in_reverse ( linked_list : LinkedList ) -> str :
44
111
"""Prints the elements of the given Linked List in reverse order
45
- >>> print_reverse([])
46
- >>> linked_list = make_linked_list([69, 88, 73])
47
- >>> print_reverse(linked_list)
48
- 73
49
- 88
50
- 69
112
+ >>> in_reverse(LinkedList())
113
+ ''
114
+ >>> in_reverse(make_linked_list([69, 88, 73]))
115
+ '73 <- 88 <- 69'
51
116
"""
52
- if head_node is not None and isinstance (head_node , Node ):
53
- print_reverse (head_node .next )
54
- print (head_node .data )
117
+ return " <- " .join (str (line ) for line in reversed (tuple (linked_list )))
55
118
56
119
57
- def main () :
120
+ if __name__ == "__main__" :
58
121
from doctest import testmod
59
122
60
123
testmod ()
61
-
62
- linked_list = make_linked_list ([14 , 52 , 14 , 12 , 43 ])
63
- print ("Linked List:" )
64
- print (linked_list )
65
- print ("Elements in Reverse:" )
66
- print_reverse (linked_list )
67
-
68
-
69
- if __name__ == "__main__" :
70
- main ()
124
+ linked_list = make_linked_list ((14 , 52 , 14 , 12 , 43 ))
125
+ print (f"Linked List: { linked_list } " )
126
+ print (f"Reverse List: { in_reverse (linked_list )} " )
0 commit comments