diff --git a/node.py b/node.py
index 14dce07ca7bf368c6af514ed46df043611ea2912..36e56169f87a2ad49a8e8934fa7fd99f905ee679 100755
--- a/node.py
+++ b/node.py
@@ -1,16 +1,19 @@
 #!/usr/bin/python3
+"""Base object for construction of all heap variants"""
+
+
 class Node:
 	def __init__(self, key):
-	#for now contains all pointers that might be needed in any implementation
-	#idea is to use only necessary ones in each implementation
+		"""contains all pointers that might be needed in any implementation.
+		Only necessary ones used in each implementation"""
 		self.key = key
 		self.parent = None
 		self.leftChild = None
-		self.rightChild=None
-		self.nextSibling=None
-		self.prevSibling=None
-		self.leftOnly=False
-		self.rightOnly=False
+		self.rightChild = None
+		self.nextSibling = None
+		self.prevSibling = None
+		self.leftOnly = False
+		self.rightOnly = False
 		
-		self.vertex=None #for testing with Dijkstra's algorithm
+		self.vertex = None  # used for testing with Dijkstra's algorithm
 
diff --git a/pairing_heap.py b/pairing_heap.py
index 8ff4c91a40a9d6e2aebc41e9439e66abea90a178..be23a3b76edaa6f251fd9d95a97291610eeaf831 100644
--- a/pairing_heap.py
+++ b/pairing_heap.py
@@ -1,4 +1,7 @@
 #!/usr/bin/python3
+"""'Universal pairing heap';
+behaviour is decided upon initialisation by a type ID"""
+
 from node import Node
 from pairing_heap_interface import PairingHeapInterface
 from pairing_heap_standard import PairingHeapStandard
@@ -10,69 +13,72 @@ COUNT_TYPE_LINKS=-1
 COUNT_TYPE_COMPS=-2
 COUNT_TYPE_BOTH=0
 
+
 class PairingHeap(PairingHeapInterface):
-	MODES={21:"Pairing_L", 22:"Smooth_L"}
-	mode=0
-	countType=COUNT_TYPE_COMPS
-	heap=None
+	MODES = {21: "Pairing_L", 22: "Smooth_L"}
+	mode = 0
+	countType = COUNT_TYPE_COMPS
+	heap = None
+
 	def __init__(self, mode=0, countType=COUNT_TYPE_COMPS):
 		self.mode=mode
 		self.countType=countType
 
 	def make_heap(self):
-		if self.mode==0:
-			self.heap=PairingHeapStandard()
-		elif self.mode==12:
-			self.heap=SmoothHeap()
-		elif self.mode==21:#root list version, everything lazy, to be used for Dijkstra test in paper
-			self.heap=PairingHeapL()
-		elif self.mode==22:#root list version, everything lazy, to be used for Dijkstra test in paper
-			self.heap=SmoothHeapL()
+		if self.mode == 0:
+			self.heap = PairingHeapStandard()
+		elif self.mode == 12:
+			self.heap = SmoothHeap()
+		elif self.mode == 21:  # root list version, everything lazy, to be used for Dijkstra test in paper
+			self.heap = PairingHeapL()
+		elif self.mode == 22:  # root list version, everything lazy, to be used for Dijkstra test in paper
+			self.heap = SmoothHeapL()
 		else:
 			raise Exception("Invalid heap ID! No heap of type ID {} is implemented.")
 	
 	def find_min(self):
-		#Careful! Implementation is inconsistent across pairing heap types.
 		return self.heap.find_min()
 
 	def insert(self, node):
-		#inserts node; returns number of linking operations performed
-		result=self.heap.insert(node)
+		"""inserts node; returns number of comparisons and
+		number of linking operations performed"""
+		result = self.heap.insert(node)
 		if isinstance(result, tuple):
-			if self.countType==COUNT_TYPE_BOTH:
-				return (result[0], result[1])#(comps, links)
+			if self.countType == COUNT_TYPE_BOTH:
+				return (result[0], result[1])  # (comps, links)
 			else:
 				return result[2+self.countType]
-		else:#result should be single number iff link count and comp count are the same
-			if self.countType==COUNT_TYPE_BOTH:
+		else:  # result should be single number iff link count and comp count are the same
+			if self.countType == COUNT_TYPE_BOTH:
 				return (result, result)
 			else:
 				return result
 
 	def delete_min(self):
-		#deletes min; returns number of linking operations/comparisons performed
-		result=self.heap.delete_min()
-		if len(result)==3:
-			if self.countType==COUNT_TYPE_BOTH:
-				return (result[0], result[1], result[2])#min, comps, links
+		"""deletes min; returns number of linking operations/comparisons performed"""
+		result = self.heap.delete_min()
+		if len(result) == 3:
+			if self.countType == COUNT_TYPE_BOTH:
+				return (result[0], result[1], result[2])  # min node, comps, links
 			else:
-				return (result[0],result[3+self.countType])
-		else:#result should be 2-tuple iff link count and comp count are the same
-			if self.countType==COUNT_TYPE_BOTH:
+				return (result[0], result[3+self.countType])
+		else:  # result should be 2-tuple iff link count and comp count are the same
+			if self.countType == COUNT_TYPE_BOTH:
 				return (result[0], result[1], result[1])
 			else:
 				return result
 		
 	def merge(self, heap2):
-		#merges this heap and heap 2; returns number of linking operations performed
+		"""merges this heap and heap 2;
+		returns number of comparisons and linking operations performed"""
 		result = self.heap.merge(heap2)
 		if isinstance(result, tuple):
-			if self.countType==COUNT_TYPE_BOTH:
-				return (result[0], result[1])#(comps, links)
+			if self.countType == COUNT_TYPE_BOTH:
+				return (result[0], result[1])  # (comps, links)
 			else:
 				return result[2+self.countType]
-		else:#result should be single number iff link count and comp count are the same
-			if self.countType==COUNT_TYPE_BOTH:
+		else:  # should be single number iff link count and comp count are the same
+			if self.countType == COUNT_TYPE_BOTH:
 				return (result, result)
 			else:
 				return result
@@ -81,18 +87,20 @@ class PairingHeap(PairingHeapInterface):
 		self.heap.delete(node)
 
 	def decrease_key(self, node, diff):
+		"""performs decrease-key;
+		returns number of comparisons and linking operations performed"""
 		result = self.heap.decrease_key(node, diff)
 		if isinstance(result, tuple):
-			if self.countType==COUNT_TYPE_BOTH:
-				if result[0]==None or result[1]==None:
-					print("heap {} returns None".format(self.MODES[self.mode]))
+			if self.countType == COUNT_TYPE_BOTH:
+				if result[0] is None or result[1] is None:
+					raise Exception("heap {} returns None".format(self.MODES[self.mode]))
 				return (result[0], result[1])#(comps, links)
 			else:
 				return result[2+self.countType]
-		else:#result should be single number iff link count and comp count are the same
-			if self.countType==COUNT_TYPE_BOTH:
-				if result==None:
-					print("heap {} returns None".format(self.MODES[self.mode]))
+		else:  # result should be single number iff link count and comp count are the same
+			if self.countType == COUNT_TYPE_BOTH:
+				if result is None:
+					raise Exception("heap {} returns None".format(self.MODES[self.mode]))
 				return (result, result)
 			else:
 				return result
diff --git a/pairing_heap_interface.py b/pairing_heap_interface.py
index bd14710d93ee86b345d9b9433f2b297a9c3d0706..22e43d398e3f2043b7cf9207713600f7fe436520 100755
--- a/pairing_heap_interface.py
+++ b/pairing_heap_interface.py
@@ -1,5 +1,6 @@
 #!/usr/bin/python3
-from node import Node
+"""interface implemented by all heap variants"""
+
 class PairingHeapInterface:
 	def __init__(self):
 		self.count = 0
diff --git a/pairing_heap_l.py b/pairing_heap_l.py
index bef91433fbc70ee5c1ab1a4b2fcad9c4ac4bdc76..8cdf4cf81715f47694b011cd8c5e51735ea6f4f2 100644
--- a/pairing_heap_l.py
+++ b/pairing_heap_l.py
@@ -2,180 +2,175 @@
 from node import Node
 from pairing_heap_interface import PairingHeapInterface
 
+
 class PairingHeapL(PairingHeapInterface):
-	#  lazy variant of standard pairing heap (maintaining root-list and consolidating only upon extract-min)
-	forest=[] #list storing roots of all top-level trees
-	def __init__(self, root=None):
-		self.forest=[]
-		if root!=None:
-			root.parent=None
-			self.forest+=[root]
+    """lazy variant of standard pairing heap
+    (maintaining root-list and consolidating only upon extract-min)"""
+    forest = []  # list storing roots of all top-level trees
+
+    def __init__(self, root=None):
+        self.forest = []
+        if root is not None:
+            root.parent = None
+            self.forest += [root]
+
+    def listInorder(self):
+        forestList = []
+        for root in self.forest:
+            forestList += [self.listInorderTree(root)]
+        return forestList
 
-	def listInorder(self):
-		forestList=[]
-		for root in self.forest:
-			forestList+=[self.listInorderTree(root)]
-		return forestList
+    def listInorderTree(self, root):
+        if root is None:
+            return []
+        else:
+            return self.listInorderTree(root.leftChild) + [root.key] + self.listInorderTree(root.nextSibling)
 
-	def listInorderTree(self, root):
-		if root==None:
-			return []
-		else:
-			return self.listInorderTree(root.leftChild)+[root.key]+self.listInorderTree(root.nextSibling)
+    def insert(self, node):
+        # concatenates node to list of trees; returns number of linking ops (always 0) for sake of consistency
+        # print("trying to insert {}...".format(node.key))
+        if node is None:
+            return 0
+        node.parent = None
+        self.forest += [node]
+        return 0
 
-	def insert(self, node):
-		#concatenates node to list of trees; returns number of linking ops (always 0) for sake of consistency
-		#print("trying to insert {}...".format(node.key))
-		if node==None:
-			return 0
-		node.parent=None
-		self.forest+=[node]
-		return 0	
+    def pairing(self):
+        """performs consolidation (left-to-right pairing pass, linking pairs of neighbours,
+         followed by right-to-left combining) and returns number of linking operations"""
+        fs = len(self.forest)
+        if fs < 2:
+            return 0
+        else:
+            # right-to-left-pairing pass
+            pairedForest = []
+            for i in range(0, fs, 2):
+                if i == fs - 1:  # last tree if length of forest is odd-numbered
+                    pairedForest += [self.forest[i]]  # concatenate to new forest (no linking required)
+                else:  # link neighbouring roots
+                    if self.forest[i].key <= self.forest[i + 1].key:
+                        if self.forest[i].leftChild == None:
+                            self.forest[i + 1].parent = self.forest[i]
+                        else:
+                            self.forest[i + 1].nextSibling = self.forest[i].leftChild
+                        self.forest[i].leftChild = self.forest[i + 1]
+                        pairedForest += [self.forest[i]]
+                    else:
+                        if self.forest[i + 1].leftChild == None:
+                            self.forest[i].parent = self.forest[i + 1]
+                        else:
+                            self.forest[i].nextSibling = self.forest[i + 1].leftChild
+                        self.forest[i + 1].leftChild = self.forest[i]
+                        pairedForest += [self.forest[i + 1]]
+            self.forest = pairedForest
 
