Reverse link direction of singly linked list - python

I have a linked list that is reverse linked, is there a way I can change the direction of the links in this program? I've tried using self.head.set_next starting at the first element, but type None doesn't have a method set_next, so I'm not sure how I would proceed.
class Node2(object):
def __init__(self, data=None, next_node=None):
self.data = data
self.next_node = next_node
def set_next(self, new_next):
self.next_node = new_next
def get_data(self):
return self.data
def get_next(self):
return self.next_node
class LinkedList2(object):
def __init__(self, head=None):
self.head = head
def insert(self, data):
new_node = Node(data)
new_node.set_next(self.head)
self.head = new_node

Something like that would do the trick
# linked_list is the list you want to reverse
previous_node = None
current_node = linked_list.head
while current_node is not None:
next_node = current_node.get_next()
current_node.set_next(previous_node)
previous_node, current_node = current_node, next_node
linked_list.head = previous_node
This will execute in linear time.
However, if you find you need to frequently reverse linked list, you may find doubly linked lists to be more adapted to your needs

You can do it recursively as well:
prev_node =
cur_node = linked_list.head
def reverse_ll(prev, cur):
if not cur: return prev
next_node = cur.get_next()
cur.set_next(prev)
return reverse_ll(cur, next_node)
reversed_head = reverse_ll(None, cur_node)

Related

error in creating a linked list using python

I am new to data structures.Tried to create a linkled list with a print function,but when running the program it is throwing an error stating "add_link takes one positional argument but 2 were given".Below is the code.Please help me out. thanks in advance
class node:
def __init__( self ,value, Next = None):
self.value = value
self.Next = None
newnode = None
def add_link(self,data):
if(self.Next == None):
self.Next = node(data)
newnode = self.Next
else:
newnode.Next = node(data)
newnode = newnode.Next
def print(self):
if(self.Next !=None):
print(self.node)
self.next.print()
# main
link = node(10)
link.add_link(20)
link.add_link(30)
link.add_link(40)
link.print()
You need to add self as an argument to the add_link() function:
def add_link(self, data):
if(self.Next == None):
self.Next = node(data)
newnode = self.Next
else:
newnode.Next = node(data)
newnode = newnode.Next
It will be better to create Node as a seprate class/structure, and LinkedList as different.
So that we can implement methods according to class.
class Node:
"""
#Summary: Node has a set of information and address to the next node.
"""
def __init__(self, data) -> None:
self.data = data
self.next = None
class SinglyLinkedList:
def __init__(self, item:Node) -> None:
# Head or start node for Singly Linked List
self.head = item
def add(self, new_item:Node) -> None:
"""
#Summary: Adde new item to Singly Linked List
#Param new_item(Node): New node item
#Return (None)
"""
# Check if Linked list is emplty or not.
if self.head == None:
self.head = new_item
else:
# Add a new item to an end.
last_node = self.head
while last_node.next != None:
last_node = last_node.next
last_node.next = new_item
def print(self):
"""Print Linked List"""
if self.head == None:
print("No item in Linked list")
else:
print("Linked List :")
tmp_node = self.head
while True:
print(tmp_node.data, end=" ")
if tmp_node.next == None:
break
tmp_node = tmp_node.next
print()
# Create Node as a Head node.
item01 = Node(10)
obj = SinglyLinkedList(item01)
obj.add(Node(20))
obj.add(Node(30))
obj.add(Node(40))
obj.print()

Create a tester class in a linked list for showing even numbers

This is my node class and Mylist class
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
class MyList():
def __init__(self,head=None):
self.head = head
def showList(self):
temp = self.head
while (temp):
print(temp.data)
temp = temp.next
if self.head is None:
print("Empty List")
This is my showeven number function
def showeven(even):
head = None
while even:
if even.data % 2 == 0:
new_Node = Node(even.data, None)
if head is None:
tail = new_Node
head = new_Node
else:
tail.next = new_Node
tail = new_Node
MyList(head).showList()
Can you guys help me create a tester class or some sort of thing for this
You can simply write something like this.
def print_even_nodes(self):
traverse = self.head
while (traverse != None):
if (traverse.data % 2 == 0):
print(traverse.data)
traverse = traverse.next
It is pretty much similar to printing the whole singly linked list, the only key difference is that we check if that particular node (node.data field) is divisible by 2. If it is true we print out the element else we go to the next node.

How to set a class attribute a specified number of times in Python

