简体   繁体   English

我们如何在二叉搜索树上进行操作

[英]How do we operate on Binary Search Trees

--UPDATE TWO-- -更新两次-

balanced BST method fixed and functioning as required. 平衡的BST方法固定并按要求运行。 The problem was that the arraylist wasn't being passed in correctly to create a new "balanced" tree. 问题是未正确传递arraylist来创建新的“平衡”树。 Here's my code for others to benefit. 这是我的代码,可让其他人受益。 Cheers to everyone for their help! 为大家的帮助加油!

public void balanceBST(TreeNode <E> node) {
    if (node == null)
        System.out.println("There is no tree to balance");

    java.util.ArrayList<E> bstToArray = new java.util.ArrayList<E>();

    Iterator<E> treeToArray = iterator();
    while(treeToArray.hasNext()){
        bstToArray.add(treeToArray.next());
    }
    int low = 0;
    int high = bstToArray.size();
    clear();
    balanceHelper(bstToArray, low, high);

}
/** Helper method for the balanceBST method*/
public void balanceHelper(java.util.ArrayList<E> b, int low, int high) {
    if(low == high)
        return;

    int midpoint = (low+high)/2;
    insert(b.get(midpoint));
    balanceHelper(b, midpoint+1, high);
    balanceHelper(b, low, midpoint);
}

--UPDATE ONE-- -更新一个-

I have created a balance BST method, however, I can't debug why a new BST is not being created, especially given I am using the insert method (the idea is to iterate over the tree, populate an array and then create a new BST with the sorted array recursively using the midpoint so that the new tree is sorted). 我已经创建了一个平衡BST方法,但是,我无法调试为什么不创建新的BST,尤其是考虑到我正在使用insert方法时(想法是遍历树,填充数组,然后创建一个新的BST方法)使用中点递归地使用排序数组的BST,以便对新树进行排序)。 I'd appreciate any help debugging this. 感谢您调试此工具的帮助。 Here's my method:- 这是我的方法:

/** Balance BST */
    public void balanceBST(TreeNode <E> node) {
        if (node == null)
            System.out.println("There is no tree to balance");

        java.util.ArrayList<E> bstToArray = new java.util.ArrayList<E>();
        Iterator<E> treeToArray = iterator();
        while(treeToArray.hasNext()){
            bstToArray.add(treeToArray.next());
        }
        //System.out.println(bstToArray);
        int low = 0;
        int high = bstToArray.size();

        balanceHelper(bstToArray, low, high);
        //System.out.println(bstToArray);
    }

    public void balanceHelper(java.util.ArrayList<E> b, int low, int high) {
        if(low == high)
            return;

        int midpoint = (low+high)/2;
        insert(b.get(midpoint));

        balanceHelper(b, midpoint+1, high);
        balanceHelper(b, low, midpoint);
    }

I am a beginner data structures student taking an online course (basically teaching myself) and have a number of questions related to OOP, BST's. 我是一名数据结构初学者,正在参加在线课程(基本上是自学成才),并且遇到了许多与OOP,BST有关的问题。

I have a class BST shown below which is available in the Liang, Introduction to Java, Comprehensive Edition book. 我有下面显示的BST类,可在Liang,Java简介,综合版中获得。 However, I am working to enhance it by adding a number of methods (treeHeight, no of nodes at a given level, balance binary search tree as well as a few more). 但是,我正在通过添加许多方法(treeHeight,给定级别的节点数,平衡二进制搜索树以及更多方法)来增强它。

So I wrote these methods but I am a bit lost with the different objects as well as how to call these methods in my driver/test program. 所以我写了这些方法,但是我对不同的对象以及如何在驱动程序/测试程序中调用这些方法感到有些迷惑。 Here are my questions (and plz excuse me since they might be trivial to some):- 这是我的问题(请打扰一下,因为它们对某些人可能微不足道):-

(1) Why do we pass a node and not a tree to these methods? (1)为什么我们将节点而不是树传递给这些方法?

(2) When I create a tree in my driver program and I try to call the treeHeight method, I get an error message which tells me that am passing the wrong parameter (tree instead of node)....am aware of the error and understand why it's there but am a bit confused here since most examples I've seen online pass a node to the treeHeight method and by inserting elements in the BST, we do have nodes but how to we call such a method then? (2)当我在驱动程序中创建树并尝试调用treeHeight方法时,我收到一条错误消息,告诉我传递了错误的参数(树而不是节点)。并理解为什么它在那里,但是这里有些困惑,因为我在网上看到的大多数示例都将节点传递给treeHeight方法,并通过在BST中插入元素,我们确实有节点,但是我们如何调用这种方法呢? This is a lack of understanding on my behalf on OOP here. 我在这里代表我对OOP缺乏理解。