-	def pairing(self):
-		fs = len(self.forest)
-		#performs pairing pass and returns number of linking operations
-		linkCount=0
-		if fs<2: 
-			return 0
-		else:
-			pairedForest=[]
-			index=-1
-			for i in range(0, fs, 2): #  pairing pass
-				if i==fs-1: #last tree if length of forest is odd-numbered
-					pairedForest+=[self.forest[i]]#concatenate to new forest (no linking required)
-				else:#pair trees
-					if self.forest[i].key<=self.forest[i+1].key:
-						if self.forest[i].leftChild==None:
-							self.forest[i+1].parent=self.forest[i]
-						else:
-							self.forest[i+1].nextSibling=self.forest[i].leftChild
-						self.forest[i].leftChild=self.forest[i+1]
-						pairedForest+=[self.forest[i]]
-					else:
-						if self.forest[i+1].leftChild==None:
-							self.forest[i].parent=self.forest[i+1]
-						else:
-							self.forest[i].nextSibling=self.forest[i+1].leftChild
-						self.forest[i+1].leftChild=self.forest[i]
-						pairedForest+=[self.forest[i+1]]
-			self.forest=pairedForest
-			##print("Result of 1st round {}.".format(self.listInorder()))
-			index = len(self.forest)-1
-			for i in range(len(self.forest)-2, -1, -1): # combining pass
-				if self.forest[index].key<=self.forest[i].key:
-					if self.forest[index].leftChild==None:
-						self.forest[i].parent=self.forest[index]
-					else:
-						self.forest[i].nextSibling=self.forest[index].leftChild
-					self.forest[index].leftChild=self.forest[i]
-				else:
-					if self.forest[i].leftChild==None:
-						self.forest[index].parent=self.forest[i]
-					else:
-						self.forest[index].nextSibling=self.forest[i].leftChild
-					self.forest[i].leftChild=self.forest[index]
-					index=i
+            # right-to-left combining pass
+            index = len(self.forest) - 1
+            for i in range(len(self.forest) - 2, -1, -1):  # link two rightmost roots
+                if self.forest[index].key <= self.forest[i].key:
+                    if self.forest[index].leftChild == None:
+                        self.forest[i].parent = self.forest[index]
+                    else:
+                        self.forest[i].nextSibling = self.forest[index].leftChild
+                    self.forest[index].leftChild = self.forest[i]
+                else:
+                    if self.forest[i].leftChild == None:
+                        self.forest[index].parent = self.forest[i]
+                    else:
+                        self.forest[index].nextSibling = self.forest[i].leftChild
+                    self.forest[i].leftChild = self.forest[index]
+                    index = i
 
-			self.forest=[self.forest[index]]
-			##print("Result of 2nd round {}.".format(self.listInorder()))
-			return (fs-1)
+            self.forest = [self.forest[index]]
+            return (fs - 1)  # number of links needed to consolidate n roots is n-1
 
-	def delete_min(self):
-		#finds and deletes min; restructures forest; returns number of linking operations
-		linkCount=0
-		compCount=0
-		cn = self.pairing()
-		assert len(self.forest)==1
-		#if (len(self.forest)==0):
-		#	print("Cannot delete min of empty heap")
-		#	return (None,0,0)
-		currentSibling=self.forest[0].leftChild
-		while currentSibling!=None:
-			nextSibling=currentSibling.nextSibling
-			self.forest+=[currentSibling]
-			currentSibling.nextSibling=None
-			currentSibling=nextSibling
-		self.forest[-1].parent=None #only for the last concatenated sibling as only this one carried parent pointer
-		minNode = self.forest[0]
-		self.forest=self.forest[1:]
-		##print("Result of delete-min {}.".format(self.listInorder()))
-		###print('**')
-		###print(minNode.key)
-		return (minNode, cn, cn)
+    def delete_min(self):
+        """finds and deletes min; restructures forest; returns number of linking operations"""
+        cn = self.pairing()
+        assert len(self.forest) == 1
+        currentSibling = self.forest[0].leftChild
+        while currentSibling != None:
+            nextSibling = currentSibling.nextSibling
+            self.forest += [currentSibling]
+            currentSibling.nextSibling = None
+            currentSibling = nextSibling
+        self.forest[-1].parent = None  # only for the last concatenated sibling as only this one carried parent pointer
+        minNode = self.forest[0]
+        self.forest = self.forest[1:]
+        return (minNode, cn, cn)
 
-	def decrease_key(self, node, diff):
-		linkCount=0
-		if node==None or diff<=0:
-			return 0
-		elif node.parent==None and node.nextSibling==None: #node is root
-			node.key=node.key-diff
-		else:
-			self.unlink_node(node)
-			node.key=node.key-diff
-			self.forest+=[node]
-		return 0
+    def decrease_key(self, node, diff):
+        """unlinks node from current position in tree (if inner node),
+        decreases key, adds node with subtree to root list"""
+        if node is None or diff <= 0:
+            return 0
+        elif node.parent is None and node.nextSibling is None:  # node is root
+            node.key = node.key - diff
+        else:
+            self.unlink_node(node)
+            node.key = node.key - diff
+            self.forest += [node]
+        return 0
 
-	def merge(self, heap2):
-		#concatenates forests of this heap and heap2; returns number of link operations (always 0) for consistency
-		#print("Trying to merge {} and {}.".format(self.listInorder(), heap2.listInorder()))
-		self.forest+=heap2.forest
-		#print("Result of merge is {}.".format(self.listInorder()))
-		return 0
+    def merge(self, heap2):
+        """concatenates forests of this heap and heap2; returns number of link operations (always 0) for consistency"""
+        self.forest += heap2.forest
+        return 0
 
-	def delete(self, node):
-		if node==None:
-			print("Cannot delete None")
-			return
-		elif node.parent==None and node.nextSibling==None: #node is root
-			print("Trying to delete {}...".format(node.key))
-			index=self.forest.index(node)#slight cheating; would be nicer to use a linked list as forest instead
-			#remove node from forest list
-			self.forest=self.forest[:index]+self.forest[index+1:]
-		else: #node is a child somewhere
-			print("Trying to delete {}...".format(node.key))
-			self.unlink_node(node)
-		#concatenate potential children to forest list
-		sibling=node.leftChild
-		while sibling!=None:
-			self.forest+=[sibling]
-			sibling=sibling.nextSibling
-			if sibling!=None:
-				self.forest[-1].nextSibling=None
-			else:
-				self.forest[-1].parent=None
-		print("Result of deletion of {} is {}.".format(node.key, self.listInorder()))
+    def delete(self, node):
+        """deletes node from heap; concatenates orphaned children to list of roots"""
+        if node is None:
+            # print("Cannot delete None")
+            return
+        elif node.parent is None and node.nextSibling is None:  # node is root
+            # print("Trying to delete {}...".format(node.key))
+            index = self.forest.index(node)  # slight cheating; would be nicer to use a linked list as forest instead
+            # remove node from forest list
+            self.forest = self.forest[:index] + self.forest[index + 1:]
+        else:  # node is a child somewhere
+            # print("Trying to delete {}...".format(node.key))
+            self.unlink_node(node)
+        # concatenate potential children to forest list
+        sibling = node.leftChild
+        while sibling is not None:
+            self.forest += [sibling]
+            sibling = sibling.nextSibling
+            if sibling is not None:
+                self.forest[-1].nextSibling = None
+            else:
+                self.forest[-1].parent = None
+        print("Result of deletion of {} is {}.".format(node.key, self.listInorder()))
 
-				
-	def unlink_node(self, node):
-		#for non-root nodes only (does nothing about forest list, only tree-internal links)
-		if node==None:
-			return
-		else:
-			if node.nextSibling!=None:
-				temp=node.nextSibling
-				while temp.nextSibling!=None:#find rightmost child
-					temp=temp.nextSibling
-				if temp.parent.leftChild==node:#node is leftmost child 
-					#link parent to next sibling
-					temp.parent.leftChild=node.nextSibling
-					node.nextSibling=None
-				else:
-					#node is neither first nor last child of parent
-					prevSibling=temp.parent.leftChild
-					while prevSibling.nextSibling!=node:#find left (previous) sibling
-						prevSibling=prevSibling.nextSibling
-					prevSibling.nextSibling=node.nextSibling #cut out node, link left and right sibling
-					node.nextSibling=None
-			else:
-				#node is rightmost child of parent
-				if node.parent.leftChild==node:
-					#node is only child: just remove
-					node.parent.leftChild=None
-				else:
-					prevSibling=node.parent.leftChild
-					while prevSibling.nextSibling!=node:#find left (previous) sibling
-						prevSibling=prevSibling.nextSibling
-					prevSibling.parent=node.parent
-					prevSibling.nextSibling=None
-			node.parent=None
+    def unlink_node(self, node):
+        """for non-root nodes only: unlinks node from current location, re-establishes links in remaining heap
+        (does nothing about forest list, only tree-internal links)"""
+        if node == None:
+            return
+        else:
+            if node.nextSibling != None:
+                temp = node.nextSibling
+                while temp.nextSibling != None:  # find rightmost child
+                    temp = temp.nextSibling
+                if temp.parent.leftChild == node:  # node is leftmost child
+                    # link parent to next sibling
+                    temp.parent.leftChild = node.nextSibling
+                    node.nextSibling = None
+                else:
+                    # node is neither first nor last child of parent
+                    prevSibling = temp.parent.leftChild
+                    while prevSibling.nextSibling != node:  # find left (previous) sibling
+                        prevSibling = prevSibling.nextSibling
+                    prevSibling.nextSibling = node.nextSibling  # cut out node, link left and right sibling
+                    node.nextSibling = None
+            else:
+                # node is rightmost child of parent
+                if node.parent.leftChild == node:
+                    # node is only child: just remove
+                    node.parent.leftChild = None
+                else:
+                    prevSibling = node.parent.leftChild
+                    while prevSibling.nextSibling != node:  # find left (previous) sibling
+                        prevSibling = prevSibling.nextSibling
+                    prevSibling.parent = node.parent
+                    prevSibling.nextSibling = None
+            node.parent = None
diff --git a/pairing_heap_standard.py b/pairing_heap_standard.py
index f1abe256cb512def1a8459b979d96e02c140e52d..bfd883dde0bd6c48fc0f833255c25d839dd1d182 100644
--- a/pairing_heap_standard.py
+++ b/pairing_heap_standard.py
@@ -2,170 +2,176 @@
 from node import Node
 from pairing_heap_interface import PairingHeapInterface
 
+
 class PairingHeapStandard(PairingHeapInterface):
-	#performs a left-to-right forward pass, then a backward combining pass
-	#TODO: left/right child (page 115)
+	"""standard pairing heap
+	performs a left-to-right forward pass, then a backward combining pass to consolidate"""
+
 	def __init__(self, root=None):