Suppose we have a class Node which is initialized as follows:
class Node(object):
def __init__(self, data=None, next_node=None, prev_node = None):
self.data = data
self.next = next_node
self.prev = prev_node
and we create an instance head as follows:
head = Node(data=4)
head.next = Node(data=5)
head.next.next = Node(data=6)
head.prev = Node(data=2)
I'd like to add another node to the doubly-linked list, which I could do by
head.next.next.next = Node(data=8)
However, instead of writing ".next" three times, I would like to use a method which takes as input the number of times to call ".next" - that is, something like head.next_n_times(3) = Node(data=8) which would have the same effect. How could I achieve this?
Here is what I've tried so far:
class Node(object):
def __init__(self, data=None, next_node=None, prev_node = None):
self.data = data
self.next = next_node
self.prev = prev_node
def next_n_times(self, n):
next_node = self.next
for i in range(n-1):
next_node = next_node.next
return next_node
head = Node(data=4)
head.next = Node(data=5)
head.next.next = Node(data=6)
head.prev = Node(data=2)
data = 5
head.next_n_times(3) = Node(data=8)
However, I get the error message
File "sorted_insert_scratch.py", line 19
head.next_n_times(5) = Node(data=8)
SyntaxError: can't assign to function call
It seems like the next_n_times method works as a 'getter', but not as a 'setter'. How can I make it work as a 'setter'?
You're trying to implement the append method for the Node class. You can easily do so with recursion:
class Node(object):
def __init__(self, data=None, next_node=None, prev_node = None):
self.data = data
self.next = next_node
self.prev = prev_node
def append(self, node):
if self.next:
self.next.append(node)
else:
self.next = node
self.next.prev = self
It seems like the next_n_times method works as a 'getter', but not as a 'setter'. How can I make it work as a 'setter'?
What you get back is a Node object, and you want to set its next attribute:
head.next_n_times(3).next = Node(data=8)
To do what you want you have to change the syntax:
def append_at_next_n(self, n, node):
next_node = self.next
for i in range(n-1):
next_node = next_node.next
next_node.next = node
return next_node
To make it work in your example:
head.append_at_next_n(3, Node(data=8))
Note that head.next.next.next is currently None, as you only set head.next.next, so the above will raise an exception unless you add another node first.
Expanding on this, however, you could make it kind of work with an actual property setter:
#property
def appender(self):
return self
#appender.setter
def append_at_next_n(self, args):
n, node = args
next_node = self.next
for i in range(n-1):
next_node = next_node.next
next_node.next = node
return next_node
head.appender = (3, Node(2))
It doesn't help readability though.
Try this
class Node(object):
def __init__(self, data=None, next_node=None, prev_node = None):
self.data = data
self.next = next_node
self.prev = prev_node
def next_n_times(self, n, value):
next_node = self.next
# loop to the penultimate Node
for i in range(n-2):
next_node = next_node.next
# set that value to the value provided
next_node.next = Node(value)
if __name__ == '__main__':
head = Node(data=4)
head.next = Node(data=5)
head.next.next = Node(data=6)
head.prev = Node(data=2)
data = 5
head.next_n_times(3, 8)
# and to see if it worked...
print head.next.next.next.data
Of course here were not checking if all the child nodes are present, so this will throw an error if head had only 1 child.

Remove method in Python LinkedList using an index

class Node(object):
def __init__(self, data, next):
self.data = data
self.next = next
class LinkedList(object):
head = None
tail = None
def print_list(self):
node = self.head
while node:
print node.data,
node = node.next
def add_front(self, data):
node = Node(data, None)
if self.head is None:
self.head = self.tail = node
else:
self.tail.next = node
self.tail = node
def remove(self, index):
curr_node = self.head
prev_node = None
while curr_node and index>=0:
if index == 0:
if prev_node is not None:
prev_node.next = curr_node.next
else:
self.head = curr_node.next
index = index - 1
prev_node = curr_node
curr_node = curr_node.next
So, I wanted to implement a remove method using index in python but it does not seem to be working. I think I'm messing something with replacing the nodes but can't figure out which one. So a little help needed here.

How to create add and remove function in a sorted doubly linked list

Here are the three classes: the node, the doubly linked list, and a sorted list which implement on the doubly linked list. Here is my code:
class DLLNode(object):
def __Init__ (self, data, prev_node=None, next_node=None):
self.data=data
self.prev_node=prev_node
self.next_node=next_node
def __str__(self):
return str(self.data)
class DoublyLinkedList(object):
def __init__(self, head=None, tail=None):
self.head=head
self.tail=tail
self.size=0
def add_to_head(self, data):
newNode = DLLNode(data)
if self.head==None:
self.head=self.tail=newNode
self.head.prev_node=self.tail.next_node=None
else:
self.head.prev_node=newNode
newNode.next_node=self.head
self.head=newNode
def add_to_tail(self, data):
newNode=DLLNode(data)
if self.head==None:
self.head=self.tail=newNode
self.head.prev_node=self.tail.next_node=None
else:
self.tail.next_node=newNode
newNode.prev_node=self.tail
self.tail=newNode
self.tail.next_node=None
def remove_head(self):
node=self.head
if self.head==self.tail:
self.prev_node=self.next_node=self.head=self.tail=None
return
if self.head!=self.tail:
node=node.next_node
node.prev_node=None
self.head=node
def remove_tail(self):
node=self.tail
if self.head==self.tail:
self.prev_node=self.next_node=self.head=self.tail=None
return
if self.head!=self.tail:
self.tail=node.prev_node
self.tail.next_node=None
def index(self,element):
current = self.head
while current != None:
if current.data == element:
return current.position
else:
current = current.next
return -1
class SortedList(object):
def __init__(self, sequence = []):
if len(sequence)==0:
self.head = None
self.tail = None
else:
cur_node = None
prev_node = None
sequence.sort()
sequence.reverse()
for element in sequence:
prev_node = cur_node
cur_node = DLLNode(element, cur_node, prev_node)
self.head = cur_node
self.tail = DLLNode(sequence[0])
For the sorted list class I need to create an add and remove function. However, I dont really know how to do it. Could anyone let me know?

Categories

Resources