【问题标题】:Trying to Convert Binary Search Tree to Array (returns Null)尝试将二叉搜索树转换为数组(返回 Null)
【发布时间】:2020-05-12 13:04:19
【问题描述】:

我想将我的二叉搜索树转换为数组(按顺序遍历)。

要做到这一点,我有 3 种方法。

问题:方法 1 System.out.print() 调用中的 java.lang.NullPointerException。但是成功返回 4 个元素(2 个为 null,因此出现此错误,但为什么?!)

类(1个主)方法1(调用方法)

 public void top() {
    array[] unsortedList = this.bookList.returnBSTAsArray(6); // 6 is the number of nodes in tree
     for (Book book: unsortedList) {
         System.out.println("--> Title: " + book.title());
     }

类(2)方法2

// traverse BST in order and return an array of books 
public Book[] returnBSTAsArray(int totalLength) {
    Book[] list = new Book[totalLength];
    int index = 0;

    storeInOrder(this.root, list, index);  // root is node accessible to this class

    return list;
}

类 (2) 方法 3 - 有趣的按顺序遍历的方法

 private Book[] storeInOrder(Node root, Book[] array, int index) {
        if (root == null)
            return null;
        storeInOrder(root.leftChild, array, index);
        array[index++] = root.movie;
        storeInOrder(root.rightChild, array, index);

        return array;
    }

【问题讨论】:

  • 能把BST的代码放上来
  • 另外,您要按插入顺序检索到 BST 吗?

标签: java arrays binary-search-tree binary-search inorder


【解决方案1】:

Java 是一种“按值传递”的语言。因此(一般而言),调用者不会看到函数中参数值的任何更改。

storeInOrder 函数是问题所在。它被写成好像对index arg 的更改将对调用者可见。

这个假设是不正确的。

而且,它返回的是数组,但由于数组确实是一个引用,它在方法中没有改变(但它是CONTENT),因此不需要返回数组作为结果。

因此,更好的配置文件是storeInOrder 获取并返回数组中第一个可用单元格的索引。

/**
 * insert the elements of the bst (denoted by root) into array,
 * starting at index (the first available position in array) and
 * returns the first available position after insertion)
 * pre-conditions : 
 *    - root is a bst containing n elements
 *    - array contains enough available cells
 *    - index = i0
 * post-conditions
 *    - tree is unchanged
 *    - array[i0..i0+n-1] contains elements of the bst
 *    - functions returns i0+n
 */
private int storeInOrder(Node root, Book[] array, int index) {
    if (root == null)
        return index;
    // then call on left, add root, call on right...
    int i = storeInOrder(root.leftChild, array, index);
    array[i] = root.movie;
    return storeInOrder(root.rightChild, array, i+1);
}

注意:如果您希望数组按 Book 的顺序排列,只需更改递归调用的顺序即可获得前缀左右遍历。

【讨论】:

  • 如果您不介意详细说明“获取并返回数组中第一个可用单元格的索引”。和“然后在左边调用,添加根,在右边调用..” - 我需要访问节点,如果我返回索引它对我有用吗?也许我错过了什么?
  • 如果规范不明确,就无法编写正确的递归函数。尝试说明您的解决方案的规格,您会立即发现它不起作用。我会将规范添加到我的版本中,您将能够在其实现中使用它。
  • 有了这个明确的规范,你会看到对于一个非空树,你将在左边的位置 index..index+nl-1 插入元素,在 index+nl 的根右边的元素位于 index+nl+1..index+nl+nr+1 (其中 nl 是左侧元素的数量,nr 是右侧元素的数量)。第一次调用将返回 (index+nl)。同样,如果您将 index+nl+1 传递给第二次调用,它将返回 index+nl+nr+1。
  • 我不得不说还在学习,但我从未见过返回方法调用:return storeInOrder(root.rightChild, array, i+1);不认为递归需要返回任何东西(它在调用堆栈中?)更不用说方法调用了?谢谢
  • return 是必要的,因为规范要求方法返回插入的结束索引
【解决方案2】:

您可以通过持续跟踪每个元素的索引来将其添加回结果数组中来完成

  static class BST {

        private class Node {
            private Integer key;
            private Node left, right;
            private int index;

            public Node(Integer key, int index) {
                this.key = key;
                this.index = index;
            }
        }

        private Node root;
        private int size = 0;

        public void put(int[] arr) {
            if (size >= arr.length)
                return;
            root = put(root, arr[size], size);
            size++;
            put(arr);
        }

        private Node put(Node node, int key, int index) {
            if (node == null)
                return new Node(key, index);
            int cmp = Integer.valueOf(key).compareTo(node.key);
            if (cmp < 0)
                node.left = put(node.left, key, index);
            else if (cmp > 0)
                node.right = put(node.right, key, index);
            else
                node.key = key;
            return node;
        }

        public int size() {
            return size;
        }

        public int[] keys() {
            int[] result = new int[size];
            get(root, result, 0);
            return result;
        }

        public void get(Node node, int[] result, int i) {
            if (i >= result.length || node == null)
                return;
            result[node.index] = node.key;
            get(node.left, result, ++i);
            get(node.right, result, ++i);
        }
    }

,主要

    public static void main(String[] args) {
        BST bst = new BST();
        bst.put(new int[] { 10, 20, 5, 40, 1, 60, -10, 0 });

        for (int num : bst.keys()) {
            System.out.print(num + " ");
        }
    }

,输出

10 20 5 40 1 60

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-01
    • 2020-12-28
    • 2018-11-05
    • 2017-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多