(3) How do I push the contents of a binary tree into an array (sorted using the inorder method) especially given an iterator inner class as shown below or do I not use that inner class? (3)如何将二叉树的内容推入数组(使用inorder方法排序),特别是在给出如下所示的迭代器内部类的情况下,还是不使用该内部类? I am trying to create a method which balances the tree by pushing out the contents of the tree into an array and then iterating over the array splitting it (recursively) in half and creating a balanced BST. 我正在尝试创建一种通过将树的内容推出到数组中然后在数组上进行迭代以将其分成两部分(递归)并创建平衡的BST来平衡树的方法。 Since the array is sorted and a BST has the left subtree with elements less than the root and the right subtree with elements greater than the root, am able to start at the middle of the array, select root and then recursively work my way through building a Balanced BST. 由于对数组进行了排序,并且BST的左子树的元素小于根,而右子树的元素大于根,因此能够从数组的中间开始,选择根,然后递归地进行构建平衡的BST。

Here's a snippet of my test program code: 这是我的测试程序代码的片段:

BST<Integer> b1 = new BST<Integer>();
b1.insert(1);
b1.insert(2);
b1.insert(3);
b1.insert(4);
// How do I call the treeHeight on BST?
// I tried b1.treeHeight() but....
// and I tried treeHeight(BST) but....
// am a bit lost

And here's the BST class with my methods (please note that some of the methods might not be correct and I am still working on them...am sure once I get the fundamentals out of the way I will have them figured out) : 这是带有我的方法的BST类(请注意,某些方法可能不正确,我仍在研究它们……确保一旦我弄清基础知识后,我就会弄清楚它们):

import java.lang.Math;

public class BST<E extends Comparable<E>> {

    protected TreeNode<E> root;
    protected int size = 0;

    /** Create a default binary tree */
    public BST() {
    }

    /** Create a binary tree from an array of objects */
    public BST(E[] objects) {
        for (int i = 0; i < objects.length; i++)
            insert(objects[i]);
    }

    /** Returns true if the element is in the tree */
    public boolean search(E e) {
        TreeNode<E> current = root; // Start from the root

        while (current != null) {
            if (e.compareTo(current.element) < 0) {
                current = current.left;
            } else if (e.compareTo(current.element) > 0) {
                current = current.right;
            } else
                // element matches current.element
                return true; // Element is found
        }

        return false;
    }

    /**
     * Insert element o into the binary tree Return true if the element is
     * inserted successfully
     */
    public boolean insert(E e) {
        if (root == null)
            root = createNewNode(e); // Create a new root
        else {
            // Locate the parent node
            TreeNode<E> parent = null;
            TreeNode<E> current = root;
            while (current != null)
                if (e.compareTo(current.element) < 0) {
                    parent = current;
                    current = current.left;
                } else if (e.compareTo(current.element) > 0) {
                    parent = current;
                    current = current.right;
                } else
                    return false; // Duplicate node not inserted

            // Create the new node and attach it to the parent node
            if (e.compareTo(parent.element) < 0)
                parent.left = createNewNode(e);
            else
                parent.right = createNewNode(e);
        }

        size++;
        return true; // Element inserted
    }

    protected TreeNode<E> createNewNode(E e) {
        return new TreeNode<E>(e);
    }

    /** Inorder traversal from the root */
    public void inorder() {
        inorder(root);
    }

    /** Inorder traversal from a subtree */
    protected void inorder(TreeNode<E> root) {
        if (root == null)
            return;
        inorder(root.left);
        System.out.print(root.element + " ");
        inorder(root.right);
    }

    /** Postorder traversal from the root */
    public void postorder() {
        postorder(root);
    }

    /** Postorder traversal from a subtree */
    protected void postorder(TreeNode<E> root) {
        if (root == null)
            return;
        postorder(root.left);
        postorder(root.right);
        System.out.print(root.element + " ");
    }

    /** Preorder traversal from the root */
    public void preorder() {
        preorder(root);
    }

    /** Preorder traversal from a subtree */
    protected void preorder(TreeNode<E> root) {
        if (root == null)
            return;
        System.out.print(root.element + " ");
        preorder(root.left);
        preorder(root.right);
    }

