From 16cc96a0920cb3714baf9a27bdcf69c1799cf9de Mon Sep 17 00:00:00 2001 From: Awfifcuihc <21129044@zju.edu.cn> Date: Tue, 20 Nov 2018 03:34:44 +0800 Subject: [PATCH 1/6] Create AVLtree.py --- data_structures/binary tree/AVLtree.py | 219 +++++++++++++++++++++++++ 1 file changed, 219 insertions(+) create mode 100644 data_structures/binary tree/AVLtree.py diff --git a/data_structures/binary tree/AVLtree.py b/data_structures/binary tree/AVLtree.py new file mode 100644 index 000000000..43fff9645 --- /dev/null +++ b/data_structures/binary tree/AVLtree.py @@ -0,0 +1,219 @@ +# -*- coding: utf-8 -*- +import math +class my_queue: + def __init__(self): + self.data = [] + self.head = 0 + self.tail = 0 + def isEmpty(self): + return self.head == self.tail + def push(self,data): + self.data.append(data) + self.tail = self.tail + 1 + def pop(self): + ret = self.data[self.head] + self.head = self.head + 1 + return ret + def count(self): + return self.tail - self.head + def print(self): + print(self.data) + print("**************") + print(self.data[self.head:self.tail]) + +class my_node: + def __init__(self,data): + self.data = data + self.left = None + self.right = None + self.height = 1 + def getdata(self): + return self.data + def getleft(self): + return self.left + def getright(self): + return self.right + def getheight(self): + return self.height + def setdata(self,data): + self.data = data + return + def setleft(self,node): + self.left = node + return + def setright(self,node): + self.right = node + return + def setheight(self,height): + self.height = height + return + +def getheight(node): +# print("xxx") + if node is None: + return 0 + return node.getheight() + +def my_max(a,b): + if a > b: + return a + return b + + + +def leftrotation(node): + ret = node.getleft() + node.setleft(ret.getright()) + ret.setright(node) + h1 = my_max(getheight(node.getright()),getheight(node.getleft())) + 1 + node.setheight(h1) + h2 = my_max(getheight(ret.getright()),getheight(ret.getleft())) + 1 + ret.setheight(h2) + return ret + +def rightrotation(node): + ret = node.getright() + node.setright(ret.getleft()) + ret.setleft(node) + h1 = my_max(getheight(node.getright()),getheight(node.getleft())) + 1 + node.setheight(h1) + h2 = my_max(getheight(ret.getright()),getheight(ret.getleft())) + 1 + ret.setheight(h2) + return ret + +def lrrotation(node): + node.setright(leftrotation(node.getright())) + return rightrotation(node) + +def rlrotation(node): + node.setleft(rightrotation(node.getleft())) + return leftrotation(node) + +def insert_node(node,data): + if node is None: + return my_node(data) + if data < node.getdata(): + node.setleft(insert_node(node.getleft(),data)) + if getheight(node.getleft()) - getheight(node.getright()) == 2: + if data < node.getleft().getdata(): + node = leftrotation(node) + else: + node = rlrotation(node) + else: + node.setright(insert_node(node.getright(),data)) + if getheight(node.getright()) - getheight(node.getleft()) == 2: + if data < node.getright().getdata(): + node = lrrotation(node) + else: + node = rightrotation(node) + h1 = my_max(getheight(node.getright()),getheight(node.getleft())) + 1 + node.setheight(h1) + return node + +class AVLtree: + def __init__(self): + self.root = None + def getheight(self): +# print("yyy") + return getheight(self.root) + def insert(self,data): + self.root = insert_node(self.root,data) + def traversale(self): + q = my_queue() + q.push(self.root) + layer = self.getheight() + cnt = 0 + while not q.isEmpty(): + node = q.pop() + space = " "*int(math.pow(2,layer) - 1) + print(space,end = " ") + if node is None: + print("*",end = " ") + else: + print(node.getdata(),end = " ") + q.push(node.getleft()) + q.push(node.getright()) + print(space,end = " ") + cnt = cnt + 1 + for i in range(100): + if cnt == math.pow(2,i) - 1: + layer = layer -1 + print() + break + print() + print("*************************************") + return + + def test(self): + getheight(None) + print("****") + self.getheight() +if __name__ == "__main__": +# t = AVLtree() +# t.test() +# q = my_queue() +## q.push(1) +## q.push(2) +# for i in range(10): +# q.push(i) +# q.print() +# q.push(90) +# q.print() +# +# q.pop() +# q.print() + t = AVLtree() + t.traversale() +# t.insert(7) +# t.traversale() + + t.insert(8) + t.traversale() + t.insert(3) + t.traversale() + t.insert(6) + t.traversale() + t.insert(1) + t.traversale() + t.insert(10) + t.traversale() + t.insert(14) + t.traversale() + t.insert(13) + t.traversale() +# t.traversale() + t.insert(4) + t.traversale() + t.insert(7) + t.traversale() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 6001215b600caabcd4ce567952e2482382f58b90 Mon Sep 17 00:00:00 2001 From: Awfifcuihc <21129044@zju.edu.cn> Date: Tue, 20 Nov 2018 03:41:52 +0800 Subject: [PATCH 2/6] Update AVLtree.py An auto balanced binary tree with no delete node function leave for latter --- data_structures/binary tree/AVLtree.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data_structures/binary tree/AVLtree.py b/data_structures/binary tree/AVLtree.py index 43fff9645..cd867906f 100644 --- a/data_structures/binary tree/AVLtree.py +++ b/data_structures/binary tree/AVLtree.py @@ -1,4 +1,7 @@ # -*- coding: utf-8 -*- +''' +An auto-balanced binary tree! +''' import math class my_queue: def __init__(self): From 9f96c155bea977cc80a7a1110ce1f46760f57904 Mon Sep 17 00:00:00 2001 From: Awfifcuihc <21129044@zju.edu.cn> Date: Wed, 21 Nov 2018 03:25:07 +0800 Subject: [PATCH 3/6] Update AVLtree.py add delete function add demo with shuffled list add print lines to trace the addition or deletion --- data_structures/binary tree/AVLtree.py | 145 +++++++++++++++++++++---- 1 file changed, 121 insertions(+), 24 deletions(-) diff --git a/data_structures/binary tree/AVLtree.py b/data_structures/binary tree/AVLtree.py index cd867906f..c0b37ab08 100644 --- a/data_structures/binary tree/AVLtree.py +++ b/data_structures/binary tree/AVLtree.py @@ -3,6 +3,7 @@ An auto-balanced binary tree! ''' import math +import random class my_queue: def __init__(self): self.data = [] @@ -65,6 +66,7 @@ def my_max(a,b): def leftrotation(node): + print("left rotation node:",node.getdata()) ret = node.getleft() node.setleft(ret.getright()) ret.setright(node) @@ -75,6 +77,7 @@ def leftrotation(node): return ret def rightrotation(node): + print("right rotation node:",node.getdata()) ret = node.getright() node.setright(ret.getleft()) ret.setleft(node) @@ -113,6 +116,52 @@ def insert_node(node,data): node.setheight(h1) return node +def getRightMost(root): + while root.getright() is not None: + root = root.getright() + return root.getdata() +def getLeftMost(root): + while root.getleft() is not None: + root = root.getleft() + return root.getdata() + +def del_node(root,data): + if root.getdata() == data: + if root.getleft() is not None and root.getright() is not None: + temp_data = getLeftMost(root.getright()) + root.setdata(temp_data) + root.setright(del_node(root.getright(),temp_data)) + elif root.getleft() is not None: + root = root.getleft() + else: + root = root.getright() + elif root.getdata() > data: + if root.getleft() is None: + print("No such data") + return root + else: + root.setleft(del_node(root.getleft(),data)) + elif root.getdata() < data: + if root.getright() is None: + return root + else: + root.setright(del_node(root.getright(),data)) + if root is None: + return root + if getheight(root.getright()) - getheight(root.getleft()) == 2: + if getheight(root.getright().getright()) > getheight(root.getright().getleft()): + root = rightrotation(root) + else: + root = lrrotation(root) + elif getheight(root.getright()) - getheight(root.getleft()) == -2: + if getheight(root.getleft().getleft()) > getheight(root.getleft().getright()): + root = leftrotation(root) + else: + root = rlrotation(root) + height = my_max(getheight(root.getright()),getheight(root.getleft())) + 1 + root.setheight(height) + return root + class AVLtree: def __init__(self): self.root = None @@ -120,27 +169,43 @@ class AVLtree: # print("yyy") return getheight(self.root) def insert(self,data): + print("insert:"+str(data)) self.root = insert_node(self.root,data) + + def del_node(self,data): + print("delete:"+str(data)) + if self.root is None: + print("Tree is empty!") + return + self.root = del_node(self.root,data) def traversale(self): q = my_queue() q.push(self.root) layer = self.getheight() + if layer == 0: + return cnt = 0 while not q.isEmpty(): node = q.pop() - space = " "*int(math.pow(2,layer) - 1) - print(space,end = " ") + space = " "*int(math.pow(2,layer-1)) + print(space,end = "") if node is None: - print("*",end = " ") + print("*",end = "") + q.push(None) + q.push(None) else: - print(node.getdata(),end = " ") + print(node.getdata(),end = "") q.push(node.getleft()) q.push(node.getright()) - print(space,end = " ") + print(space,end = "") cnt = cnt + 1 for i in range(100): if cnt == math.pow(2,i) - 1: layer = layer -1 + if layer == 0: + print() + print("*************************************") + return print() break print() @@ -168,27 +233,59 @@ if __name__ == "__main__": t = AVLtree() t.traversale() # t.insert(7) +## t.traversale() +# +# t.insert(8) # t.traversale() +# t.insert(3) +# t.traversale() +# t.insert(6) +# t.traversale() +# t.insert(1) +# t.traversale() +# t.insert(10) +# t.traversale() +# t.insert(14) +# t.traversale() +# t.insert(13) +# t.traversale() +## t.traversale() +# t.insert(4) +# t.traversale() +# t.insert(7) +# t.traversale() +# +# +# t.del_node(8) +# t.traversale() +# t.del_node(3) +# t.traversale() +# t.del_node(6) +# t.traversale() +# t.del_node(1) +# t.traversale() +# t.del_node(10) +# t.traversale() +# t.del_node(14) +# t.traversale() +# t.del_node(13) +# t.traversale() +## t.traversale() +# t.del_node(4) +# t.traversale() +# t.del_node(7) +# t.traversale() + l = list(range(10)) + random.shuffle(l) + for i in l: + t.insert(i) + t.traversale() + + random.shuffle(l) + for i in l: + t.del_node(i) + t.traversale() - t.insert(8) - t.traversale() - t.insert(3) - t.traversale() - t.insert(6) - t.traversale() - t.insert(1) - t.traversale() - t.insert(10) - t.traversale() - t.insert(14) - t.traversale() - t.insert(13) - t.traversale() -# t.traversale() - t.insert(4) - t.traversale() - t.insert(7) - t.traversale() From d1dba51326abc2b1cf8d621b0fd85c84611f4d28 Mon Sep 17 00:00:00 2001 From: Awfifcuihc <21129044@zju.edu.cn> Date: Wed, 21 Nov 2018 12:46:32 +0800 Subject: [PATCH 4/6] remove commented lines --- data_structures/binary tree/AVLtree.py | 56 -------------------------- 1 file changed, 56 deletions(-) diff --git a/data_structures/binary tree/AVLtree.py b/data_structures/binary tree/AVLtree.py index c0b37ab08..467017656 100644 --- a/data_structures/binary tree/AVLtree.py +++ b/data_structures/binary tree/AVLtree.py @@ -217,64 +217,8 @@ class AVLtree: print("****") self.getheight() if __name__ == "__main__": -# t = AVLtree() -# t.test() -# q = my_queue() -## q.push(1) -## q.push(2) -# for i in range(10): -# q.push(i) -# q.print() -# q.push(90) -# q.print() -# -# q.pop() -# q.print() t = AVLtree() t.traversale() -# t.insert(7) -## t.traversale() -# -# t.insert(8) -# t.traversale() -# t.insert(3) -# t.traversale() -# t.insert(6) -# t.traversale() -# t.insert(1) -# t.traversale() -# t.insert(10) -# t.traversale() -# t.insert(14) -# t.traversale() -# t.insert(13) -# t.traversale() -## t.traversale() -# t.insert(4) -# t.traversale() -# t.insert(7) -# t.traversale() -# -# -# t.del_node(8) -# t.traversale() -# t.del_node(3) -# t.traversale() -# t.del_node(6) -# t.traversale() -# t.del_node(1) -# t.traversale() -# t.del_node(10) -# t.traversale() -# t.del_node(14) -# t.traversale() -# t.del_node(13) -# t.traversale() -## t.traversale() -# t.del_node(4) -# t.traversale() -# t.del_node(7) -# t.traversale() l = list(range(10)) random.shuffle(l) for i in l: From 9bbc4d9021c439ad5d3a3f5103073438acf8e0f2 Mon Sep 17 00:00:00 2001 From: Awfifcuihc <21129044@zju.edu.cn> Date: Thu, 22 Nov 2018 14:33:50 +0800 Subject: [PATCH 5/6] Update AVLtree.py add comments --- data_structures/binary tree/AVLtree.py | 40 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/data_structures/binary tree/AVLtree.py b/data_structures/binary tree/AVLtree.py index 467017656..5c72e273f 100644 --- a/data_structures/binary tree/AVLtree.py +++ b/data_structures/binary tree/AVLtree.py @@ -53,7 +53,6 @@ class my_node: return def getheight(node): -# print("xxx") if node is None: return 0 return node.getheight() @@ -66,6 +65,17 @@ def my_max(a,b): def leftrotation(node): + ''' + A B + / \ / \ + B C Bl A + / \ --> / / \ + Bl Br UB Br C + / + UB + + UB = unbalanced node + ''' print("left rotation node:",node.getdata()) ret = node.getleft() node.setleft(ret.getright()) @@ -77,6 +87,9 @@ def leftrotation(node): return ret def rightrotation(node): + ''' + a mirror symmetry rotation of the leftrotation + ''' print("right rotation node:",node.getdata()) ret = node.getright() node.setright(ret.getleft()) @@ -87,24 +100,35 @@ def rightrotation(node): ret.setheight(h2) return ret +def rlrotation(node): + ''' + A A Br + / \ / \ / \ + B C RR Br C LR B A + / \ --> / \ --> / / \ + Bl Br B UB Bl UB C + \ / + UB Bl + RR = rightrotation LR = leftrotation + ''' + node.setleft(rightrotation(node.getleft())) + return leftrotation(node) + def lrrotation(node): node.setright(leftrotation(node.getright())) return rightrotation(node) -def rlrotation(node): - node.setleft(rightrotation(node.getleft())) - return leftrotation(node) def insert_node(node,data): if node is None: return my_node(data) if data < node.getdata(): node.setleft(insert_node(node.getleft(),data)) - if getheight(node.getleft()) - getheight(node.getright()) == 2: - if data < node.getleft().getdata(): + if getheight(node.getleft()) - getheight(node.getright()) == 2: #an unbalance detected + if data < node.getleft().getdata(): #new node is the left child of the left child node = leftrotation(node) else: - node = rlrotation(node) + node = rlrotation(node) #new node is the right child of the left child else: node.setright(insert_node(node.getright(),data)) if getheight(node.getright()) - getheight(node.getleft()) == 2: @@ -178,7 +202,7 @@ class AVLtree: print("Tree is empty!") return self.root = del_node(self.root,data) - def traversale(self): + def traversale(self): #a level traversale, gives a more intuitive look on the tree q = my_queue() q.push(self.root) layer = self.getheight() From 72c217c37eb2ad694eeb9cb360d1cd65b2d52e8d Mon Sep 17 00:00:00 2001 From: Harshil Date: Fri, 23 Nov 2018 18:23:06 +0100 Subject: [PATCH 6/6] Update AVLtree.py Removed blank lines (256 to 287)! --- data_structures/binary tree/AVLtree.py | 32 -------------------------- 1 file changed, 32 deletions(-) diff --git a/data_structures/binary tree/AVLtree.py b/data_structures/binary tree/AVLtree.py index 5c72e273f..cb27004b6 100644 --- a/data_structures/binary tree/AVLtree.py +++ b/data_structures/binary tree/AVLtree.py @@ -253,35 +253,3 @@ if __name__ == "__main__": for i in l: t.del_node(i) t.traversale() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -