diff --git a/README b/README index 8658cde..5e9a57d 100644 --- a/README +++ b/README @@ -1,50 +1,11 @@ -Copyright (c) 2010 Pavel Grafov +Getting the idea from the original repository I made a simple +implementation for a project in my studying department. +Access of nodes is recursive. -Implementation of AVL trees (http://en.wikipedia.org/wiki/AVL_tree) in Python. -Class AVL Tree supports the following functionality: - - insertion of a new entry in the tree; - - removal of any entry in the tree; - - search for any entry in the tree; - - "sanity check" for the tree (described later); - - 4 various tree traversals - - preorder, - - inorder, - - postorder, - - inorder non-recursive. - -I would like to mention some sources, that helped me a lot while working on this code: -1) Wikipedia -1a) http://en.wikipedia.org/wiki/AVL_tree - Description of AVL trees. -1b) http://en.wikipedia.org/wiki/Tree_traversal - Description of tree traversals in binary search trees and - sample implementations of traversal algorithms in pseudocode. -2) http://www.cse.ohio-state.edu/~sgomori/570/avlrotations.html - Rotation algorithms for putting an out-of-balance AVL tree back in balance. -3) http://sourceforge.net/projects/standardavl/ - Implementation of AVL trees in C++. I borrowed an idea of "sanity check" - - a method, which traverses the tree and checks that tree is in balance, contains - no circular references, height for each node is calculated correctly and so on. -4) http://oopweb.com/Algorithms/Documents/AvlTrees/Volume/AvlTrees.htm - From this page I borrowed the idea how to correctly delete an entry - from an AVL tree. +Sources: -This code is available under MIT License. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. \ No newline at end of file +http://interactivepython.org/runestone/static/pythonds/Trees/AVLTreeImplementation.html +https://www.cs.usfca.edu/~galles/visualization/AVLtree.html +http://www.cise.ufl.edu/~nemo/cop3530/AVL-Tree-Rotations.pdf +Deletion: +http://www.cs.toronto.edu/~krueger/cscB63h/lectures/tut03.txt \ No newline at end of file diff --git a/avltreeRecursive.py b/avltreeRecursive.py new file mode 100644 index 0000000..eb6978a --- /dev/null +++ b/avltreeRecursive.py @@ -0,0 +1,257 @@ +myavllist = [150,40,900,300,700,60,500,160,450,600,30,80,430] + +class Node(object): + def __init__(self,key,parent=None): + self.key = key + self.parent = parent + self.L_child = None + self.R_child = None + self.L_hight = 0 + self.R_hight = 0 + self.hight = 0 + + def isLeaf(self): + if self.L_child ==None and self.R_child==None: + return True + else: + return False + + def leafDeletion(self): + #just make its parent pointing to none and update its parent hight + par = self.parent + if par.L_child is not None and par.L_child is self: + par.L_child = None + par.L_hight = 0 + else: + par.R_child = None + par.R_hight = 0 + + + def updateHight(self): + if self.L_child is not None: + self.L_hight = self.L_child.hight + 1 + else: + self.L_hight = 0 + if self.R_child is not None: + self.R_hight = self.R_child.hight + 1 + else: + self.R_hight = 0 + self.hight = max(self.L_hight,self.R_hight) + + def isRoot(self): + if self.parent is None: + return True + else: + return False + + def balance(self): + L=0 + R=0 + if self.L_child is not None: + L = self.L_hight + if self.R_child is not None: + R = self.R_hight + return R - L + + + +class AVLtree(object): + def __init__(self,node=None): + self.rootNode = node + + def sameNodes(self,node1,node2): + same = False + if node1 is not None and node2 is not None: + if node1.key == node2.key: + same = True + return same + + def reBalance(self,uNode): + if uNode.balance() > 1: + if uNode.R_child.balance() < 0 : + #double left rotation + self.RRotation(uNode.R_child) + self.LRotation(uNode) + else: + self.LRotation(uNode) + elif uNode.balance() < -1: + if uNode.L_child.balance() > 0 : + #double right rotation + self.LRotation(uNode.L_child) + self.RRotation(uNode) + else: + self.RRotation(uNode) + + + def accessNode(self,key,cur_node=None): + if cur_node is None: + cur_node = self.rootNode + print "key: %d with hight %d" %(cur_node.key,cur_node.hight) + if keycur_node.key: + if cur_node.R_child == None: + print "FAILURE:key not found" + else: + self.accessNode(key,cur_node.R_child) + else: + print "Found Key!!!" + + def attachOnLeft(self,cur_node,key): + cur_node.L_child = Node(key,cur_node) + cur_node.L_hight += 1 + cur_node.hight = max(cur_node.L_hight,cur_node.R_hight) + + def attachOnRight(self,cur_node,key): + cur_node.R_child = Node(key,cur_node) + cur_node.R_hight += 1 + cur_node.hight = max(cur_node.L_hight,cur_node.R_hight) + + def LRotation(self,rotatedNode): + newRoot = rotatedNode.R_child + #correct the relation of the new root with the parent of rotated node + if not rotatedNode.isRoot(): + newRoot.parent = rotatedNode.parent + #if rotatedNode.parent.L_child is rotatedNode: + if self.sameNodes(rotatedNode.parent.L_child,rotatedNode): + rotatedNode.parent.L_child = newRoot + else: + rotatedNode.parent.R_child = newRoot + else: + newRoot.parent = None + self.rootNode = newRoot + #the left child(if exists) of the new root node becomes the right child of the rotated node + rotatedNode.R_child = newRoot.L_child + if newRoot.L_child is not None: + newRoot.L_child.parent = rotatedNode + #the rotated node becomes the left child of the new root node + rotatedNode.parent = newRoot + newRoot.L_child = rotatedNode + #correct each hight of subtree + self.updatehight(rotatedNode) + self.updatehight(newRoot) + + def RRotation(self,rotatedNode): + newRoot = rotatedNode.L_child + #correct the relation of the new root with the parent of rotated node + if not rotatedNode.isRoot(): + newRoot.parent = rotatedNode.parent + if self.sameNodes(rotatedNode.parent.L_child,rotatedNode): + rotatedNode.parent.L_child = newRoot + else: + rotatedNode.parent.R_child = newRoot + else: + newRoot.parent = None + self.rootNode = newRoot + #the left child(if exists) of the new root node becomes the right child of the rotated node + rotatedNode.L_child = newRoot.R_child + if newRoot.R_child is not None: + newRoot.R_child.parent = rotatedNode + #the rotated node becomes the left child of the new root node + rotatedNode.parent = newRoot + newRoot.R_child = rotatedNode + #correct each hight of subtree + self.updatehight(rotatedNode) + self.updatehight(newRoot) + + def updatehight(self,cur_node): + if cur_node.L_child is not None: + cur_node.L_hight = cur_node.L_child.hight + 1 + else: + cur_node.L_hight = 0 + if cur_node.R_child is not None: + cur_node.R_hight = cur_node.R_child.hight + 1 + else: + cur_node.R_hight = 0 + cur_node.hight = max(cur_node.L_hight,cur_node.R_hight) + + def insertNode(self,key,cur_node=None): + if cur_node is None: + cur_node = self.rootNode + if self.rootNode is None: + self.rootNode = Node(key) + return + if key 1 or cur_node.balance() < -1: + self.reBalance(cur_node) + + def swapNodeData(self,node1,node2): + tempKey = node1.key + node1.key = node2.key + node2.key = tempKey + + + def deleteNode(self,s_key,cur_node = None): + if cur_node is None: + cur_node = self.rootNode + if s_key < cur_node.key: + self.deleteNode(s_key,cur_node.L_child) + elif s_key > cur_node.key: + self.deleteNode(s_key,cur_node.R_child) + elif s_key == cur_node.key: + #key to delete found.Start the deletion process + #if node is a leaf just make its parent pointing to none + if cur_node.isLeaf(): + cur_node.leafDeletion() + else: + self.findProcAndDel(cur_node.L_child,cur_node) + else: + print "FAILURE:key not found" + return + cur_node.updateHight() + if cur_node.balance() > 1 or cur_node.balance() < -1: + self.reBalance(cur_node) + + def findProcAndDel(self,cnode,dnode): + if cnode.R_child is not None: + self.findProcAndDel(cnode.R_child,dnode) + else: + if cnode.isLeaf(): + cnode.leafDeletion() + else: + cnode.parent.R_child = cnode.L_child + cnode.L_child.parent = cnode.parent + cnode.parent.R_hight -= 1 + self.swapNodeData(cnode,dnode) + cnode.updateHight() + if cnode.balance() > 1 or cnode.balance() < -1: + self.reBalance(cnode) + + + +myavl = AVLtree() +#myavl.rootNode = Node(150,None) #initialize the root node +for i in myavllist: + myavl.insertNode(i) +myavl.accessNode(600) +myavl.deleteNode(500) +myavl.accessNode(430) + +# myavl2 = AVLtree() +# myavl2.rootNode = Node(3,None) +# myavl2.insertNode(1) +# myavl2.insertNode(2) +# #myavl2.reBalance(myavl2.rootNode) +# myavl2.accessNode(1) +""" +sources +http://interactivepython.org/runestone/static/pythonds/Trees/AVLTreeImplementation.html +https://www.cs.usfca.edu/~galles/visualization/AVLtree.html +http://www.cise.ufl.edu/~nemo/cop3530/AVL-Tree-Rotations.pdf +Deletion: +http://www.cs.toronto.edu/~krueger/cscB63h/lectures/tut03.txt +""" + diff --git a/old.README b/old.README new file mode 100644 index 0000000..8658cde --- /dev/null +++ b/old.README @@ -0,0 +1,50 @@ +Copyright (c) 2010 Pavel Grafov + +Implementation of AVL trees (http://en.wikipedia.org/wiki/AVL_tree) in Python. +Class AVL Tree supports the following functionality: + - insertion of a new entry in the tree; + - removal of any entry in the tree; + - search for any entry in the tree; + - "sanity check" for the tree (described later); + - 4 various tree traversals + - preorder, + - inorder, + - postorder, + - inorder non-recursive. + +I would like to mention some sources, that helped me a lot while working on this code: +1) Wikipedia +1a) http://en.wikipedia.org/wiki/AVL_tree + Description of AVL trees. +1b) http://en.wikipedia.org/wiki/Tree_traversal + Description of tree traversals in binary search trees and + sample implementations of traversal algorithms in pseudocode. +2) http://www.cse.ohio-state.edu/~sgomori/570/avlrotations.html + Rotation algorithms for putting an out-of-balance AVL tree back in balance. +3) http://sourceforge.net/projects/standardavl/ + Implementation of AVL trees in C++. I borrowed an idea of "sanity check" - + a method, which traverses the tree and checks that tree is in balance, contains + no circular references, height for each node is calculated correctly and so on. +4) http://oopweb.com/Algorithms/Documents/AvlTrees/Volume/AvlTrees.htm + From this page I borrowed the idea how to correctly delete an entry + from an AVL tree. + +This code is available under MIT License. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file