插入节点然后重新平衡avl树

时间:2015-07-16 22:44:59

标签: python python-3.x avl-tree

我正在为我的AVL树类创建3个运行插入函数的函数。我的重新平衡采用不平衡的节点,并使用我的左旋转和右旋方法,取决于节点情况。当我使用DATA1 =“ABCDEFGHIJKLMNOPQRSTUVWXYZ”加载avl(avl = AVL())并使用我的级别订单打印方法打印它时,它肯定不会证明它应该如何。你们谁都知道我哪里出错了?

import copy
from list_array_1 import List

    class _AVLNode:

    def __init__(self, value):
        """
        -------------------------------------------------------
        Creates a node containing value.
        Use: node = _AVLNode( value )
        -------------------------------------------------------
        Preconditions:
            value - data for the node (?)
        Postconditions:
            Initializes an AVL node containing value. Child pointers are None,
            height is 1.
        -------------------------------------------------------
        """
        self._value = copy.deepcopy(value)
        # New node is initially added at a leaf.
        self._left = None
        self._right = None
        self._height = 1
        return

    def _update_height(self):
        """
        -------------------------------------------------------
        Updates the height of the current node.
        Use: node._update_height()
        -------------------------------------------------------
        Postconditions:
            returns:
            True if node height has been changed, False otherwise.
            _height is 1 plus the maximum of the node's two children.
        -------------------------------------------------------
        """
        old_height = self._height

        if self._left is None:
            left_height = 0
        else:
            left_height = self._left._height

        if self._right is None:
            right_height = 0
        else:
            right_height = self._right._height

        self._height = max(left_height, right_height) + 1
        return self._height != old_height

    def _balance(self):
        """
        -------------------------------------------------------
        Returns the difference in height between the left and right children
        of the current node.
        Use: balance = node._balance()
        -------------------------------------------------------
        Postconditions:
            returns:
            balance - difference in height between the left and right children
            of the node. A value of -1, 0, or 1 indicates balance. -2 or less
            the node is unbalanced to the right; 2 or more the node is
            unbalanced to the left. (int)
        -------------------------------------------------------
        """
        if self._left is None:
            left_height = 0
        else:
            left_height = self._left._height

        if self._right is None:
            right_height = 0
        else:
            right_height = self._right._height

        balance = left_height - right_height
        return balance

    def __str__(self):
        """
        -------------------------------------------------------
        Returns a string version of the node. For debugging purposes.
        -------------------------------------------------------
        Postconditions:
            prints:
            the contents of the node in the form "h: height, v: value"
        -------------------------------------------------------
        """
        return "h: {}, v: {}".format(self._height, self._value)

