Sorted Linked List in Python - data-structures

I'm having a bit of trouble figuring out how to sort a Singly Linked list in Python. I've figured out how to create a linked list and push data onto it but how do I push it in a sorted format (not sorting after all the data is pushed onto it) or just sorting it in any way?
Objective
Create a sorted singly linked list of numbers based upon user input.
Program logic:
Ask for a number, add that number to the list in sorted position, print the list.
Repeat until they enter -1 for the number.
Current Code
#!/usr/bin/env python
class node:
def __init__(self):
self.data = None # contains the data
self.next = None # contains the reference to the next node
class linked_list:
def __init__(self):
self.cur_node = None
def add_node(self, data):
new_node = node() # create a new node
new_node.data = data
new_node.next = self.cur_node # link the new node to the 'previous' node.
self.cur_node = new_node # set the current node to the new one.
def list_print(self):
node = self.cur_node # cant point to ll!
while node:
print(node.data)
node = node.next
def main():
ll = linked_list()
num=int(input("Enter a num to push onto the list, -1 to stop: "))
while num!=-1:
data=num
ll.add_node(data)
num=int(input("Enter a num to push onto the list, -1 to stop: "))
print("\n")
ll.list_print()
main()
I'm really stuck here. Thank you in advance for any help!

This should do it:
class Node:
def __init__(self):
self.data = None
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def addNode(self, data):
curr = self.head
if curr is None:
n = Node()
n.data = data
self.head = n
return
if curr.data > data:
n = Node()
n.data = data
n.next = curr
self.head = n
return
while curr.next is not None:
if curr.next.data > data:
break
curr = curr.next
n = Node()
n.data = data
n.next = curr.next
curr.next = n
return
def __str__(self):
data = []
curr = self.head
while curr is not None:
data.append(curr.data)
curr = curr.next
return "[%s]" %(', '.join(str(i) for i in data))
def __repr__(self):
return self.__str__()
def main():
ll = LinkedList()
num = int(input("Enter a number: "))
while num != -1:
ll.addNode(num)
num = int(input("Enter a number: "))
c = ll.head
while c is not None:
print(c.data)
c = c.next
Gives
>>> main()
Enter a number: 5
Enter a number: 3
Enter a number: 2
Enter a number: 4
Enter a number: 1
Enter a number: -1
1
2
3
4
5