-		self.root=root
+		self.root = root
 
 	def make_heap(self):
-		#this is equivalent to init
+		# this is equivalent to init
 		pass
-	
+
 	def listInorder(self, root):
-		if(root==None):
+		if (root is None):
 			return []
-		return self.listInorder(root.leftChild)+[root.key]+self.listInorder(root.nextSibling)
+		return self.listInorder(root.leftChild) + [root.key] + self.listInorder(root.nextSibling)
 
 	def find_min(self):
-		if self.root==None:
+		if self.root is None:
 			return None
 		else:
 			return self.root
 
 	def insert(self, node):
-		#inserts node as child of root, returns number of link operations
-		linkCount=0
-		#print("trying to insert {}...".format(node.key))
-		if self.root==None: 
-			#heap was empty before
-			self.root=node
+		""" inserts node by linking to current root,
+		returns number of link operations"""
+		linkCount = 0
+		if self.root is None:
+			# heap was empty before
+			self.root = node
 		else:
-			newheap=PairingHeapStandard(node)
-			linkCount=self.merge(newheap)
-		#print(self.listInorder(self.root))
+			newheap = PairingHeapStandard(node)
+			linkCount = self.merge(newheap)
+		# print(self.listInorder(self.root))
 		return linkCount
 
 	def delete_min(self):
-		#print("trying to delete min...")
-		linkCount=0 #counts number of linking operations
-		minKey=None
-		minNode=None
-		if self.root==None:
+		"""Extracts minimum (current root), consolidates orphaned children.
+		returns number of link operations"""
+		linkCount = 0  # counts number of linking operations
+		minNode = None
+		if self.root is None:
 			print("Heap was already empty.")
-			return (minNode,linkCount)
-		elif self.root.leftChild==None:
-			#heap contained only one element
-			minNode=self.root
-			self.root=None
 			return (minNode, linkCount)
-		elif self.root.leftChild.nextSibling==None:
-			#first child has no siblings->first child becomes root
-			minNode=self.root
-			self.root=self.root.leftChild
-			self.root.parent=None
+		elif self.root.leftChild is None:
+			# heap contained only one element
+			minNode = self.root
+			self.root = None
+			return (minNode, linkCount)
+		elif self.root.leftChild.nextSibling is None:
+			# first child has no siblings->first child becomes root
+			minNode = self.root
+			self.root = self.root.leftChild
+			self.root.parent = None
 			return (minNode, linkCount)
 		else:
-			minNode=self.root
-			self.root=self.root.leftChild
-			current=self.root
-			nextSibling=None
-			heaps=[]
-			paired=[]
-			#left-to-right pairing pass v2
-			while current!=None:#create heaps of all orphaned children
-				nextSibling=current.nextSibling
-				heaps+=[PairingHeapStandard(current)]
-				current.nextSibling=None
-				current=nextSibling
-			for j in range(0,len(heaps),2):
-				if(j==len(heaps)-1):#last one
-					paired+=[heaps[j]]
+			minNode = self.root
+			self.root = self.root.leftChild
+			current = self.root
+			nextSibling = None
+			heaps = []
+			paired = []
+			# left-to-right pairing pass
+			while current is not None:  # create heaps of all orphaned children
+				nextSibling = current.nextSibling
+				heaps += [PairingHeapStandard(current)]
+				current.nextSibling = None
+				current = nextSibling
+			for j in range(0, len(heaps), 2):
+				if j == (len(heaps) - 1):  # last one
+					paired += [heaps[j]]
 				else:
-					heap=heaps[j]
-					linkCount+=heap.merge(heaps[j+1])#merge returns its number of link operations
-					paired+=[heap]
-			#combining backwards pass v2
-			combined=paired[-1]#start with last tree
-			for i in range(len(paired)-2, -1, -1):
-				linkCount+=combined.merge(paired[i])#merge returns its number of link operations
-			self.root=combined.root
-			self.root.parent=None
-		#print("result is {}".format(self.listInorder(self.root)))	
+					heap = heaps[j]
+					linkCount += heap.merge(heaps[j + 1])  # merge returns its number of link operations
+					paired += [heap]
+			# combining backwards (right-to-left) pass
+			combined = paired[-1]  # start with last (rightmost) tree
+			for i in range(len(paired) - 2, -1, -1):
+				linkCount += combined.merge(paired[i])  # merge returns its number of link operations
+			self.root = combined.root
+			self.root.parent = None
 		return (minNode, linkCount)
 
 	def merge(self, heap2):
-		linkCount=0 #counts number of linking operations
-		#print("Trying to merge {} and {}...".format(self.listInorder(self.root), self.listInorder(heap2.root)))
-		if self.root==None:#heap is empty
-			self.root=heap2.root
-		elif heap2.root==None:#heap 2 is empty
-			pass #this heap is the result
+		"""merges heap2 with current heap by linking roots.
+		returns number of link operations"""
+		linkCount = 0  # counts number of linking operations
+		if self.root is None:  # heap is empty
+			self.root = heap2.root
+		elif heap2.root is None:  # heap 2 is empty
+			pass  # this heap is the result
 		else:
-			if self.root.key<=heap2.root.key:
-				heap2.root.nextSibling=self.root.leftChild
-				if heap2.root.nextSibling==None:
-					heap2.root.parent=self.root
-				self.root.leftChild=heap2.root
-				linkCount=1
+			# link roots
+			if self.root.key <= heap2.root.key:
+				heap2.root.nextSibling = self.root.leftChild
+				if heap2.root.nextSibling is None:
+					heap2.root.parent = self.root
+				self.root.leftChild = heap2.root
+				linkCount = 1
 			else:
-				self.root.nextSibling=heap2.root.leftChild
-				if self.root.nextSibling==None:
-					self.root.parent=heap2.root
-				heap2.root.leftChild=self.root
-				self.root=heap2.root
-				linkCount=1
-			#TODO check for only children?
-		#print("Result is {}".format(self.listInorder(self.root)))
+				self.root.nextSibling = heap2.root.leftChild
+				if self.root.nextSibling is None:
+					self.root.parent = heap2.root
+				heap2.root.leftChild = self.root
+				self.root = heap2.root
+				linkCount = 1
 		return linkCount
 
-	def decrease_key(self, node, diff):#TODO more testing
-		linkCount=0
-		if self.root==node:
-			self.root.key=self.root.key-diff
+	def decrease_key(self, node, diff):
+		"""cuts node with subtree from current place in tree;
+		decreases key; links node to root"""
+		linkCount = 0
+		if self.root == node:
+			self.root.key = self.root.key - diff
 		else:
-			#first step: cut node from heap
-			self.unlink_node(node)#helper function
-			#second step: decrease key
-			subheap=PairingHeapStandard(node)
-			subheap.root.key=subheap.root.key-diff
-			#third step: merge back in
+			# first step: cut node from heap
+			self.unlink_node(node)  # helper function
+			# second step: decrease key
+			subheap = PairingHeapStandard(node)
+			subheap.root.key = subheap.root.key - diff
+			# third step: merge back in
 			linkCount = self.merge(subheap)
 		return linkCount
 
-	def delete(self, node): #TODO more testing?
-		print("trying to delete {} from {}".format(node.key, self.listInorder(self.root)))
-		if self.root.key==node.key:
-			self.delete_min()
+	def delete(self, node):
+		"""removes node with subtree from current place in tree;
+		deletes node, consolidating orphaned children;
+		links consolidated subtree to root.
+		returns number of link operations"""
+		if node is None:
+			return 0
+		if self.root.key == node.key:
+			(minNode, lc) = self.delete_min()
+			return lc
 		else:
-			self.unlink_node(node)#helper function
-					
-			subheap=PairingHeapStandard(node)
-			subheap.delete_min()
-			self.merge(subheap)
-		print("result is {}".format(self.listInorder(self.root)))
-		pass
+			self.unlink_node(node)  # helper function
+
+			subheap = PairingHeapStandard(node)
+			linkCount = subheap.delete_min()
+			linkCount += self.merge(subheap)
+			return linkCount
 
 	def unlink_node(self, node):
-		#removes node from heap updating pointers
-		if self.root==node:#remove the whole heap
-			self.root=None
+		"""removes node from heap, updating pointers accordingly"""
+		if self.root == node:  # remove the whole heap
+			self.root = None
 		else:
-			if node.nextSibling!=None:
-				temp=node.nextSibling
-				while temp.nextSibling!=None:
-					temp=temp.nextSibling
-				if temp.parent.leftChild==node:#node is leftmost child
-					#link parent to next sibling
-					temp.parent.leftChild=node.nextSibling
-					node.nextSibling=None
+			if node.nextSibling != None:
+				temp = node.nextSibling
+				while temp.nextSibling != None:
+					temp = temp.nextSibling
+				if temp.parent.leftChild == node:  # node is leftmost child
+					# link parent to next sibling
+					temp.parent.leftChild = node.nextSibling
+					node.nextSibling = None
 				else:
-					#node is neither first nor last child of parent
-					prevSibling=temp.parent.leftChild
-					while prevSibling.nextSibling!=node:#find left (previous) sibling
-						prevSibling=prevSibling.nextSibling
-					prevSibling.nextSibling=node.nextSibling #cut out node, link left and right sibling
+					# node is neither first nor last child of parent
+					prevSibling = temp.parent.leftChild
+					while prevSibling.nextSibling != node:  # find left (previous) sibling
+						prevSibling = prevSibling.nextSibling
+					prevSibling.nextSibling = node.nextSibling  # cut out node, link left and right sibling
 			else:
-				#node is rightmost child of parent
-				if node.parent.leftChild==node:
-					#node is only child: just remove
-					node.parent.leftChild=None
+				# node is rightmost child of parent
+				if node.parent.leftChild == node:
+					# node is only child: just remove
+					node.parent.leftChild = None
 				else:
-					prevSibling=node.parent.leftChild
-					while prevSibling.nextSibling!=node:#find left (previous) sibling
-						prevSibling=prevSibling.nextSibling
-					prevSibling.parent=node.parent
-					prevSibling.nextSibling=None
-			node.parent=None	
-		
-			
+					prevSibling = node.parent.leftChild
+					while prevSibling.nextSibling != node:  # find left (previous) sibling
+						prevSibling = prevSibling.nextSibling
+					prevSibling.parent = node.parent
+					prevSibling.nextSibling = None
+			node.parent = None
diff --git a/paper-dijkstra-test-new.py b/scripts/paper-dijkstra-test-new.py
similarity index 91%
rename from paper-dijkstra-test-new.py
rename to scripts/paper-dijkstra-test-new.py
index 412551919286766960e526ed4c77236f52c223ca..a467324ceb1026435900439554e8b273c488c8a0 100755
--- a/paper-dijkstra-test-new.py
+++ b/scripts/paper-dijkstra-test-new.py
@@ -1,12 +1,19 @@
 #!/usr/bin/python3