    /**
     * This inner class is static, because it does not access any instance
     * members defined in its outer class
     */
    public static class TreeNode<E extends Comparable<E>> {
        protected E element;
        protected TreeNode<E> left;
        protected TreeNode<E> right;

        public TreeNode(E e) {
            element = e;
        }
    }

    /** Get the number of nodes in the tree */
    public int getSize() {
        return size;
    }

    /** Returns the root of the tree */
    public TreeNode<E> getRoot() {
        return root;
    }

    /** Return tree height - my own method */
    public int treeHeight(TreeNode <E> node) {
        // height of empty tree = ZERO
        if (node == null)
            return 0;

        int leftHeight = treeHeight(node.left);
        int rightHeight = treeHeight(node.right);

        if (leftHeight > rightHeight)
            return leftHeight;
        else
            return rightHeight;
    }

    /** Return the no of nodes at given level - my own method */
    public int numberOfNodesAtLevel(TreeNode <E> node, int level) {
        if (root == null)
            return 0;
        if (level == 0)
            return 1;
        return numberOfNodesAtLevel(node.left, level-1) + numberOfNodesAtLevel(node.right, level-1);
    }

    /** Return the no of nodes in binary tree - my own method  */
    public int numberOfNodes(TreeNode <E> node) {
        if (node == null)
            return 0;
        return 1 + numberOfNodes(node.left) + numberOfNodes(node.right);
    }

    /** Calculate ACE - my own method  */
    public double calculateACE(TreeNode <E> node) {
        int n = numberOfNodes(node);
        int treeHeight = treeHeight(node);
        int sum = 0;
        int level = 0;
        for (level=0, sum=0; level < treeHeight; level++ ) {
            sum += numberOfNodesAtLevel(node, level) * (level + 1);
        }
       double ACE = sum / n;
       return ACE;
    }

    /** Calculate MinACE - my own method */
    public double calculateMinACE(TreeNode <E> node) {
        int n = numberOfNodes(node);
        int treeHeight = (int) Math.floor((Math.log(n))+1);
        int sum = 0;
        int level = 0;
        for (level=0, sum=0; level < treeHeight; level++ ) {
            sum += numberOfNodesAtLevel(node, level) * (level + 1);
        }
       double ACE = sum / n;
       return ACE;
    }

    /** Calculate MaxACE - my own method */
    public double calculateMaxACE(TreeNode <E> node) {
        int n = numberOfNodes(node);
        int treeHeight = n;
        int sum = 0;
        int level = 0;
        for (level=0, sum=0; level < treeHeight; level++ ) {
            sum += numberOfNodesAtLevel(node, level) * (level + 1);
        }
       double ACE = sum / n;
       return ACE;
    }

    /** Needs Balancing - my own method */
    public boolean needsBalancing(TreeNode <E> node) {
        double k = 1.25;
        double AceValue = calculateACE(node);
        double MinAceValue = calculateMinACE(node);
        if(AceValue > (MinAceValue*k))
            return true;
        return false;

    }

    /** Balance BST  - my own method, not complete yet */
    public void balanceBST(TreeNode <E> node) {
        int size = numberOfNodes(node);

    }

    /** Returns a path from the root leading to the specified element */
    public java.util.ArrayList<TreeNode<E>> path(E e) {
        java.util.ArrayList<TreeNode<E>> list = new java.util.ArrayList<TreeNode<E>>();
        TreeNode<E> current = root; // Start from the root

        while (current != null) {
            list.add(current); // Add the node to the list
            if (e.compareTo(current.element) < 0) {
                current = current.left;
            } else if (e.compareTo(current.element) > 0) {
                current = current.right;
            } else
                break;
        }

        return list; // Return an array of nodes
    }