class AVL:

    def __init__(self):
        """
        -------------------------------------------------------
        Initializes an empty AVL.
        Use: avl = AVL()
        -------------------------------------------------------
        Postconditions:
            Initializes an empty avl.
        -------------------------------------------------------
        """
        self._root = None
        self._count = 0
        self.comparisons = 0
        return

    def is_empty(self):
        """
        -------------------------------------------------------
        Determines if avl is empty.
        Use: b = avl.is_empty()
        -------------------------------------------------------
        Postconditions:
            returns:
            True if avl is empty, False otherwise (boolean)
        -------------------------------------------------------
        """
        return self._root is None

    def __len__(self):
        """
        -------------------------------------------------------
        Returns the number of elements in the AVL tree.
        Use: n = len( avl )
        -------------------------------------------------------
        Postconditions:
            returns:
            the number of values in the AVL tree (int)
        -------------------------------------------------------
        """
        return self._count

    def insert(self, value):
        """
        -------------------------------------------------------
        Inserts a new node containing value into the avl.
        The avl may contain only one copy of a value.
        Use: b = avl.insert(value)
        -------------------------------------------------------
        Preconditions:
            value - the value to insert into the avl (?)
        Postconditions:
            returns:
            inserted - True if value has been inserted into the tree,
            False otherwise.
        -------------------------------------------------------
        """
        self._root, inserted = self._insert_aux(self._root, value)
        return inserted

    def _insert_aux(self, node, value):
        """
        -------------------------------------------------------
        Inserts a new node containing value into a new leaf of the avl.
        The avl may contain only one copy of a value. The tree may be
        rebalanced after the insertion.
        Private recursive operation called only by insert.
        Use: node, inserted = self._insert_aux(node, value)
        -------------------------------------------------------
        Preconditions:
            node - the current node to examine for the existence of
            value (_AVLNode)
            value - the value to insert into the avl (?)
        Postconditions:
            returns:
            node - the current node (_AVLNode)
            inserted - True if value has been inserted into the tree,
            False otherwise (boolean)
        -------------------------------------------------------
        """
        if node is None:
            # Base case: create the new node and increment the node count.
            node = _AVLNode(value)
            self._count += 1
            inserted = True
        elif value < node._value:
            # General case: attempt to insert the value to the left.
            node._left, inserted = self._insert_aux(node._left, value)
        elif value > node._value:
            # General case: attempt to insert the value to the right.
            node._right, inserted = self._insert_aux(node._right, value)
        else:
            # Base case: value is already in tree.
            inserted = False

        if inserted:
            # Rebalance the current node if necessary.
            node = self._rebalance(node)
        # Return the node.
        return node, inserted

    def retrieve(self, key):
        """
        -------------------------------------------------------
        Retrieves a value matching key in an AVL. (Iterative)
        Use: v = avl.retrieve( key )
        -------------------------------------------------------
        Preconditions:
            key - data to search for (?)
        Postconditions:
            returns:
            value - the full value matching key, otherwise None (?)
        -------------------------------------------------------
        """
        node = self._root
        value = None

        while node is not None and value is None:
            self.comparisons += 1

            if key < node._value:
                node = node._left
            elif key > node._value:
                node = node._right
            else:
                value = copy.deepcopy(node._value)
        return value

    def _rebalance(self, node):
        """
        -------------------------------------------------------
        Rebalances the current node if its children are not balanced.
        Private operation called on insertion and deletion.
        Use: node = self._rebalance(node)
        -------------------------------------------------------
        Preconditions:
            node - the avl node to rebalance (_AVLNode)
        Postconditions:
            node - the avl node that replaces the original node (_AVLNode)
        -------------------------------------------------------
        """
        if node._balance() <= -2 and node._right._balance() <= -1:
            node = node._rotate_left(node)
        elif node._balance() >= 2 and node._left._balance() >= 1:
            node = node.rotate_right(node)
        elif node._balance() <= -2 and node._left._balance() >= 1:
            node._right = node._right._rotate_right(node._right)
            node = node._rotate_left(node)
        elif node._balance() >= 2 and node._right._balance() <= -1:
            node._left = node._left._rotate_left(node._left)
            node = node.rotate_right(node)


        return node

    def _rotate_left(self, node):
        """
        -------------------------------------------------------
        Rotates the pivot to its left around its right child.
        Updates the heights of the rotated nodes.
        Private operation called on rebalancing.
        Use: node = self._rotate_left(node)
        -------------------------------------------------------
        Preconditions:
            node - the pivot node to rotate around (_AVLNode)
        Postconditions:
            node - the node that replaces the pivot node (_AVLNode)
        -------------------------------------------------------
        """
        temp = node._right._left
        new_root = node._right
        new_root._left = node
        node._right = temp
        node._update_height()




        return new_root

    def _rotate_right(self, node):

        """
        -------------------------------------------------------
        Rotates the pivot to its right around its left child.
        Updates the heights of the rotated nodes.
        Private operation called on rebalancing.
        Use: node = self._rotate_right(node)
        -------------------------------------------------------
        Preconditions:
            node - the pivot node to rotate around (_AVLNode)
        Postconditions:
            node - the node that replaces the pivot node (_AVLNode)
        -------------------------------------------------------
        """
        temp = node._left._right
        new_root = node._left
        new_root._right = node
        node._left = temp

        node._update_height()

        return new_root 
    def __contains__(self, key):
        """
        ---------------------------------------------------------
        Determines if the AVL contains key.
        Use: b = key in avl
        -------------------------------------------------------
        Preconditions:
            key - a comparable data element (?)
        Postconditions:
            returns:
            True if the AVL contains key, False otherwise (boolean)
        -------------------------------------------------------
        """
        value = self.retrieve(key)
        return value is not None

    def height(self):
        """
        -------------------------------------------------------
        Returns the height of the AVL.
        Use: h = avl.height()
        -------------------------------------------------------
        Postconditions:
            returns:
            h - the current height of the AVL (int)
        -------------------------------------------------------
        """
        if self._root is None:
            h = 0
        else:
            h = self._root._height
        return h

    def inorder(self):
        """
        -------------------------------------------------------
        Prints the contents of the tree in inorder order.
        Use: avl.inorder()
        -------------------------------------------------------
        Postconditions:
            prints:
            The contents of the tree are printed inorder.
        -------------------------------------------------------
        """
        self._inorder_aux(self._root)
        return

    def _inorder_aux(self, node):
        """
        ---------------------------------------------------------
        Traverses node subtree in inorder.
        Private recursive operation called only by inorder.
        Use: self._inorder_aux(node)
        ---------------------------------------------------------
        Preconditions:
            node - an AVL node (_AVLNode)
        Postconditions:
            prints:
            The children of node are printed inorder.
        ---------------------------------------------------------
        """
        if node is not None:
            self._inorder_aux(node._left)
            print(node._value)
            self._inorder_aux(node._right)
        return

    def postorder(self):
        """
        -------------------------------------------------------
        Prints the contents of the tree in postorder order.
        Use: avl.postorder()
        -------------------------------------------------------
        Postconditions:
            prints:
            The contents of the tree are printed postorder.
        -------------------------------------------------------
        """
        self._postorder_aux(self._root)
        return

    def _postorder_aux(self, node):
        """
        ---------------------------------------------------------
        Traverses node subtree in postorder.
        Private recursive operation called only by postorder.
        Use: self._postorder_aux(node)
        ---------------------------------------------------------
        Preconditions:
            node - an AVL node (_AVLNode)
        Postconditions:
            prints:
            The children of node are printed postorder.
        ---------------------------------------------------------
        """
        if node is not None:
            self._postorder_aux(node._left)
            self._postorder_aux(node._right)
            print(node._value)
        return

    def preorder(self):
        """
        -------------------------------------------------------
        Prints the contents of the tree in preorder order.
        Use: avl.preorder()
        -------------------------------------------------------
        Postconditions:
            prints:
            The contents of the tree are printed preorder.
        -------------------------------------------------------
        """
        self._preorder_aux(self._root)
        return

    def _preorder_aux(self, node):
        """
        ---------------------------------------------------------
        Traverses node subtree in preorder.
        Private recursive operation called only by preorder.
        Use: self._preorder_aux(node)
        ---------------------------------------------------------
        Preconditions:
            node - an AVL node (_AVLNode)
        Postconditions:
            prints:
            The children of node are printed preorder.
        ---------------------------------------------------------
        """
        if node is not None:
            print(node._value)
            self._preorder_aux(node._left)
            self._preorder_aux(node._right)
        return

    def is_valid(self):
        """
        ---------------------------------------------------------
        Determines if an AVL is valid.
        Use: b = avl.is_valid()
        ---------------------------------------------------------
        Postconditions:
            returns:
            valid - True if the tree is an AVL, False otherwise.
        ---------------------------------------------------------
        """
        valid = self._is_valid_aux(self._root)
        return valid

    def _is_valid_aux(self, node):
        """
        ---------------------------------------------------------
        Helper function to determine the AVL validity of node.
        Private operation called only by is_valid.
        Use: b = self._is_valid_aux(node)
        ---------------------------------------------------------
        Preconditions:
            node - the node to check the validity of (_AVLNode)
        Postconditions:
            returns:
            result - True if node is an AVL, False otherwise (boolean)
        ---------------------------------------------------------
        """
        if node is None or (node._left is None and node._right is None):
            # Base case: node is empty or a leaf, so tree must be an AVL.
            result = True
        elif abs(self._node_height(node._left) - \
                 self._node_height(node._right)) > 1:
            # Base case: left or right subtree is too deep.
            print("Height Violation at value: {}".format(node._value))
            result = False
        elif (node._left is not None and node._left._value > node._value) \
            or (node._right is not None and node._right._value < node._value):
            # Base case: does not follow the BST property.
            print("Binary Tree Violation")
            result = False
        else:
            # General case: check the nodes children for validity.
            result = self._is_valid_aux(node._left) and \
                     self._is_valid_aux(node._right)
        return result

    def _node_height(self, node):
        """
        ---------------------------------------------------------
        Helper function to determine the height of node - handles empty node.
        Private operation called only by _is_valid_aux.
        Use: h = self._node_height(node)
        ---------------------------------------------------------
        Preconditions:
            node - the node to get the height of (_AVLNode)
        Postconditions:
            returns:
            height - 0 if node is None, node._height otherwise (int)
        ---------------------------------------------------------
        """
        if node is None:
            height = 0
        else:
            height = node._height
        return height

    def levelorder(self):
        """
        -------------------------------------------------------
        Prints the contents of the tree in levelorder order.
        Use: bst.levelorder()
        -------------------------------------------------------
        Postconditions:
          The contents of the tree are printed levelorder.
        -------------------------------------------------------
        """
        if self._root is not None:
            thislevel = [self._root]
            while thislevel is not None:
                nextlevel = List()
                for n in thislevel:
                    print(n._value)
                    if n._left is not None: 
                        nextlevel.append(n._left)
                    if n._right is not None: 
                        nextlevel.append(n._right)

                thislevel = nextlevel
                print()

                if n._right is None and n._left is None:
                        thislevel = None

0 个答案:

没有答案