-
Notifications
You must be signed in to change notification settings - Fork 0
/
asymlist.py
127 lines (106 loc) · 4.16 KB
/
asymlist.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
class TransitionBackError(Exception):
def __init__(self, message):
self.message = message
class Node:
def __init__(self, node_id, is_bidirect, **kwargs):
''' Used by AsymLList. Not instantiated directly
Parameters:
node_id: unique Node id
is_bidirect (boolean): flags if the Node can be traversed in forward
and reverse direction (True) or only in forward direction (False)
'''
self.id=node_id
self.is_bidirect=is_bidirect
# self.prev - pointer to the previous bidirectional Node
# self.next - pointer to the next Node
self.prev=None
self.next=None
def __str__(self):
return str(self.id)
def __repr__(self):
return "Node:{} Prev:{} Next:{}".format(self.id,self.prev,self.next)
class AsymLList:
def __init__(self,node_id, is_bidirect=True, nodeClass=Node, **kwargs):
'''Instantiates AsymLList with the first Node
parameters:
node_id, is_bidirect: Node class attrributes.
nodeClass: class of the Node
'''
self.nodeClass=nodeClass
firstNode=self.nodeClass(node_id,is_bidirect, **kwargs)
if firstNode.is_bidirect:
self.back=firstNode
else:
self.back=None
# self.begin - pointer to the first Node of the AsymList
# self.last - pointer to the last Node of the AsymLyst
# self.current - pointer to the Node under consideration.
# used in fwd() and rwd() methods
# self.back - pointer to the last bidirectional node (defines way back)
self.begin=firstNode
self.last=firstNode
self.current=None
def append(self,node_id,is_bidirect=True, **kwargs):
''' Appends a Node to the AsymLList.
Parameters:
node_id: unique node id
is_biderect (boolean): is node biderectional, default - True
Returns the pointer to the last node.
'''
newNode = self.nodeClass(node_id,is_bidirect, **kwargs)
newNode.prev = self.back
self.last.next = newNode
if newNode.is_bidirect:
self.back = newNode
self.last = newNode
return self.last
def forward(self):
''' Returns a list of Nodes linked in the forward direction
starting from the first one
'''
result = []
ptr = self.begin
while ptr is not None:
result.append(ptr)
ptr = ptr.next
return result
def backward(self):
''' Returns a list of Nodes linked in the backward direction,
starting from the last bidirectional Node, or None if the
list is empty.
'''
if self.back is None:
return None
result = []
ptr = self.back
while ptr is not None:
result.append(ptr)
ptr = ptr.prev
return result
def fwd(self):
'''Traverses throgh the Nodes of the AsymLList in forward direction.
Returns the pointer to the next Node. When self.current points to the last Node,
turns over to the first Node
'''
if self.current is None:
self.current=self.begin
else:
self.current=self.current.next
if self.current is None:
self.current=self.begin
return self.current
def rwd(self):
'''Traverses through the Nodes of the AsymLList in the reverse direction.
Returns the pointer to the previous Node if exists, otherwise raises an Exeption.
When self.current points to the first biderectional Node, turns over to
the last bidirectional Node.
'''
if self.back is None:
raise TransitionBackError("No way back")
if self.current is None:
self.current = self.back
else:
self.current = self.current.prev
if self.current is None:
self.current = self.back
return self.current