class Node:
def __init__(self, data):
self.data = int(data)
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def asc_ordered_list(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
temp = self.head
if temp.data > data:
new_node.next = temp
self.head = new_node
return
while temp.next:
if temp.next.data > data:
break
temp = temp.next
new_node.next = temp.next
temp.next = new_node
def desc_ordered_list(self, data):
new_node = Node(data)
if self.head is None:
self.head = new_node
return
temp = self.head
if data > temp.data:
new_node.next = temp
self.head = new_node
return
while temp.next:
if temp.data > data and temp.next.data < data:
break
temp = temp.next
new_node.next = temp.next
temp.next = new_node
def display_list(self):
temp = self.head
while temp is not None:
print("data = {0}".format(temp.data))
temp = temp.next
if __name__ == "__main__":
llist = LinkedList()
llist.desc_ordered_list(8)
llist.desc_ordered_list(3)
llist.desc_ordered_list(1)
llist.desc_ordered_list(4)
llist.desc_ordered_list(5)
llist.desc_ordered_list(7)
llist.desc_ordered_list(6)
llist.desc_ordered_list(2)
llist.display_list()

4 years later, but I think that is easier in this way
def append(self, value):
new_node = Node(value)
if self.head is None:
self.head = new_node
else:
current = self.head
while current is not None and current.value <= value:
previous = current
current = current.next
if current is self.head:
aux = self.head
self.head = new_node
new_node.next = aux
else:
previous.next = new_node
new_node.next = current
self.size += 1

class Solution:
def sortList(self,node):
if(node is None):
return
temp=node
while(temp!=None):
i=temp.next
while(i!=None):
if(temp.data>i.data):
n=i.data
i.data=temp.data
temp.data=n
i=i.next
temp=temp.next

I thought this was a bit shorter and easier
class Node:
def __init__(self, data, _next=None):
self.data = data
self.next = _next
def main():
nodes = []
num = int(input("Enter number: "))
while num != -1:
nodes.append(Node(num))
num = int(input("Enter number: "))
# If list is empty then just end function
if len(nodes) == 0:
return
# Let python do the sorting
nodes = sorted(nodes, key=lambda node: node.data)
# Link the nodes together and print them while you're at it
for i in range(len(nodes) - 1):
nodes[i].next = nodes[i + 1]
print(nodes[i].data)
# We need to print the last node
print(nodes[-1].data)

Related

Using model Binary Tree code snippet, how to implement this?

I have a code for Binary Tree (Not BST) from MIT 6.006 (2020, MIT OCW). By the way, I have no idea of how to add elements into the Tree using below two Classes (symbol A or T seems to be used instead of a self). Specifically,
how to insert elements into Binary_Tree
how to incorporate the build(X) function into the Binary_Tree
Could anybody give an example of how I can utilize this code?
# From Recitation 6, MIT 6.006, Spring 2020
class Binary_Node:
def __init__(A, x): # O(1)
A.item = x
A.left = None
A.right = None
A.parent = None
def subtree_iter(A): # O(n), in-order traversal
if A.left: yield from A.left.subtree_iter()
yield A
if A.right: yield from A.right.subtree_iter()
def subtree_first(A): # O(h)
if A.left: return A.left.subtree_first()
else: return A
def subtree_last(A): # O(h)
if A.right: return A.right.subtree_last()
else: return A
def successor(A): # O(h)
if A.right: return A.right.subtree_first()
while A.parent and (A is A.parent.right):
A = A.parent
return A.parent
def predecessor(A): # O(h)
if A.left: return A.left.subtree_last()
while A.parent and (A is A.parent.left):
A = A.parent
return A.parent
def subtree_insert_before(A, B): # O(h)
if A.left:
A = A.left.subtree_last()
A.right, B.parent = B, A
else:
A.left, B.parent = B, A
def subtree_insert_after(A, B): # O(h)
if A.right:
A = A.right.subtree_first()
A.left, B.parent = B, A
else:
A.right, B.parent = B, A
def subtree_delete(A): # O(h)
if A.left or A.right:
if A.left: B = A.predecessor()
else: B = A.successor()
A.item, B.item = B.item, A.item
return B.subtree_delete()
if A.parent:
if A.parent.left is A: A.parent.left = None
else: A.parent.right = None
return A
class Binary_Tree:
def __init__(T, Node_Type = Binary_Node):
T.root = None
T.size = 0
T.Node_Type = Node_Type
def __len__(T): return T.size
def __iter__(T):
if T.root:
for A in T.root.subtree_iter():
yield A.item
def build(X):
A = [x for x in X]
def build_subtree(A, i, j):
c = (i + j) // 2
root = self.Node_Type(A[c])
if i < c:
root.left = build_subtree(A, i, c - 1)
root.left.parent = root
if c < j:
root.right = build_subtree(A, c + 1, j)
root.right.parent = root
return root
self.root = build_subtree(A, 0, len(A) - 1)

Why AVL sort is not in place?

I was recently told that AVL sort is not in place. Can anyone please explain it? From the below code, I am not sure where I assign extra space when sorting. In this code, when a data structure is built or an element are inserted, elements are ordered by their key.
Reference for the claim: They are using this claim to motivate "binary heap"
[1].https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-spring-2020/lecture-notes/MIT6_006S20_r08.pdf
Reference for code:
[2]. https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-spring-2020/lecture-notes/MIT6_006S20_r06.pdf
[3]. https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-006-introduction-to-algorithms-spring-2020/lecture-notes/MIT6_006S20_r07.pdf
def height(A):
if A: return A.height
else: return -1
class Binary_Node:
def __init__(self, x):
self.item = x
self.parent = None
self.left = None
self.right = None
self.subtree_update()
def subtree_update(self):
self.height = 1 + max(height(self.left), height(self.right))
def subtree_iter(self):
if self.left: yield from self.left.subtree_iter()
yield self
if self.right: yield from self.right.subtree_iter()
def subtree_first(self):
if self.left: return self.left.subtree_first()
else: return self
def subtree_last(self):
if self.right: return self.right.subtree_last()
else: return self
def sucessor(self):
if self.right: return self.right.subtree_first()
while self.parent and (self is self.parent.right): #A is parent's left child and A's parent exists
self = self.parent
return self.parent
def predecessor(self):
if self.left: return self.left.subtree_last()
while self.parent and (self is self.parent.left):
self = self.parent
return self.parent
def subtree_insert_before(self, A):
if self.left:
self = self.left.subtree_last()
self.right, A.parent = A, self
else:
self.left, A.parent = A, self
self.maintain()
def subtree_insert_after(self, A):
if self.right:
self = self.right.subtree_first()
self.left, A.parent = A, self
else:
self.right, A.parent = A, self
self.maintain()
def delete(self):
if not self.left and not self.right: # when self is leaf
if self.parent:
A = self.parent
if A.left is self: A.left = None
else: A.right = None
self.parent = None
if self.left:
self.item, self.left.subtree_last().item = self.left.subtree_last().item, self.item
self.left.subtree_last().delete()
else:
self.item, self.right.subtree_first().item = self.right.subtree_first().item, self.item
self.right.subtree_last().delete()
def subtree_delete(self):
if self.left or self.right:
if self.left: B = self.predecessor()
else: B = self.sucessor()
self.item, B.item = B.item, self.item
return B.subtree_delete()
if self.parent:
if self.parent.left is self: self.parent.left = None
else: self.parent.right = None
self.parent.maintain()
return self
def subtree_rotate_right(self):
assert self.left
B, E = self.left, self.right
A, C = B.left, B.right
B, self = self, B
self.item, B.item = B.item, self.item
B.left, B.right = A, self
self.left, self.right = C, E
if A: A.parent = B
if E: E.parent = self
B.subtree_update()
self.subtree_update()
def subtree_rotate_left(self):
assert self.right
A, D = self.left, self.right
C, E = D.left, D.right
self, D = D, self
self.item, D.item = D.item, self.item
self.left, self.right = A, C
D.left, D.right = self, E
if A: A.parent = self
if E: E.parent = D
self.subtree_update()
D.subtree_update()
def skew(self):
return height(self.right) - height(self.left)
def rebalance(self):
if self.skew() == 2:
if self.right.skew() < 0:
self.right.subtree_rotate_right()
self.subtree_rotate_left()
elif self.skew() == -2:
if self.left.skew() > 0:
self.left.subtree_rotate_left()
self.subtree_rotate_right()
def maintain(self):
self.rebalance()
self.subtree_update()
if self.parent: self.parent.maintain()
class Binary_Tree:
def __init__(self, Node_Type = Binary_Node):
self.root = None
self.size = 0
self.Node_Type = Node_Type
def __len__(self): return self.size
def __iter__(self):
if self.root:
for A in self.root.subtree_iter():
yield A.item
def build(self, X):
A = [x for x in X]
def build_subtree(A, i, j):
c = (i + j) // 2
root = self.Node_Type(A[c])
if i < c:
root.left = build_subtree(A, i, c - 1)
root.left.parent = root
if j > c:
root.right = build_subtree(A, c + 1, j)
root.right.parent = root
return root
self.root = build_subtree(A, 0, len(A) - 1)
class BST_Node(Binary_Node):
def subtree_find(self, k):
if self.item.key > k:
if self.left: self.left.subtree_find(k)
elif self.item.key < k:
if self.right: self.right.subtree_find(k)
else: return self
return None
def subtree_find_next(self, k):
if self.item.key <= k:
if self.right: return self.right.subtree_find_next(k)
else: return None
elif self.item.key > k:
if self.left: return self.left.subtree_find_next(k)
else: return self
return self
def subtree_find_prev(self, k):
if self.item.key >= k:
if self.left: return self.left.subtree_find_prev(k)
else: return None
elif self.item.key < k:
if self.right: return self.right.subtree_find_prev(k)
else: return self
return self
def subtree_insert(self, B):
if B.item.key < self.item.key:
if self.left: self.left.subtree_insert(B)
else: self.subtree_insert_before(B)
elif B.item.key > self.item.key:
if self.right: self.right.subtree_insert(B)
else: self.subtree_insert_after(B)
else:
self.item = B.item
class Set_Binary_Tree(Binary_Tree):
def __init__(self): super().__init__(BST_Node)
def iter_order(self): yield from self
def build(self, X):
for x in X: self.insert(x)
def find_min(self):
if self.root: return self.root.subtree_first()
def find_max(self):
if self.root: return self.root.subtree_last()
def find(self, k):
if self.root:
node = self.root.subtree_find(k)
if node:
return node.item
def find_next(self, k):
if self.root:
node = self.root.subtree_find_next(k)
if node:
return node.item
def find_prev(self, k):
if self.root:
node = self.root.subtree_find_prev(k)
if node:
return node.item
def insert(self, x):
new = self.Node_Type(x)
if self.root:
self.root.subtree_insert(new)
if new.parent is None: return False
else:
self.root = new
self.size += 1
return True
def delete(self, k):
assert self.root
node = self.root.subtree_find(k)
assert node
ext = node.subtree_delete()
if ext.parent is None: self.root = None
self.size -= 1
return ext.item
Wikipedia defines an in-place algorithm as follows:
In computer science, an in-place algorithm is an algorithm which transforms input using no auxiliary data structure. However, a small amount of extra storage space is allowed for auxiliary variables. The input is usually overwritten by the output as the algorithm executes. An in-place algorithm updates its input sequence only through replacement or swapping of elements.
So one of the properties of an algorithm that is called "in-place" is that it does not copy all input values into an newly allocated data structure. If an algorithm creates a binary search tree (like AVL), for which node objects are created that are populated with the input values, then it cannot be called in-place by the above definition, even if at the end of the process the values are copied back into the input array.
As a comparison, heap sort does not have to create a new data structure, as the input array can be used to reorganise its values into a heap. It merely has to swap values in that array in order to sort it. It is therefore an in-place algorithm.

Removing an Item from a LinkedList

I am trying to make a LinkedList assignment on ruby and was facing difficulties to do the remove method, so I searched in google and got the code from the remove method.
What I can't understand is the logic behind it, I can't understand how it works, how it works the logic to delete it.
class Node
attr_accessor :value, :next_node
def initialize(value, next_node = nil)
#value = value
#next_node = next_node
end
end
class LinkedList
def add(number)
new_node = Node.new(number)
if #head.nil?
#head = new_node
#tail = new_node
else
#tail.next_node = new_node
#tail = new_node
end
end
def get(index)
#your code here
node = #head
while index > 0 && node
node = node.next_node
index -= 1
end
node.value
end
def add_at (index, number)
if #head.nil?
#head = Node.new(number)
#tail = Node.new(number)
else
first = #head
index -= 1
while index > 0 && first
first = first.next_node
index -= 1
end
old_next = first.next_node
first.next_node = Node.new(number)
first.next_node.next_node = old_next
end
end
def remove (index)
node = #head
index -= 1
while index > 0 && node
node = node.next_node
index -= 1
end
node.next_node = node.next_node.next_node
end
end

how to create graph (data structure) using linked lists

I have create my linked list and I need to create a graph without using dictionaries and normal lists, i have to use linked list, how anyone recommended me to build it? my linked list looks like this:
class LinkList:
def __init__(self):
self.head = None
self.tail = None
self.count = int()
def add(self, value):
if not self.head:
self.head = Node(value)
self.tail = self.head
else:
self.tail.next = Node(value)
self.tail = self.tail.next
self.count += 1
def get(self, position):
node = self.head
for i in range(position):
if node:
node = node.next
if not node:
return "posicion no encontrada"
else:
return node.value
def delete_first(self):
if self.head is None:
print("lista vacia, imposible eliminar primer elemento")
elif self.head == self.tail:
self.head = None
self.tail = None
self.count -= 1
print("habia un elemento, lista vacia")
else:
self.head = self.head.next
self.count -= 1
def delete_last(self):
if self.tail is None:
print("lista vacia, imposible eliminar ultimo elemento")
elif self.head == self.tail:
self.head = None
self.tail = None
self.count -= 1
print("habia un elemento, lista vacia")
else:
validate = True
temp = self.head
while validate:
if temp.next == self.tail:
self.tail = temp
self.count -= 1
validate = False
else:
temp = temp.next
def delete(self, number):
temp = self.head
temp2 = self.head
if self.head is None:
print("Lista vacia, imposible eliminar elemento")
else:
if self.head.value == number:
self.delete_first()
elif self.tail.value == number:
self.delete_last()
else:
validate = True
while validate:
temp = temp.next
if temp.value == number:
temp2.next = temp.next
self.count -= 1
validate = False
elif self.tail == temp:
print("El elemento no esta en la lista")
validate = False
temp2 = temp2.next
def __repr__(self):
if self.head is None:
return str("[]")
rep = '['
actual_node = self.head
while actual_node:
if actual_node != self.tail:
rep += '{0},'.format(actual_node.value)
else:
rep += '{0}]'.format(actual_node.value)
break
actual_node = actual_node.next
return rep
To create a graph data structure, you need to modify your linked list so that each node has a pointer to multiple nodes. Since you have a max of 7 connections, this could be an array with the list of connections.
Instead of just having node.next, you might have an array of connections, like node.links where you would add a link to connect a node to any other node in the graph.

How to remove object in Ruby

I've implemented Binary search tree in ruby, and now I need to clean whole structure but I can't find any way to do that.
def post_order_clean(node)
if node.left != nil
post_order_clean(node.left)
end
if node.right != nil
post_order_clean(node.right)
end
node = nil
end
But when i do sth like that:
example = [4,6,9,5,7,3,1]
tree = BST::BinaryTree.new(example)
tree.clean
puts tree.root.value
It still prints out 4 as a root value.
How can I clean the tree with post-order traversing method?
Edit:
Just like #Cary Swoveland mentioned:
.. successively remove nodes (together with arcs directed to the node) that have no arcs directed to other nodes.
That's my point.
I did this solution for insert and remove:
class TreeNode
attr_accessor :val, :left, :right
def initialize(val)
#val = val
#left, #right = nil, nil
end
def insert(v)
side = (v <= val ? :left : :right)
if send(side)
send(side).insert(v)
else
send("#{side}=", TreeNode.new(v))
end
end
def delete(v)
if v < val
self.left = self.left ? self.left.delete(v) : nil
elsif v > val
self.right = self.right ? self.right.delete(v) : nil
else
if self.left.nil?
return self.right
elsif self.right.nil?
return self.left
end
min = self.right
min = min.left while !min.left.nil?
self.val = min.val
self.right = self.right.delete(self.val)
end
self
end
end

Resources