    /**
     * Delete an element from the binary tree. Return true if the element is
     * deleted successfully Return false if the element is not in the tree
     */
    public boolean delete(E e) {
        // Locate the node to be deleted and also locate its parent node
        TreeNode<E> parent = null;
        TreeNode<E> current = root;
        while (current != null) {
            if (e.compareTo(current.element) < 0) {
                parent = current;
                current = current.left;
            } else if (e.compareTo(current.element) > 0) {
                parent = current;
                current = current.right;
            } else
                break; // Element is in the tree pointed at by current
        }

        if (current == null)
            return false; // Element is not in the tree

        // Case 1: current has no left children
        if (current.left == null) {
            // Connect the parent with the right child of the current node
            if (parent == null) {
                root = current.right;
            } else {
                if (e.compareTo(parent.element) < 0)
                    parent.left = current.right;
                else
                    parent.right = current.right;
            }
        } else {
            // Case 2: The current node has a left child
            // Locate the rightmost node in the left subtree of
            // the current node and also its parent
            TreeNode<E> parentOfRightMost = current;
            TreeNode<E> rightMost = current.left;

            while (rightMost.right != null) {
                parentOfRightMost = rightMost;
                rightMost = rightMost.right; // Keep going to the right
            }

            // Replace the element in current by the element in rightMost
            current.element = rightMost.element;

            // Eliminate rightmost node
            if (parentOfRightMost.right == rightMost)
                parentOfRightMost.right = rightMost.left;
            else
                // Special case: parentOfRightMost == current
                parentOfRightMost.left = rightMost.left;
        }

        size--;
        return true; // Element inserted
    }

    /** Obtain an iterator. Use inorder. */
    public java.util.Iterator<E> iterator() {
        return new InorderIterator();
    }

    // Inner class InorderIterator
    private class InorderIterator implements java.util.Iterator<E> {
        // Store the elements in a list
        private java.util.ArrayList<E> list = new java.util.ArrayList<E>();
        private int current = 0; // Point to the current element in list

        public InorderIterator() {
            inorder(); // Traverse binary tree and store elements in list
        }

        /** Inorder traversal from the root */
        private void inorder() {
            inorder(root);
        }

        /** Inorder traversal from a subtree */
        private void inorder(TreeNode<E> root) {
            if (root == null)
                return;
            inorder(root.left);
            list.add(root.element);
            inorder(root.right);
        }

        /** More elements for traversing? */
        public boolean hasNext() {
            if (current < list.size())
                return true;

            return false;
        }

        /** Get the current element and move to the next */
        public E next() {
            return list.get(current++);
        }

        /** Remove the current element */
        public void remove() {
            delete(list.get(current)); // Delete the current element
            list.clear(); // Clear the list
            inorder(); // Rebuild the list
        }
    }

    /** Remove all elements from the tree */
    public void clear() {
        root = null;
        size = 0;
    }
}

(1) Why do we pass a node and not a tree to these methods? (1)为什么我们将节点而不是树传递给这些方法?

Answer: 回答:
A BST is defined by its root, you can implement the methods to accept the root or the tree - it's an arbitrary decision. BST由其根定义,您可以实现接受根或树的方法-这是一个任意决定。

(2) ...I've seen online pass a node to the treeHeight method and by inserting elements in the BST, we do have nodes but how to we call such a method then? (2)...我已经看到在线将节点传递给treeHeight方法,并且通过在BST中插入元素,我们确实有节点,但是我们如何调用这种方法呢? This is a lack of understanding on my behalf on OOP here. 我在这里代表我对OOP缺乏理解。

Answer: 回答:
In the example you gave you should call it like this: 在您提供的示例中,您应该这样称呼它:

BST<Integer> b1 = new BST<Integer>();
b1.insert(1);
b1.insert(2);
b1.insert(3);
b1.insert(4);
int h = b1.treeHeight(b1.getRoot()); // get the height

(3) How do I push the contents of a binary tree into an array. (3)如何将二叉树的内容推入数组。

Answer: 回答:
I didn't debug the following code, but I'm sure it'll give you a good idea of how it's done: 我没有调试以下代码,但是我敢肯定,它将为您提供有关如何完成操作的好主意:

int arraySize = b1.getSize();
Integer[] treeToArray = new Integer[arraySize];
iterator iter = b1.iterator();
int i=0;
while(iter.hasNext()) {
    treeToArray[i++] = (Integer)iter.next();
}

(4) why doesn't treeHeight() work (always returns zero) ? (4)为什么treeHeight()不起作用(总是返回零)?

Answer: 回答:
Because it has a bug, here's how to fix it: 因为它存在错误,所以下面是解决方法:

/** Return tree height - my own method */
    public int treeHeight(TreeNode <E> node) {
        // height of empty tree = ZERO
        if (node == null)
            return 0;

        int leftHeight = treeHeight(node.left);
        int rightHeight = treeHeight(node.right);

        if (leftHeight > rightHeight)
            return leftHeight+1; // bug was here: you should return the height of the child + 1 (yourself)
        else
            return rightHeight+1; // and here
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM