Quantcast
Channel: Active questions tagged python - Stack Overflow
Viewing all articles
Browse latest Browse all 23131

AVLtree insert infinite loop

$
0
0

im trying to implement insertion in AVLtree , the insertion works on small number of insertions , but when i try random insert there is a loop in node_position , a small number of insertions with small valued numbers there is no loops or errors , there is a virtual node for every son that is None ( this is instructions from the homework ) , first i find the position to insert then i do insertion and rotations ...
here is my code :import randomclass AVLNode(object):"""Constructor, you are allowed to add more fields.

@type key: int or None@type value: any@param value: data of your node"""def __init__(self, key, value):    self.key = key    self.value = value    self.left = None    self.right = None    self.parent = None    self.height = -1"""returns the left child@rtype: AVLNode@returns: the left child of self, None if there is no left child (if self is virtual)"""def get_left(self):    return self.left if self.is_real_node() else None"""returns the right child@rtype: AVLNode@returns: the right child of self, None if there is no right child (if self is virtual)"""def get_right(self):    return self.right if self.is_real_node() else None"""returns the parent @rtype: AVLNode@returns: the parent of self, None if there is no parent"""def get_parent(self):    return self.parent"""returns the key@rtype: int or None@returns: the key of self, None if the node is virtual"""def get_key(self):    return self.key if self.is_real_node() else None"""returns the value@rtype: any@returns: the value of self, None if the node is virtual"""def get_value(self):    return self.value if self.is_real_node() else None"""returns the height@rtype: int@returns: the height of self, -1 if the node is virtual"""def get_height(self):    return self.height if self.is_real_node() else -1"""sets left child@type node: AVLNode@param node: a node"""def set_left(self, node):    self.left = node    node.parent = self"""sets right child@type node: AVLNode@param node: a node"""def set_right(self, node):    self.right = node    node.parent = self"""sets parent@type node: AVLNode@param node: a node"""def set_parent(self, node):    self.parent = node"""sets key@type key: int or None@param key: key"""def set_key(self, key):    self.key = key"""sets value@type value: any@param value: data"""def set_value(self, value):    self.value = value"""sets the height of the node@type h: int@param h: the height"""def set_height(self, h):    self.height = h"""returns whether self is not a virtual node @rtype: bool@returns: False if self is a virtual node, True otherwise."""def is_real_node(self):    return self.key is not None""" Calculate BlanceFactor and returns it @rtype: int @returns : BalanceFactor """

"""A class implementing the ADT Dictionary, using an AVL tree."""

class AVLTree(object):

