11from __future__ import annotations
22
3+ from collections .abc import Iterable , Iterator
4+ from dataclasses import dataclass
35
6+
7+ @dataclass
48class 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 ])
853
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 )
1770
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 )
1886
19- def make_linked_list (elements_list : list ):
87+
88+ def make_linked_list (elements_list : Iterable [int ]) -> LinkedList :
2089 """Creates a Linked List from the elements of the given sequence
2190 (list/tuple) and returns the head of the Linked List.
2291 >>> make_linked_list([])
@@ -28,43 +97,30 @@ def make_linked_list(elements_list: list):
2897 >>> make_linked_list(['abc'])
2998 abc
3099 >>> make_linked_list([7, 25])
31- 7-> 25
100+ 7 -> 25
32101 """
33102 if not elements_list :
34103 raise Exception ("The Elements List is empty" )
35104
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
41108
42109
43- def print_reverse ( head_node : Node ) -> None :
110+ def in_reverse ( linked_list : LinkedList ) -> str :
44111 """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'
51116 """
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 )))
55118
56119
57- def main () :
120+ if __name__ == "__main__" :
58121 from doctest import testmod
59122
60123 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