+"""Experimental script comparing performance of pairing heap and smooth heap
+as priority queue in Dijkstra's algorithm. Algorithm is run on randomly generated
+Erdös-Renyi graphs of fixed size and variable edge probability.
+Results are stored as .csv files in ../data folder and plots of results in ../plots"""
+
+
+import os, sys, inspect
+# ensuring imports work
+current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+parent_dir = os.path.dirname(current_dir)
+sys.path.insert(0, parent_dir)
 from node import Node
-from pairing_heap_interface import PairingHeapInterface
 from pairing_heap import PairingHeap
 import networkx as nx
-import sys
 import random
-import math
-import numpy as np
 import matplotlib.pyplot as plt
 import os
 import psutil
@@ -81,7 +88,7 @@ def plot_avg_counts(avgCounts):
     #plt.gca().invert_xaxis()
     figure = plt.gcf()  # get current figure
     figure.set_size_inches(16, 18)  # set figure's size manually to full screen
-    plt.savefig('plots/paper-dijkstra-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
+    plt.savefig('../plots/paper-dijkstra-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
     plt.legend(loc='best')
     plt.show()
 
@@ -89,14 +96,14 @@ def plot_avg_counts(avgCounts):
 def export_results(xs, results, countType, heapTypes, filename="dijkstra"):
     # parse data as randomness parameter; counts per heap type
     if countType == COUNT_TYPE_BOTH:
-        with open("data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
+        with open("../data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
             csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
             for i in range(len(results[0])):
                 row = [xs[i]] + [results[0][i][k] for k in TYPES.keys()]
                 csvwriter.writerow(row)
-        with open("data/" + filename + '-links.csv', 'w', newline='') as csvfile:
+        with open("../data/" + filename + '-links.csv', 'w', newline='') as csvfile:
             csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
@@ -104,7 +111,7 @@ def export_results(xs, results, countType, heapTypes, filename="dijkstra"):
                 row = [xs[i]] + [results[1][i][k] for k in TYPES.keys()]
                 csvwriter.writerow(row)
     else:
-        fn = "data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "data/" + filename + '-comps.csv'
+        fn = "../data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "../data/" + filename + '-comps.csv'
         with open(fn, 'w', newline='') as csvfile:
             csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
diff --git a/paper-dijkstra-test2-new.py b/scripts/paper-dijkstra-test2-new.py
similarity index 88%
rename from paper-dijkstra-test2-new.py
rename to scripts/paper-dijkstra-test2-new.py
index 9f71a2c14c683e9ec3d170782bf23389246267d4..532e1b74857286524f75ea0fe057ead905ec54e7 100755
--- a/paper-dijkstra-test2-new.py
+++ b/scripts/paper-dijkstra-test2-new.py
@@ -1,14 +1,20 @@
 #!/usr/bin/python3
+"""Experimental script comparing performance of pairing heap and smooth heap
+as priority queue in Dijkstra's algorithm. Algorithm is run on randomly generated
+10-regular graphs of variable size.
+Results are stored as .csv files in ../data folder and plots of results in ../plots"""
+
+
+import os, sys, inspect
+# ensuring imports from parent directory work
+current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+parent_dir = os.path.dirname(current_dir)
+sys.path.insert(0, parent_dir)
 from node import Node
-from pairing_heap_interface import PairingHeapInterface
 from pairing_heap import PairingHeap
 import networkx as nx
-import sys
 import random
-import math
-import numpy as np
 import matplotlib.pyplot as plt
-import os
 import psutil
 import csv
 
@@ -18,27 +24,21 @@ COUNT_TYPE_COMPS = -2
 
 TYPES = {21: "Pairing", 22: "Smooth"} 
 MAX_TYPE_KEY = max(TYPES.keys())
-#COLOURS = ['xkcd:fire engine red', 'xkcd:dusty orange', 'xkcd:clear blue', 'xkcd:cool green',
-#           'xkcd:macaroni and cheese', 'xkcd:fire engine red', 'xkcd:dusty orange', 'xkcd:clear blue',
-#           'xkcd:cool green', 'xkcd:macaroni and cheese', 'xkcd:bright sky blue', 'xkcd:bright sky blue', 'xkcd:green',
-#           'xkcd:ochre', 'xkcd:sea blue', 'xkcd:sea green', 'xkcd:sea blue', 'xkcd:warm grey',
-#           'xkcd:bright sky blue', 'xkcd:bright sky blue']
 LINETYPES = 5 * ['-'] + 5 * ['--'] + ['--', '-'] + ['--', '--', '--', '--', '--', '--', '-', '-']
 FIG_LABELS = ["comparisons", "links"]
 MAX_TYPE_KEY = max(TYPES.keys())
 
+# colours from https://xkcd.com/color/rgb/
 COLOURS = {21:'xkcd:fire engine red', 22:'xkcd:sea green'}
 SHADE_COLOURS = {21:'#fe4d4e', 22:'#58ab8e'}
 
 NUMBER_TESTS = 10  # number of tests to run
-TEST_SIZE = 500  # ,6000,7000,8000,9000,10000,20000,30000,40000,50000,60000,70000,80000,90000,100000
+TEST_SIZE = 500
 EDGE_PROBABILITY = 0.05
 WEIGHT_RANGE = 10000
 
 
 def plot_avg_counts_old(avgCounts):
-    # colours from https://xkcd.com/color/rgb/
-    linetypes = 5 * ["-"] + 5 * ["--"] + ["--", "-"] + ["-, -"]
     plt.figure('Dijkstra with variable connectivity')
     for k in TYPES.keys():
         avgComps = [acounts[k] for acounts in avgCounts[0]]
@@ -52,7 +52,6 @@ def plot_avg_counts_old(avgCounts):
     plt.show()
 
 def plot_avg_counts(avgCounts):
-    # colours from https://xkcd.com/color/rgb/
     MARKERS_COMP = {21:"o", 12:"d", 22:"^"}#https://matplotlib.org/3.1.1/api/markers_api.html
     MARKERS_LINK = {21:"o", 12:"D", 22:"D"}
     plt.figure('avg number of operations in Dijkstra\'s algorithm')
@@ -70,18 +69,18 @@ def plot_avg_counts(avgCounts):
         plt.plot(deviations, avgLinks, color=COLOURS[k], linestyle="--", marker=MARKERS_LINK[k], markerfacecolor=COLOURS[k], markersize=9, markeredgewidth=1, markeredgecolor='black', label=TYPES[k] + " links")
         plt.fill_between(deviations, minLinks, maxLinks, color=SHADE_COLOURS[k], alpha=.3)
 
-
     plt.xlabel('Graph size', fontsize=26)
     plt.ylabel('Avg. number of operations / size', fontsize=26)
     plt.xticks(fontsize=20)
     plt.yticks(fontsize=20)
     plt.rc('legend',fontsize=26) # using a size in points
+    #plt.gca().invert_xaxis()
     plt.legend()
     plt.grid(True)
     #plt.gca().invert_xaxis()
     figure = plt.gcf()  # get current figure
     figure.set_size_inches(16, 18)  # set figure's size manually to full screen
-    plt.savefig('plots/paper-dijkstra2-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
+    plt.savefig('../plots/paper-dijkstra2-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
     plt.legend(loc='best')
     plt.show()
 
@@ -89,14 +88,14 @@ def plot_avg_counts(avgCounts):
 def export_results(xs, results, countType, heapTypes, filename="dijkstra2"):
     # parse data as randomness parameter; counts per heap type
     if countType == COUNT_TYPE_BOTH:
-        with open("data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
+        with open("../data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
             csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
             for i in range(len(results[0])):
                 row = [xs[i]] + [results[0][i][k] for k in TYPES.keys()]
                 csvwriter.writerow(row)
-        with open("data/" + filename + '-links.csv', 'w', newline='') as csvfile:
+        with open("../data/" + filename + '-links.csv', 'w', newline='') as csvfile:
             csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
@@ -104,7 +103,7 @@ def export_results(xs, results, countType, heapTypes, filename="dijkstra2"):
                 row = [xs[i]] + [results[1][i][k] for k in TYPES.keys()]
                 csvwriter.writerow(row)
     else:
-        fn = "data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "data/" + filename + '-comps.csv'
+        fn = "../data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "../data/" + filename + '-comps.csv'
         with open(fn, 'w', newline='') as csvfile:
             csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
             csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
diff --git a/paper-permutations.py b/scripts/paper-permutations.py
similarity index 94%
rename from paper-permutations.py
rename to scripts/paper-permutations.py
index e384830e2a6337afa30e9f26875d452789e18b31..5d8b956ba4576f159ac1be774815ea1cb11bcc02 100755
--- a/paper-permutations.py
+++ b/scripts/paper-permutations.py
@@ -5,7 +5,8 @@ import matplotlib.pyplot as plt
 import math
 import numpy as np
 
-"""This file generates visualizations of the different random permutation classes"""
+"""This file generates visualizations of the different random permutation classes.
+Resulting plots are stored in ../plots"""
 
 def plot_permutation(permutation, title, filename):
     # visualizing given permutation as element index in permutation over element index in sorted list
@@ -25,7 +26,7 @@ def plot_permutation(permutation, title, filename):
     plt.grid(True)
     figure = plt.gcf()  # get current figure
     figure.set_size_inches(16, 18)  # set figure's size manually to full screen
-    plt.savefig('plots/paper-permutation-{}.svg'.format(filename), bbox_inches='tight')  # bbox_inches removes extra white spaces
+    plt.savefig('../plots/paper-permutation-{}.svg'.format(filename), bbox_inches='tight')  # bbox_inches removes extra white spaces
     plt.legend(loc='best')
     plt.show()
     
diff --git a/paper-sorting-loc-new.py b/scripts/paper-sorting-loc-new.py
similarity index 87%
rename from paper-sorting-loc-new.py
rename to scripts/paper-sorting-loc-new.py
index 994df0b32be8b044374b833e265641f2a2da1cef..403323e8cf59276d624b26d85e0d317297448e08 100644
--- a/paper-sorting-loc-new.py
+++ b/scripts/paper-sorting-loc-new.py
@@ -1,13 +1,20 @@
 #!/usr/bin/python3
-from random import shuffle
-import random
+"""Experimental script comparing performance of pairing heap and smooth heap
+in 'sorting mode': n inserts followed by n delete-min operations.
+Input lists are randomly generated 'localised' permutations of fixed length with variable
+locality parameter.
+Results are stored as .csv files in ../data folder and plots of results in ../plots"""
+
+
 import numpy as np
 import matplotlib.pyplot as plt
-import sys
-import signal
-import copy
 import math
 import csv
+import os, sys, inspect
+# ensuring imports work
+current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+parent_dir = os.path.dirname(current_dir)
+sys.path.insert(0, parent_dir)
 from node import Node
 from pairing_heap import PairingHeap
 
@@ -74,24 +81,24 @@ def plot_avg_counts(avgCounts):
 	plt.grid(True)
 	figure = plt.gcf()  # get current figure
 	figure.set_size_inches(16, 18)  # set figure's size manually to your full screen (32x18)
-	plt.savefig('plots/paper-sorting-loc-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
+	plt.savefig('../plots/paper-sorting-loc-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
 	plt.legend(loc='best')
 	plt.show()
 
 
 
 def export_results(params, results, countType, heapTypes, filename="dijkstra"):
-	#  exports results of simulation as separate .csv files, one for links and one for comparisons, into /data directory
+	#  exports results of simulation as separate .csv files, one for links and one for comparisons, into ../data directory
 	#  each row contains randomness parameter value; plus one column containing the number of operations for each heap type
 	if countType == COUNT_TYPE_BOTH:
-		with open("data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
+		with open("../data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
 			for i in range(len(results[0])):
 				row = [params[i]] + [results[0][i][k] for k in TYPES.keys()]
 				csvwriter.writerow(row)
-		with open("data/" + filename + '-links.csv', 'w', newline='') as csvfile:
+		with open("../data/" + filename + '-links.csv', 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
@@ -99,7 +106,7 @@ def export_results(params, results, countType, heapTypes, filename="dijkstra"):
 				row = [params[i]] + [results[1][i][k] for k in TYPES.keys()]
 				csvwriter.writerow(row)
 	else:
-		fn = "data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "data/" + filename + '-comps.csv'
+		fn = "../data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "../data/" + filename + '-comps.csv'
 		with open(fn, 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
diff --git a/paper-sorting-sep-new.py b/scripts/paper-sorting-sep-new.py
similarity index 88%
rename from paper-sorting-sep-new.py
rename to scripts/paper-sorting-sep-new.py
index 265688c11dd662b34f5ce12feeb67587a1e010e9..48cab31997c06339948105da021356862244bdf0 100644
--- a/paper-sorting-sep-new.py
+++ b/scripts/paper-sorting-sep-new.py
@@ -1,13 +1,19 @@
 #!/usr/bin/python3
-from random import shuffle
+"""Experimental script comparing performance of pairing heap and smooth heap
+in 'sorting mode': n inserts followed by n delete-min operations.
+Input lists are randomly generated separable permutations of variable length.
+Results are stored as .csv files in ../data folder and plots of results in ../plots"""
+
 import random
-import numpy as np
 import matplotlib.pyplot as plt
-import sys
-import signal
 import copy
 import math
 import csv
+import os, sys, inspect
+# ensuring imports work
+current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+parent_dir = os.path.dirname(current_dir)
+sys.path.insert(0, parent_dir)
 from node import Node
 from pairing_heap import PairingHeap
 
@@ -61,23 +67,23 @@ def plot_avg_counts(avgCounts):
 	plt.grid(True)
 	figure = plt.gcf()  # get current figure
 	figure.set_size_inches(16, 18)  # set figure's size manually to full screen
-	plt.savefig('plots/paper-sorting-sep-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
+	plt.savefig('../plots/paper-sorting-sep-new-test.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
 	plt.legend(loc='best')
 	plt.show()
 
 
 def export_results(params, results, countType, heapTypes, filename="dijkstra"):
-	#  exports results of simulation as separate .csv files, one for links and one for comparisons, into /data directory
+	#  exports results of simulation as separate .csv files, one for links and one for comparisons, into ../data directory
 	#  each row contains randomness parameter value; plus one column containing the number of operations for each heap type
 	if countType == COUNT_TYPE_BOTH:
-		with open("data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
+		with open("../data/" + filename + '-comps-test.csv', 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
 			for i in range(len(results[0])):
 				row = [params[i]] + [results[0][i][k] for k in TYPES.keys()]
 				csvwriter.writerow(row)
-		with open("data/" + filename + '-links.csv', 'w', newline='') as csvfile:
+		with open("../data/" + filename + '-links-test.csv', 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
@@ -85,7 +91,7 @@ def export_results(params, results, countType, heapTypes, filename="dijkstra"):
 				row = [params[i]] + [results[1][i][k] for k in TYPES.keys()]
 				csvwriter.writerow(row)
 	else:
-		fn = "data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "data/" + filename + '-comps.csv'
+		fn = "../data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "../data/" + filename + '-comps.csv'
 		with open(fn, 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
diff --git a/paper-sorting-subseq-new.py b/scripts/paper-sorting-subseq-new.py
similarity index 87%
rename from paper-sorting-subseq-new.py
rename to scripts/paper-sorting-subseq-new.py
index a72bc084f07da6f06dfea08d526c68e4ae7924cf..2db58de98c79ad1a46587b3c534ed23feb02c3e1 100644
--- a/paper-sorting-subseq-new.py
+++ b/scripts/paper-sorting-subseq-new.py
@@ -1,18 +1,24 @@
 #!/usr/bin/python3
+"""Experimental script comparing performance of pairing heap and smooth heap
+in 'sorting mode': n inserts followed by n delete-min operations.
+Input lists are randomly generated lists of fixed length, containing sorted subsequences
+of variable average length.
+Results are stored as .csv files in ../data folder and plots of results in ../plots"""
+
+
 from random import shuffle
 import random
-import numpy as np
 import matplotlib.pyplot as plt
-import sys
-import signal
 import copy
 import math
 import csv
+import os, sys, inspect
+# ensuring imports work
+current_dir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+parent_dir = os.path.dirname(current_dir)
+sys.path.insert(0, parent_dir)
 from node import Node
 from pairing_heap import PairingHeap
-from pairing_heap_interface import PairingHeapInterface
-from pairing_heap_standard import PairingHeapStandard
-from smooth_heap import SmoothHeap
 
 COUNT_TYPE_BOTH = 0
 COUNT_TYPE_LINKS = -1
@@ -79,23 +85,23 @@ def plot_avg_counts(avgCounts):
 	plt.gca().invert_xaxis()
 	figure = plt.gcf()  # get current figure
 	figure.set_size_inches(16, 18)  # set figure's size manually to full screen
-	plt.savefig('plots/paper-sorting-subseq-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
+	plt.savefig('../plots/paper-sorting-subseq-new.svg', bbox_inches='tight')  # bbox_inches removes extra white spaces
 	plt.legend(loc='best')
 	plt.show()
 
 
 def export_results(params, results, countType, heapTypes, filename="dijkstra"):
-	#  exports results of simulation as separate .csv files, one for links and one for comparisons, into /data directory
+	#  exports results of simulation as separate .csv files, one for links and one for comparisons, into ../data directory
 	#  each row contains randomness parameter value; plus one column containing the number of operations for each heap type
 	if countType == COUNT_TYPE_BOTH:
-		with open("data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
+		with open("../data/" + filename + '-comps.csv', 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
 			for i in range(len(results[0])):
 				row = [params[i]] + [results[0][i][k] for k in TYPES.keys()]
 				csvwriter.writerow(row)
-		with open("data/" + filename + '-links.csv', 'w', newline='') as csvfile:
+		with open("../data/" + filename + '-links.csv', 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.keys()])
@@ -103,7 +109,7 @@ def export_results(params, results, countType, heapTypes, filename="dijkstra"):
 				row = [params[i]] + [results[1][i][k] for k in TYPES.keys()]
 				csvwriter.writerow(row)
 	else:
-		fn = "data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "data/" + filename + '-comps.csv'
+		fn = "../data/" + filename + '-links.csv' if countType == COUNT_TYPE_LINKS else "../data/" + filename + '-comps.csv'
 		with open(fn, 'w', newline='') as csvfile:
 			csvwriter = csv.writer(csvfile, delimiter=';', quotechar='|', quoting=csv.QUOTE_MINIMAL)
 			csvwriter.writerow(["randomness parameter value"] + [name for name in TYPES.values()])
diff --git a/smooth_heap.py b/smooth_heap.py
index 2983981f17482f6326b97935edbda2ce819f03a0..fa3ebce236d4ea1d35dabb98c4e45620a7b97f16 100644
--- a/smooth_heap.py
+++ b/smooth_heap.py
@@ -3,311 +3,314 @@ from node import Node
 import math
 from pairing_heap_interface import PairingHeapInterface
 
+
 class SmoothHeap(PairingHeapInterface):
-	forest=[] #list storing roots of all top-level trees not in buffer
-	buffer=[] #decrease buffer
-	minNode=None
-	size=0
-
-	def __init__(self, root=None):
-		self.forest=[]
-		self.buffer=[]
-		if root!=None:
-			root.parent=None
-			root.nextSibling=root
-			self.minNode=root
-			self.forest+=[root]
-			#self.size=0
-
-	def make_heap(self):
-		#this is equivalent to init
-		pass
-	
-	def find_min(self):
-		return self.minNode
-		
-	def listPreOrderHelper(self, root):
-		res=[]
-		if root.rightChild==None:
-			return [root.key]
-		else:
-			current=root.rightChild
-			res+=[root.key, self.listPreOrderHelper(current)]
-			while current.nextSibling!=root.rightChild:
-				current=current.nextSibling
-				res+=[self.listPreOrderHelper(current)]
-			return [res]
-		
-	def listPreOrder(self):
-		res=[]
-		buf=[]
-		for item in self.forest:
-			res+=self.listPreOrderHelper(item)
-		print(res)
-		for elem in self.buffer:
-			buf+=self.listPreOrderHelper(elem)
-		print("buffer: {}".format(buf))
-
-	def stable_link_left(self, left, right):
-		#left node becomes parent of right node
-		#print("left-linking nodes {} and {}".format(left.key, right.key))
-		if left.rightChild!=None:
-			right.nextSibling = left.rightChild.nextSibling
-			left.rightChild.nextSibling=right
-		else:
-			right.nextSibling = right
-		left.rightChild=right
-		right.parent=left
-		
-	def stable_link_right(self, left, right):
-		#right node becomes parent of left node
-		if right.rightChild==None:
-			right.rightChild=left
-			left.nextSibling=left
-		else:
-			left.nextSibling=right.rightChild.nextSibling
-			right.rightChild.nextSibling=left
-		left.parent=right
-
-	def insert(self, node):
-		#concatenates node to list of trees in pool
-		if node==None:
-			return (0,0)#no comparisons, no links
-		node.nextSibling=node
-		node.parent=None
-		self.forest+=[node]
-		self.size+=1
-		if self.minNode==None or node.key<=self.minNode.key:
-			self.minNode=node
-		#print("Result of insert is {}.".format(self.listInorder()))
-		return (1, 0)#1 comparison, no links
-
-	def merge(self, heap2):
-		if heap2==None:
-			return(0,0)
-		compCount=0
-		linkCount=0
-		if len(self.forest)+len(self.buffer)>len(heap2.forest)+len(heap2.buffer):
-			#first heap larger than second
-			(cc,lc)=heap2.clean_buffer()
-			linkCount+=lc
-			compCount+=cc+1#accounting for minNode comparison (at the end) as well
-			self.forest+=heap2.forest
-		else:
-			(cc,lc)=self.clean_buffer()
-			linkCount+=lc
-			compCount+=cc+1#accounting for minNode comparison (at the end) as well
-			self.forest=heap2.forest+self.forest
-			self.buffer=heap2.buffer
-		self.size+=heap2.size
-		if(self.minNode.key>=heap2.minNode.key):
-			self.minNode=heap2.minNode
-		return (compCount, linkCount)
-
-	def delete_min(self):
-		(compCount, linkCount)=self.clean_buffer()
-		if self.minNode==None or len(self.forest)+len(self.buffer)==0:#this should be the same
-			return (None, 0, 0)
-		minKey = self.minNode.key
-		minKeyNode = self.minNode
-		minNodeChildren=[]
-		
-		if self.minNode.rightChild!=None:
-			minNodeChildren+=[self.minNode.rightChild]
-			self.minNode.rightChild.parent=None
-			current=self.minNode.rightChild.nextSibling
-			self.minNode.rightChild.nextSibling=self.minNode.rightChild
-			
-			while current!=self.minNode.rightChild:
-				minNodeChildren+=[current]
-				tempNode = current
-				current=current.nextSibling
-				tempNode.nextSibling = tempNode
-				tempNode.parent = None
-		idx = self.forest.index(self.minNode)#should we count this somehow?
-		self.forest = self.forest[:idx]+minNodeChildren+self.forest[idx+1:]#replace minNode with its children
-		self.size-=1
-		(cc, lc)=self.treapify()
-		return (minKeyNode, compCount+cc, linkCount+lc)
-
-	def treapify(self):
-		#links roots in pool (forest) into treap and returns number of links/comparisons
-		#this uses the pseudocode of delete-min from https://arxiv.org/abs/1802.05471
-		linkCount=0#counts only number of links
-		compCount=0#counts only number of comparisons
-		if len(self.forest)==0: #pool is empty
-			self.minNode=None
-			return (compCount, linkCount)
-			
-		elif len(self.forest)==1:
-			self.minNode=self.forest[0]
-			return (compCount, linkCount)
-			
-		else:
-			i=0
-			curr_forest=self.forest
-			while i<len(curr_forest)-1:
-				compCount+=1#first if-else comparison
-				if curr_forest[i].key<curr_forest[i+1].key:
-					i=i+1
-				else:
-					skip=False
-					while i>0:
-						compCount+=1
-						linkCount+=1
-						if curr_forest[i-1].key>curr_forest[i+1].key:
-							#stable-link predecessor as parent of current node
-							self.stable_link_left(curr_forest[i-1], curr_forest[i])
-							#remove node at index i from top-list
-							curr_forest=curr_forest[:i]+curr_forest[i+1:]
-							i=i-1
-						else:
-							#stable-link successor as parent of current node
-							self.stable_link_right(curr_forest[i], curr_forest[i+1])
-							#remove node at index i from top-list
-							curr_forest=curr_forest[:i]+curr_forest[i+1:]
-							#i=i+1
-							skip=True
-							break
-					if not skip:#i==0
-						#stable-link current as leftmost child of successor
-						self.stable_link_right(curr_forest[i], curr_forest[i+1])
-						#remove node from top-list
-						curr_forest=curr_forest[i+1:]
-						linkCount+=1
-
-			while i>0:
-				#stable-link predecessor as parent of current node
-				self.stable_link_left(curr_forest[i-1], curr_forest[i])
-				curr_forest=curr_forest[:i]
-				linkCount+=1
-				i=i-1
-			self.forest=curr_forest
-			assert len(self.forest)==1
-			self.minNode=self.forest[0]
-		return (compCount, linkCount)
-		
-
-	def mergesort(self, llist):
-		#standard mergesort, implemented to count comparisons properly
-		if len(llist)<2:
-			return 0, llist
-		split_idx = int(math.floor(len(llist)/2))
-		compsleft, lleft = self.mergesort(llist[:split_idx])
-		compsright, lright = self.mergesort(llist[split_idx:])
-		l=0
-		r=0
-		comps = compsleft+compsright
-		sorted = []
-		while l+r<len(llist):
-			if r==len(lright) or (l<len(lleft) and lleft[l].key<=lright[r].key):
-				sorted+=[lleft[l]]
-				l+=1
-			else:
-				sorted+=[lright[r]]
-				r+=1
-			comps+=1
-		return comps, sorted
-
-	def clean_buffer(self):
-		if len(self.buffer)==0:#buffer is empty
-			return (0,0)
-		comps,self.buffer = self.mergesort(self.buffer)
-		self.buffer.reverse()
-		n=len(self.buffer)
-		
-		while len(self.buffer)>1:
-			self.stable_link_right(self.buffer[0], self.buffer[1])
-			self.buffer=self.buffer[1:]
-
-		treapified = self.buffer[0]
-		self.buffer=[]
-		(compCount,linkCount)=self.merge(SmoothHeap(treapified))
-		
-		return (compCount+comps, linkCount+n-1) #(n-1)links while consolidating
-
-	def decrease_key(self, node, diff):
-		assert node!=None
-		linkCount=0
-		compCount=0
-		node.key = node.key-diff
-		#if self.minNode==None or node.key<self.minNode.key:
-		#	self.minNode=node
-		#compCount+=1
-		
-		if node.parent==None and node.rightChild==None: #node is root and has no children
-			#could just leave this in place
-			if node in self.forest:
-				idx = self.forest.index(node)
-				self.forest=self.forest[:idx]+self.forest[idx+1:]
-				self.buffer+=[node]
-			elif node in self.buffer:
-				pass
-			else:
-				self.listPreOrder()
-				raise Exception("node with key {} is not in heap".format(node.key))
-
-		elif node.parent==None: #node is a root and has children
-			leftChild=node.rightChild.nextSibling
-			if leftChild.nextSibling!=leftChild:
-				node.rightChild.nextSibling=leftChild.nextSibling#cut out leftmost child
-			else:
-				node.rightChild=None
-			leftChild.nextSibling=leftChild
-			leftChild.parent=None
-			if node in self.forest:
-				idx = self.forest.index(node)#remove node from pool and replace with leftChild
-				self.forest = self.forest[:idx] + [leftChild] + self.forest[idx+1:]
-				self.buffer+=[node]
-			elif node in self.buffer:
-				pass
-			else:
-				self.listPreOrder()
-				raise Exception("node with key {} is not in heap".format(node.key))
-		else:#node is not a root
-			leftChild=None
-			if node.rightChild!=None:
-				leftChild=node.rightChild.nextSibling
-				leftChild.parent=node.parent
-			current=node.parent.rightChild
-			
-			if node.nextSibling==node and leftChild!=None:#node not a leaf and has no siblings
-				if leftChild.nextSibling!=leftChild:
-					node.rightChild.nextSibling=leftChild.nextSibling#cut out leftmost child
-				else:
-					node.rightChild=None
-				leftChild.nextSibling=leftChild
-				node.parent.rightChild = leftChild
-				
-			elif leftChild!=None:#node is not a leaf and has siblings
-				if leftChild.nextSibling!=leftChild:
-					node.rightChild.nextSibling=leftChild.nextSibling#cut out leftmost child
-				else:
-					node.rightChild=None
-				while current.nextSibling!=node:#find predecessor of node
-					current=current.nextSibling
-				current.nextSibling=leftChild
-				leftChild.nextSibling=node.nextSibling
-				if node.parent.rightChild==node:
-					node.parent.rightChild=leftChild
-					
-			elif node.nextSibling!=node:#node is leaf and has siblings
-				while current.nextSibling!=node:
-					current=current.nextSibling
-				current.nextSibling=node.nextSibling
-				if node.parent.rightChild==node:
-					node.parent.rightChild=current
-					
-			else: #node is leaf and has no siblings
-				node.parent.rightChild=None
-		
-			node.parent=None
-			node.nextSibling=node
-			self.buffer+=[node]
-			
-		if len(self.buffer)>math.ceil(math.log(self.size,2)):
-			#(cc2, lc2)=self.clean_buffer()
-			(cc2, lc2)=self.clean_buffer()
-			compCount+=cc2
-			linkCount+=lc2
-		return (compCount, linkCount)
+    forest = []  # list storing roots of all top-level trees not in buffer
+    buffer = []  # decrease buffer
+    minNode = None
+    size = 0
+
+    def __init__(self, root=None):
+        self.forest = []
+        self.buffer = []
+        if root is not None:
+            root.parent = None
+            root.nextSibling = root
+            self.minNode = root
+            self.forest += [root]
+
+
+    def make_heap(self):
+        # this is equivalent to init
+        pass
+
+    def find_min(self):
+        return self.minNode
+
+    def listPreOrderHelper(self, root):
+        res = []
+        if root.rightChild is None:
+            return [root.key]
+        else:
+            current = root.rightChild
+            res += [root.key, self.listPreOrderHelper(current)]
+            while current.nextSibling != root.rightChild:
+                current = current.nextSibling
+                res += [self.listPreOrderHelper(current)]
+            return [res]
+
+    def listPreOrder(self):
+        res = []
+        buf = []
+        for item in self.forest:
+            res += self.listPreOrderHelper(item)
+        print(res)
+        for elem in self.buffer:
+            buf += self.listPreOrderHelper(elem)
+        print("buffer: {}".format(buf))
+
+    def stable_link_left(self, left, right):
+        """left node becomes parent of right node"""
+        if left.rightChild is not None:
+            right.nextSibling = left.rightChild.nextSibling
+            left.rightChild.nextSibling = right
+        else:
+            right.nextSibling = right
+        left.rightChild = right
+        right.parent = left
+
+    def stable_link_right(self, left, right):
+        """right node becomes parent of left node"""
+        if right.rightChild is None:
+            right.rightChild = left
+            left.nextSibling = left
+        else:
+            left.nextSibling = right.rightChild.nextSibling
+            right.rightChild.nextSibling = left
+        left.parent = right
+
+    def insert(self, node):
+        """concatenates node to list of roots in forest list"""
+        if node is None:
+            return (0, 0)  # no comparisons, no links
+        node.nextSibling = node
+        node.parent = None
+        self.forest += [node]
+        self.size += 1
+        if self.minNode is None or node.key <= self.minNode.key:
+            self.minNode = node
+        return (1, 0)  # 1 comparison, no links
+
+    def merge(self, heap2):
+        """cleans buffer of smaller heap, then concatenates forest lists
+        returns number of comparisons and link operations"""
+        if heap2 is None:
+            return (0, 0)
+        compCount = 0
+        linkCount = 0
+        if len(self.forest) + len(self.buffer) > len(heap2.forest) + len(heap2.buffer):
+            # first heap larger than second
+            (cc, lc) = heap2.clean_buffer()
+            linkCount += lc
+            compCount += cc + 1  # accounting for minNode comparison (at the end) as well
+            self.forest += heap2.forest
+        else:
+            (cc, lc) = self.clean_buffer()
+            linkCount += lc
+            compCount += cc + 1  # accounting for minNode comparison (at the end) as well
+            self.forest = heap2.forest + self.forest
+            self.buffer = heap2.buffer
+        self.size += heap2.size
+        if (self.minNode.key >= heap2.minNode.key):
+            self.minNode = heap2.minNode
+        return (compCount, linkCount)
+
+    def delete_min(self):
+        """consolidates and empties buffer, replaces minimum by its children in root list,
+        then consolidates root list.
+        Returns minNode, number of comparisons, number of link operations"""
+        (compCount, linkCount) = self.clean_buffer()
+        if self.minNode is None or len(self.forest) + len(self.buffer) == 0:  # this should be the same
+            return (None, 0, 0)
+        minKeyNode = self.minNode
+        minNodeChildren = []
+
+        if self.minNode.rightChild is not None:
+            minNodeChildren += [self.minNode.rightChild]
+            self.minNode.rightChild.parent = None
+            current = self.minNode.rightChild.nextSibling
+            self.minNode.rightChild.nextSibling = self.minNode.rightChild
+
+            while current != self.minNode.rightChild:
+                minNodeChildren += [current]
+                tempNode = current
+                current = current.nextSibling
+                tempNode.nextSibling = tempNode
+                tempNode.parent = None
+        idx = self.forest.index(self.minNode)
+        self.forest = self.forest[:idx] + minNodeChildren + self.forest[idx + 1:]  # replace minNode with its children
+        self.size -= 1
+        (cc, lc) = self.treapify()
+        return (minKeyNode, compCount + cc, linkCount + lc)
+
+    def treapify(self):
+        """links roots in pool (forest) into treap
+        (this uses the pseudocode of delete-min from https://arxiv.org/abs/1802.05471)
+        returns number of links/comparisons
+        """
+        linkCount = 0  # counts only number of links
+        compCount = 0  # counts only number of comparisons
+        if len(self.forest) == 0:  # pool is empty
+            self.minNode = None
+            return (compCount, linkCount)
+
+        elif len(self.forest) == 1:
+            self.minNode = self.forest[0]
+            return (compCount, linkCount)
+
+        else:
+            i = 0
+            curr_forest = self.forest
+            while i < len(curr_forest) - 1:
+                compCount += 1  # first if-else comparison
+                if curr_forest[i].key < curr_forest[i + 1].key:
+                    i = i + 1
+                else:
+                    skip = False
+                    while i > 0:
+                        compCount += 1
+                        linkCount += 1
+                        if curr_forest[i - 1].key > curr_forest[i + 1].key:
+                            # stable-link predecessor as parent of current node
+                            self.stable_link_left(curr_forest[i - 1], curr_forest[i])
+                            # remove node at index i from top-list
+                            curr_forest = curr_forest[:i] + curr_forest[i + 1:]
+                            i = i - 1
+                        else:
+                            # stable-link successor as parent of current node
+                            self.stable_link_right(curr_forest[i], curr_forest[i + 1])
+                            # remove node at index i from top-list
+                            curr_forest = curr_forest[:i] + curr_forest[i + 1:]
+                            # i=i+1
+                            skip = True
+                            break
+                    if not skip:  # i==0
+                        # stable-link current as leftmost child of successor
+                        self.stable_link_right(curr_forest[i], curr_forest[i + 1])
+                        # remove node from top-list
+                        curr_forest = curr_forest[i + 1:]
+                        linkCount += 1
+
+            while i > 0:
+                # stable-link predecessor as parent of current node
+                self.stable_link_left(curr_forest[i - 1], curr_forest[i])
+                curr_forest = curr_forest[:i]
+                linkCount += 1
+                i = i - 1
+            self.forest = curr_forest
+            assert len(self.forest) == 1
+            self.minNode = self.forest[0]
+        return (compCount, linkCount)
+
+    def mergesort(self, llist):
+        # standard mergesort, implemented to count comparisons properly
+        if len(llist) < 2:
+            return 0, llist
+        split_idx = int(math.floor(len(llist) / 2))
+        compsleft, lleft = self.mergesort(llist[:split_idx])
+        compsright, lright = self.mergesort(llist[split_idx:])
+        l = 0
+        r = 0
+        comps = compsleft + compsright
+        sorted = []
+        while l + r < len(llist):
+            if r == len(lright) or (l < len(lleft) and lleft[l].key <= lright[r].key):
+                sorted += [lleft[l]]
+                l += 1
+            else:
+                sorted += [lright[r]]
+                r += 1
+            comps += 1
+        return comps, sorted
+
+    def clean_buffer(self):
+        if len(self.buffer) == 0:  # buffer is empty
+            return (0, 0)
+        comps, self.buffer = self.mergesort(self.buffer)
+        self.buffer.reverse()
+        n = len(self.buffer)
+
+        while len(self.buffer) > 1:
+            self.stable_link_right(self.buffer[0], self.buffer[1])
+            self.buffer = self.buffer[1:]
+
+        treapified = self.buffer[0]
+        self.buffer = []
+        (compCount, linkCount) = self.merge(SmoothHeap(treapified))
+
+        return (compCount + comps, linkCount + n - 1)  # (n-1)links while consolidating
+
+    def decrease_key(self, node, diff):
+        """cut out node from current location, leaving leftmost child;
+        decrease key; place node with remaining subtree in buffer.
+        Returns number of comparisons, links"""
+        assert node is not None
+        linkCount = 0
+        compCount = 0
+        node.key = node.key - diff
+
+        if node.parent is None and node.rightChild is None:  # node is root and has no children
+            # could just leave this in place alternatively
+            if node in self.forest:
+                idx = self.forest.index(node)
+                self.forest = self.forest[:idx] + self.forest[idx + 1:]
+                self.buffer += [node]
+            elif node in self.buffer:
+                pass
+            else:
+                self.listPreOrder()
+                raise Exception("node with key {} is not in heap".format(node.key))
+
+        elif node.parent is None:  # node is a root and has children
+            leftChild = node.rightChild.nextSibling
+            if leftChild.nextSibling != leftChild:
+                node.rightChild.nextSibling = leftChild.nextSibling  # cut out leftmost child
+            else:
+                node.rightChild = None
+            leftChild.nextSibling = leftChild
+            leftChild.parent = None
+            if node in self.forest:
+                idx = self.forest.index(node)  # remove node from pool and replace with leftChild
+                self.forest = self.forest[:idx] + [leftChild] + self.forest[idx + 1:]
+                self.buffer += [node]
+            elif node in self.buffer:
+                pass
+            else:
+                self.listPreOrder()
+                raise Exception("node with key {} is not in heap".format(node.key))
+        else:  # node is not a root
+            leftChild = None
+            if node.rightChild is not None:
+                leftChild = node.rightChild.nextSibling
+                leftChild.parent = node.parent
+            current = node.parent.rightChild
+
+            if node.nextSibling == node and leftChild is not None:  # node not a leaf and has no siblings
+                if leftChild.nextSibling != leftChild:
+                    node.rightChild.nextSibling = leftChild.nextSibling  # cut out leftmost child
+                else:
+                    node.rightChild = None
+                leftChild.nextSibling = leftChild
+                node.parent.rightChild = leftChild
+
+            elif leftChild is not None:  # node is not a leaf and has siblings
+                if leftChild.nextSibling != leftChild:
+                    node.rightChild.nextSibling = leftChild.nextSibling  # cut out leftmost child
+                else:
+                    node.rightChild = None
+                while current.nextSibling != node:  # find predecessor of node
+                    current = current.nextSibling
+                current.nextSibling = leftChild
+                leftChild.nextSibling = node.nextSibling
+                if node.parent.rightChild == node:
+                    node.parent.rightChild = leftChild
+
+            elif node.nextSibling != node:  # node is leaf and has siblings
+                while current.nextSibling != node:
+                    current = current.nextSibling
+                current.nextSibling = node.nextSibling
+                if node.parent.rightChild == node:
+                    node.parent.rightChild = current
+
+            else:  # node is leaf and has no siblings
+                node.parent.rightChild = None
+
+            node.parent = None
+            node.nextSibling = node
+            self.buffer += [node]
+
+        if len(self.buffer) > math.ceil(math.log(self.size, 2)):
+            (cc2, lc2) = self.clean_buffer()
+            compCount += cc2
+            linkCount += lc2
+        return (compCount, linkCount)
diff --git a/smooth_heap_l.py b/smooth_heap_l.py
index 0c62c78bbe63370868a9f392e8eaac97e1ce05ae..5b7bc6572c7c489688559dae088ab8be7287a943 100644
--- a/smooth_heap_l.py
+++ b/smooth_heap_l.py
@@ -3,224 +3,202 @@ from node import Node
 import math
 from pairing_heap_interface import PairingHeapInterface
 
+
 class SmoothHeapL(PairingHeapInterface):
-	forest=[] #list storing roots of all top-level trees not in buffer
-	minNode=None
-
-	def __init__(self, root=None):
-		self.forest=[]
-		if root!=None:
-			root.parent=None
-			root.nextSibling=root
-			self.minNode=root
-			self.forest+=[root]
-
-	def make_heap(self):
-		#this is equivalent to init
-		pass
-	
-	def find_min(self):
-		return self.minNode
-		
-	def listPreOrderHelper(self, root):
-		res=[]
-		if root.rightChild==None:
-			return [root.key]
-		else:
-			current=root.rightChild
-			res+=[root.key, self.listPreOrderHelper(current)]
-			while current.nextSibling!=root.rightChild:
-				current=current.nextSibling
-				res+=[self.listPreOrderHelper(current)]
-			return [res]
-		
-	def listPreOrder(self):
-		res=[]
-		buf=[]
-		for item in self.forest:
-			res+=self.listPreOrderHelper(item)
-		print(res)
-		
-	def stable_link_left(self, left, right):
-		#left node becomes parent of right node
-		#print("left-linking nodes {} and {}".format(left.key, right.key))
-		if left.rightChild!=None:
-			right.nextSibling = left.rightChild.nextSibling
-			left.rightChild.nextSibling=right
-		else:
-			right.nextSibling = right
-		left.rightChild=right
-		right.parent=left
-		
-	def stable_link_right(self, left, right):
-		#right node becomes parent of left node
-		if right.rightChild==None:
-			right.rightChild=left
-			left.nextSibling=left
-		else:
-			left.nextSibling=right.rightChild.nextSibling
-			right.rightChild.nextSibling=left
-		left.parent=right
-
-	def insert(self, node):
-		#concatenates node to list of trees in pool
-		if node==None:
-			return (0,0)#no comparisons, no links
-		node.nextSibling=node
-		node.parent=None
-		self.forest+=[node]
-		#if self.minNode==None or node.key<self.minNode.key:
-		#	self.minNode=node
-		#print("Result of insert is {}.".format(self.listInorder()))
-		return (0, 0)#1 comparison, no links
-
-	def merge(self, heap2):
-		if heap2==None:
-			return(0,0)
-		compCount=0
-		linkCount=0
-		if len(self.forest)>len(heap2.forest):
-			#first heap larger than second
-			self.forest+=heap2.forest
-		else:
-			self.forest=heap2.forest+self.forest
-		#if(self.minNode.key>heap2.minNode.key):
- 		#	self.minNode=heap2.minNode
-		return (compCount, linkCount)#TODO add 1 if comparing minnode
-
-	def delete_min(self):
-		if (len(self.forest)==0):
-			return(None,0,0)
-		(cc, lc)=self.treapify()
-		assert len(self.forest)==1
-		minKey = self.minNode.key
-		minKeyNode = self.minNode
-		minNodeChildren=[]
-		
-		if self.minNode.rightChild!=None:
-			minNodeChildren+=[self.minNode.rightChild]
-			self.minNode.rightChild.parent=None
-			current=self.minNode.rightChild.nextSibling
-			self.minNode.rightChild.nextSibling=self.minNode.rightChild
-			
-			while current!=self.minNode.rightChild:
-				minNodeChildren+=[current]
-				tempNode = current
-				current=current.nextSibling
-				tempNode.nextSibling = tempNode
-				tempNode.parent = None
-		self.forest = minNodeChildren
-		#print('###')
-		#print(minKeyNode.key)
-		return (minKeyNode, cc, lc)
-
-	def treapify(self):
-		#links roots in pool (forest) into treap and returns number of links/comparisons
-		#this uses the pseudocode of delete-min from https://arxiv.org/abs/1802.05471
-		linkCount=0#counts only number of links
-		compCount=0#counts only number of comparisons
-		fs = len(self.forest)
-		if len(self.forest)==0: #pool is empty
-			self.minNode=None
-			return (compCount, linkCount)
-			
-		elif len(self.forest)==1:
-			self.minNode=self.forest[0]
-			return (compCount, linkCount)
-			
-		else:
-			i=0
-			curr_forest=self.forest
-			while i<len(curr_forest)-1:
-				compCount+=1#first if-else comparison
-				if curr_forest[i].key<curr_forest[i+1].key:
-					i=i+1
-				else:
-					skip=False
-					while i>0:
-						compCount+=1
-						linkCount+=1
-						if curr_forest[i-1].key>curr_forest[i+1].key:
-							#stable-link predecessor as parent of current node
-							self.stable_link_left(curr_forest[i-1], curr_forest[i])
-							#remove node at index i from top-list
-							curr_forest=curr_forest[:i]+curr_forest[i+1:]
-							i=i-1
-						else:
-							#stable-link successor as parent of current node
-							self.stable_link_right(curr_forest[i], curr_forest[i+1])
-							#remove node at index i from top-list
-							curr_forest=curr_forest[:i]+curr_forest[i+1:]
-							#i=i+1
-							skip=True
-							break
-					if not skip:#i==0
-						#stable-link current as leftmost child of successor
-						self.stable_link_right(curr_forest[i], curr_forest[i+1])
-						#remove node from top-list
-						curr_forest=curr_forest[i+1:]
-						linkCount+=1
-
-			while i>0:
-				#stable-link predecessor as parent of current node
-				self.stable_link_left(curr_forest[i-1], curr_forest[i])
-				curr_forest=curr_forest[:i]
-				linkCount+=1
-				i=i-1
-			self.forest=curr_forest
-			assert len(self.forest)==1
-			self.minNode=self.forest[0]
-		assert(fs-1 == linkCount)
-		return (compCount, linkCount)
-		
-        
-	def mergesort(self, llist):
-		#standard mergesort, implemented to count comparisons properly
-		if len(llist)<2:
-			return 0, llist
-		split_idx = int(math.floor(len(llist)/2))
-		compsleft, lleft = self.mergesort(llist[:split_idx])
-		compsright, lright = self.mergesort(llist[split_idx:])
-		l=0
-		r=0
-		comps = compsleft+compsright
-		sorted = []
-		while l+r<len(llist):
-			if r==len(lright) or (l<len(lleft) and lleft[l].key<=lright[r].key):
-				sorted+=[lleft[l]]
-				l+=1
-			else:
-				sorted+=[lright[r]]
-				r+=1
-			comps+=1
-		return comps, sorted
-
-	def decrease_key(self, node, diff):
-		assert node!=None
-		node.key = node.key-diff
-		
-		#concatenates node to list of trees in pool
-
-		if node.parent==None: #node is a root and has children
-			if node in self.forest:
-				pass #leave in-place
-			else:
-				self.listPreOrder()
-				raise Exception("node with key {} is not in heap".format(node.key))
-		else:#node is not a root
-			
-			if node.nextSibling==node:#node has no siblings
-				node.parent.rightChild=None
-								
-			else:#node has siblings
-				current=node.nextSibling
-				while current.nextSibling!=node:#find predecessor of node
-					current=current.nextSibling
-				current.nextSibling=node.nextSibling
-				if node.parent.rightChild==node:
-					node.parent.rightChild=current
-		
-			node.parent=None
-			node.nextSibling=node
-			self.forest+=[node]
-		return (0, 0)
+    """lazy implementation of smooth heap without buffer"""
+    forest = []  # list storing roots of all top-level trees
+    minNode = None
+
+    def __init__(self, root=None):
+        self.forest = []
+        if root != None:
+            root.parent = None
+            root.nextSibling = root
+            self.minNode = root
+            self.forest += [root]
+
+    def make_heap(self):
+        # this is equivalent to init
+        pass
+
+    def find_min(self):
+        return self.minNode
+
+    def listPreOrderHelper(self, root):
+        res = []
+        if root.rightChild == None:
+            return [root.key]
+        else:
+            current = root.rightChild
+            res += [root.key, self.listPreOrderHelper(current)]
+            while current.nextSibling != root.rightChild:
+                current = current.nextSibling
+                res += [self.listPreOrderHelper(current)]
+            return [res]
+
+    def listPreOrder(self):
+        res = []
+        buf = []
+        for item in self.forest:
+            res += self.listPreOrderHelper(item)
+        print(res)
+
+    def stable_link_left(self, left, right):
+        """left node becomes parent of right node"""
+        if left.rightChild != None:
+            right.nextSibling = left.rightChild.nextSibling
+            left.rightChild.nextSibling = right
+        else:
+            right.nextSibling = right
+        left.rightChild = right
+        right.parent = left
+
+    def stable_link_right(self, left, right):
+        """right node becomes parent of left node"""
+        if right.rightChild is None:
+            right.rightChild = left
+            left.nextSibling = left
+        else:
+            left.nextSibling = right.rightChild.nextSibling
+            right.rightChild.nextSibling = left
+        left.parent = right
+
+    def insert(self, node):
+        """concatenates node to list of trees in pool"""
+        if node is None:
+            return (0, 0)  # no comparisons, no links
+        node.nextSibling = node
+        node.parent = None
+        self.forest += [node]
+        return (0, 0)  # 1 comparison, no links
+
+    def merge(self, heap2):
+        """concatenates root lists of heaps"""
+        if heap2 is None:
+            return (0, 0)
+        compCount = 0
+        linkCount = 0
+        if len(self.forest) > len(heap2.forest):
+            # first heap larger than second
+            self.forest += heap2.forest
+        else:
+            self.forest = heap2.forest + self.forest
+        return (compCount, linkCount)
+
+    def delete_min(self):
+        """consolidates into single tree; extracts min node,
+        placing its orphaned children in root list.
+        Returns min node, number comparisons, number links"""
+        if len(self.forest) == 0:
+            return (None, 0, 0)
+        (cc, lc) = self.treapify()
+        assert len(self.forest) == 1
+        minKeyNode = self.minNode
+        minNodeChildren = []
+
+        if self.minNode.rightChild is not None:
+            minNodeChildren += [self.minNode.rightChild]
+            self.minNode.rightChild.parent = None
+            current = self.minNode.rightChild.nextSibling
+            self.minNode.rightChild.nextSibling = self.minNode.rightChild
+
+            while current != self.minNode.rightChild:
+                minNodeChildren += [current]
+                tempNode = current
+                current = current.nextSibling
+                tempNode.nextSibling = tempNode
+                tempNode.parent = None
+        self.forest = minNodeChildren
+        return (minKeyNode, cc, lc)
+
+    def treapify(self):
+        """links roots in pool (forest) into treap and returns number of links/comparisons
+        this uses the pseudocode of delete-min from https://arxiv.org/abs/1802.05471
+        returns number comparisons, number link operations performed"""
+        linkCount = 0  # counts only number of links
+        compCount = 0  # counts only number of comparisons
+        fs = len(self.forest)
+        if len(self.forest) == 0:  # pool is empty
+            self.minNode = None
+            return (compCount, linkCount)
+
+        elif len(self.forest) == 1:
+            self.minNode = self.forest[0]
+            return (compCount, linkCount)
+
+        else:
+            i = 0
+            curr_forest = self.forest
+            while i < len(curr_forest) - 1:
+                compCount += 1  # first if-else comparison
+                if curr_forest[i].key < curr_forest[i + 1].key:
+                    i = i + 1
+                else:
+                    skip = False
+                    while i > 0:
+                        compCount += 1
+                        linkCount += 1
+                        if curr_forest[i - 1].key > curr_forest[i + 1].key:
+                            # stable-link predecessor as parent of current node
+                            self.stable_link_left(curr_forest[i - 1], curr_forest[i])
+                            # remove node at index i from top-list
+                            curr_forest = curr_forest[:i] + curr_forest[i + 1:]
+                            i = i - 1
+                        else:
+                            # stable-link successor as parent of current node
+                            self.stable_link_right(curr_forest[i], curr_forest[i + 1])
+                            # remove node at index i from top-list
+                            curr_forest = curr_forest[:i] + curr_forest[i + 1:]
+                            # i=i+1
+                            skip = True
+                            break
+                    if not skip:  # i==0
+                        # stable-link current as leftmost child of successor
+                        self.stable_link_right(curr_forest[i], curr_forest[i + 1])
+                        # remove node from top-list
+                        curr_forest = curr_forest[i + 1:]
+                        linkCount += 1
+
+            while i > 0:
+                # stable-link predecessor as parent of current node
+                self.stable_link_left(curr_forest[i - 1], curr_forest[i])
+                curr_forest = curr_forest[:i]
+                linkCount += 1
+                i = i - 1
+            self.forest = curr_forest
+            assert len(self.forest) == 1
+            self.minNode = self.forest[0]
+        assert (fs - 1 == linkCount)
+        return (compCount, linkCount)
+
+
+    def decrease_key(self, node, diff):
+        """removes node with subtree from current position;
+        decreases key; places node in root list."""
+        assert node is not None
+        node.key = node.key - diff
+        # concatenates node to list of trees in pool
+
+        if node.parent is None:  # node is a root and has children
+            if node in self.forest:
+                pass  # leave in-place
+            else:
+                self.listPreOrder()
+                raise Exception("node with key {} is not in heap".format(node.key))
+        else:  # node is not a root
+
+            if node.nextSibling == node:  # node has no siblings
+                node.parent.rightChild = None
+
+            else:  # node has siblings
+                current = node.nextSibling
+                while current.nextSibling != node:  # find predecessor of node
+                    current = current.nextSibling
+                current.nextSibling = node.nextSibling
+                if node.parent.rightChild == node:
+                    node.parent.rightChild = current
+
+            node.parent = None
+            node.nextSibling = node
+            self.forest += [node]
+        return (0, 0)