"""Constructor, you are allowed to add more fields.  """def __init__(self):    self.root = None    self.size = 0    # add your fields here"""searches for a value in the dictionary corresponding to the key@type key: int@param key: a key to be searched@rtype: any@returns: the value corresponding to key."""def search(self, key):    if self.root is None :        return None    return self.search_helper(self.root, key)def search_helper(self , node ,key):    if not node.is_real_node() :        return None    Node_key = node.get_key()    if Node_key == key:        return node    if key < Node_key:        return self.search_helper(node.get_left(), key)    return self.search_helper(node.get_right(), key)"""inserts val at position i in the dictionary@type key: int@pre: key currently does not appear in the dictionary@param key: key of item that is to be inserted to self@type val: any@param val: the value of the item@rtype: int@returns: the number of rebalancing operation due to AVL rebalancing"""def insert(self, key, val):    node = AVLNode(key, val)    node.set_height(0)    vert1 = AVLNode(None, None)    vert2 = AVLNode(None, None)    if self.root is None:        self.root = node        self.root.set_left(vert1)        self.root.set_right(vert2)        self.size+=1        return 0    self.regular_insert(node)    p = node.get_parent()    son = node    self.size += 1    node.set_left(vert1)    node.set_right(vert2)    return self.Balance(p, son)def node_position(self, node, key):  # look for key "key" in the subtree of node    # return the last node encountered    while node is not None and node.key is not None:        curr = node        if key == node.key:            return node        elif key < node.key:            node = node.left        else:            node = node.right    return currdef regular_insert(self, node):    new_p = self.node_position(self.root, node.key)  # new parent    node.set_parent(new_p)    if node.key < new_p.key:        new_p.set_left(node)    else:        new_p.set_right(node)    returndef BF(self, node):  # returns the balance factor of a node    h1 = node.get_left().get_height() if node.get_left() is not None else -1    h2 = node.get_right().get_height() if node.get_right() is not None else -1    return h1 - h2def height_has_changed(self, node, son):  # checks if node`s height has changed after insertion    return node.get_height() < son.get_height() + 1def rotate(self, node, son):  # performs rotation    n_bf = self.BF(node)    s_bf = self.BF(son)    if n_bf > 0 and s_bf > 0:        self.do_right_rotation(node, son)        return 1    if n_bf < 0 and s_bf < 0:        self.do_left_rotation(node, son)        return 1    if n_bf > 0 and s_bf < 0:        grandson = son.get_right()        self.do_left_rotation(son, grandson)        self.do_right_rotation(node, grandson)        grandson.set_height(grandson.get_height() + 1)        return 2    if n_bf < 0 and s_bf > 0:        grandson = son.get_left()        self.do_right_rotation(son, grandson)        self.do_left_rotation(node, grandson)        grandson.set_height(grandson.get_height() + 1)        return 2    return 0def do_left_rotation(self, node, son):    if self.root == node:        self.root = son    node.set_height(node.get_height() - 2)    grandson = son.get_left()    node.set_right(grandson)    grandson.set_parent(node)    node_p = node.get_parent()    son.set_left(node)    son.set_parent(node_p)    if node_p is not None:        if node_p.get_left() == node:            node_p.set_left(son)        else:            node_p.set_right(son)    node.set_parent(son)    returndef do_right_rotation(self, node, son):    if self.root == node:        self.root = son    node.set_height(node.get_height() - 2)    node_p = node.get_parent()    grandson = son.get_right()    node.set_left(grandson)    grandson.set_parent(node)    son.set_right(node)    son.set_parent(node_p)    if node_p is not None:        if node_p.get_left() == node:            node_p.set_left(son)        else:            node_p.set_right(son)    node.set_parent(son)    returndef Balance(self, p, son):    balance = 0  # to compute the number of balancing operations    while p is not None:        bf = self.BF(p)        h_changed = self.height_has_changed(p, son)        if (abs(bf) < 2) and (h_changed is False):            return balance        if (abs(bf) < 2) and h_changed:            p.set_height(p.get_height() + 1)            balance += 1            son = p            p = p.get_parent()        else:            p.set_height(p.get_height() + 1)            balance += 1            balance += self.rotate(p, son)            return balance    return balance""" Rebalnce@pre : node in self @rtype:int @returns: Number of rebalancing operations including fixing height and rotations"""def Deletion_Rebalance(self, node):    if node is None:        return 0  # this means that we deleted a root, we can't modify its height so we return 0    count = 0    while node is not None:        original_height = node.get_height()        node_parent = node.get_parent()        self.height_Update(node)        right_son_BF = self.BF(node.get_right())        left_son_BF = self.BF(node.get_left())        BF = self.BF(node)        if (abs(BF)) < 2 :            if original_height == node.get_height() :  # case 3.2                break            else :                count+=1        else:            if BF == -2:                if right_son_BF == -1 or right_son_BF == 0:                    self.do_left_rotation(node , node.get_right())                    count += 1                elif right_son_BF == 1:                    self.do_right_rotation(node.get_right() , node.get_right().get_left())                    self.do_left_rotation(node , node.get_right())                    count += 2            elif BF == 2:                left_node = node.get_left()                if left_son_BF == -1:                    self.do_left_rotation(node.get_left(),node.get_left().get_right())                    self.do_right_rotation(node, node.get_left())                    count += 2                elif left_son_BF == 1 or left_son_BF == 0:                    self.do_right_rotation(node , node.get_left())                    count += 1        node = node_parent    return count""" find the successor of node @pre : node in self @rtype: AVL node@returns: the successor of node"""def successor (self,node) :    if node.get_right().is_real_node():        return self.Min(node.get_right())    temp = node.get_parent()    while temp is not None and node == temp.right :        node = temp        temp = node.get_parent()    return temp""" find the min @pre: node is in self@returns : the node with the min key in node path @:rtype AVL node"""def Min(self,node):    temp = node    while temp.get_left().is_real_node() :        temp = temp.get_left()    return temp""" updates node's height @pre: node is in self"""def height_Update(self, node):    left_height = node.get_left().get_height() if node.is_real_node() else -1    right_height = node.get_right().get_height() if node.is_real_node() else -1    node.set_height(max(left_height, right_height) + 1 )"""deletes node from the dictionary@type node: AVLNode@pre: node is a real pointer to a node in self@rtype: int@returns: the number of rebalancing operation due to AVL rebalancing"""def delete(self, node):    return self.delete_node(node)""" deleting node as usual in BST and fixing size @pre : node is in self @rtype : int @returns :  the number of rebalancing operation due to AVL rebalancing"""def delete_node(self,node):    flag= False    node_parent = node.get_parent()    node_right = node.get_right()    node_left = node.get_left()    virtual_Node = AVLNode(None, None)    if not node_right.is_real_node() and not node_left.is_real_node() :        if node_parent is None:            self.root = None        else : # node is not a root            if node_parent.get_left() == node :                node_parent.set_left(virtual_Node)            else :                node_parent.set_right(virtual_Node)    elif not node_right.is_real_node() and node_left.is_real_node() : # case 2 : ond child        if node_parent is None:  # Root node            self.root = node_left        elif node_parent.get_left() == node:            node_parent.set_left(node_left)        else:            node_parent.set_right(node_left)    elif node_right.is_real_node() and not node_left.is_real_node() : # just bypass it , note that we didnt use set functions implemented in AVLnode class because there we add 1 to height        if node_parent is None:  # Root node            self.root = node_right        elif node_parent.left == node:            node_parent.left = node_right            node_parent.right = virtual_Node        else:            node_parent.right = node_right            node_parent.left = virtual_Node    else : # case 2 : two children        flag=True        successor_node = self.successor(node)  # Find the successor node        successor_node_parent = successor_node.get_parent()        node.set_value(successor_node.get_value())        node.set_key((successor_node.get_key()))        if node_parent is None :            self.root=node            self.root.set_left(node.left)            self.root.set_right(node.right)        elif successor_node_parent.left == successor_node :            successor_node_parent.set_left(virtual_Node)        else :            successor_node_parent.set_right(virtual_Node)        return self.delete_node(successor_node)    if not flag : # if flag is false , we didnt delete successor node recursively , thus size updated once not twice        self.size = self.size - 1  # update size    if node_parent is not None and abs(self.BF(node_parent)) ==2 :        return self.Deletion_Rebalance(node_parent)"""returns an array representing dictionary @rtype: list@returns: a sorted list according to key of touples (key, value) representing the data structure"""def avl_to_array(self):    arr = []    def avl_to_array_helper(node,arr):        if not node.is_real_node() :            return        avl_to_array_helper(node.left,arr)        arr.append((node.get_key(),node.get_value()))        avl_to_array_helper(node.right, arr)    avl_to_array_helper(self.root,arr)    return arr"""returns the number of items in dictionary @rtype: int@returns: the number of items in dictionary """def size(self): # Simply return size field    return self.size"""splits the dictionary at the i'th index@type node: AVLNode@pre: node is in self@param node: The intended node in the dictionary according to whom we split@rtype: list@returns: a list [left, right], where left is an AVLTree representing the keys in the dictionary smaller than node.key, right is an AVLTree representing the keys in the dictionary larger than node.key."""def split(self, node):    cost = 0    counter = 0    right_tree = AVLTree()    left_tree = AVLTree()    current = self.search(node.get_key())    left_tree.root=current.get_left() if   current.get_left().is_real_node() else None    right_tree.root=current.get_right() if current.get_right().is_real_node() else None    if current == self.root :        return[left_tree,right_tree]    cost, counter = self.Left_Subtree(current.get_parent(), left_tree, node.get_key(),cost, counter)    cost, counter = self.Right_Subtree(current.get_parent(), right_tree, node.get_key(),cost, counter)    print("cost", cost)    print("counter", counter)    return [left_tree, right_tree]def Left_Subtree(self, n1, left_tree,node_key, cost, counter):    while n1 is not None:        if n1.get_key()< node_key:            _leftSubtree = AVLTree()            if left_tree.root is None :                left_tree.insert(n1.get_key(),n1.get_value())            elif not n1.get_left().is_real_node() :                left_tree.insert(n1.get_key(),n1.get_value())            else:                _leftSubtree.root= n1.get_left()                cost += left_tree.join(_leftSubtree, n1.get_key(), n1.get_value())                counter += 1        n1 = n1.get_parent()        print(cost)    return cost, counterdef Right_Subtree(self, n2, right_tree, node_key, cost, counter):    while n2 is not None:        if n2.get_key() > node_key:            _rightSubtree = AVLTree()            if right_tree.root is None:                right_tree.insert(n2.get_key(), n2.get_value())            elif not n2.get_left().is_real_node() :                right_tree.insert(n2.get_key(), n2.get_value())            else:                _rightSubtree.root = n2.get_left()                cost += right_tree.join(_rightSubtree, n2.get_key(), n2.get_value())                counter += 1        n2 = n2.get_parent()    return cost, counter"""joins self with key and another AVLTree@type tree2: AVLTree @param tree2: a dictionary to be joined with self@type key: int @param key: The key separting self with tree2@type val: any @param val: The value attached to key@pre: all keys in self are smaller than key and all keys in tree2 are larger than key@rtype: int@returns: the absolute value of the difference between the height of the AVL trees joined"""def join(self, tree2, key, val):    print("here?")    x = AVLNode(key, val)    t1_h = self.root.get_height()    t2_h = tree2.root.get_height()    t1_k = self.root.get_key()    t2_k = tree2.root.get_key()    if (t1_h == t2_h) and (t1_k < t2_k):        x.set_left(self.root)        x.set_right(tree2.root)        x.set_height(t1_h + 1)        self.root = x    elif (t1_h == t2_h) and (t1_k > t2_k):        x.set_right(self.root)        x.set_left(tree2.root)        x.set_height(t1_h + 1)        self.root = x    elif (t1_h < t2_h) and (t1_k < t2_k):        t1 = self        t2 = tree2        self.add(t1, t2, x, True)  # the boolean tells if self`s keys are bigger than key    elif (t1_h >= t2_h) and (t1_k > t2_k):        t1 = tree2        t2 = self        self.add(t1, t2, x, True)    elif (t1_h > t2_h) and (t1_k < t2_k):        t1 = tree2        t2 = self        self.add(t1, t2, x, False)    elif (t1_h < t2_h) and (t1_k > t2_k):        t1 = self        t2 = tree2        self.add(t1, t2, x, False)    self.size = self.size + tree2.size + 1    return abs(t1_h - t2_h) + 1def add(self, t1, t2, x, add_to_left):    t1_h = t1.root.get_height()    t2_h = t2.root.get_height()    for h in range(t2_h):        if add_to_left:            needed = t2.root.get_left()  # node with the height of t1 at most        else:            needed = t2.root.get_right()        if needed.get_height() <= t1_h:            c = needed.get_parent()            if add_to_left:                x.set_left(t1.root)                x.set_right(needed)                c.set_left(x)            else:                x.set_right(t1.root)                x.set_left(needed)                c.set_right(x)            x.set_height(t1_h + 1)            self.root = t2.get_root()            if self.height_has_changed(c, x):                self.Balance(c, x)                return"""returns the root of the tree representing the dictionary@rtype: AVLNode@returns: the root, None if the dictionary is empty"""def get_root(self): # return root field , root is updated in the proccess    return self.rootdef main():    a=0    for i in range(1, 11):    used=set()    avl_tree = AVLTree()    n = 1000 * pow(2, i)    for j in range(n) :        num = random.randint(1,n)        if num not in used :            avl_tree.insert(num, str(num))            used.add(num)    print("i is " , i)    avl_tree.split(avl_tree.search(n+5))

Viewing all articles
Browse latest Browse all 23131

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>