gpt4 book ai didi

java - 二叉搜索树的字符串表示

转载 作者:搜寻专家 更新时间:2023-11-01 03:09:38 28 4
gpt4 key购买 nike

我一直在尝试为二叉搜索树编写递归字符串方法,该方法返回具有预序路径信息的树的多行表示。

每个节点都应以一系列 < 和 > 字符开头,显示从根节点到该节点的路径。我不确定如何在每次连续调用中使用由一个字符扩展的字符串前缀参数。

该方法应该能够重现这个例子:

树:

     15
/ \
12 18
/ / \
10 16 20
\ \
11 17

预期打印输出:

15
<12
<<10
<<>11
>18
><16
><>17
>>20

我是递归的新手,经过数小时的代码困惑后,到目前为止,我的实际打印输出还不够接近:

18
<17
<10
>15
<11
>12
16
20

这是我的正确工作的树节点类:

/**
* A single binary tree node.
* <p>
* Each node has both a left or right child, which can be null.
*/
public class TreeNode<E> {

private E data;
private TreeNode<E> left;
private TreeNode<E> right;

/**
* Constructs a new node with the given data and references to the
* given left and right nodes.
*/
public TreeNode(E data, TreeNode<E> left, TreeNode<E> right) {
this.data = data;
this.left = left;
this.right = right;
}

/**
* Constructs a new node containing the given data.
* Its left and right references will be set to null.
*/
public TreeNode(E data) {
this(data, null, null);
}

/** Returns the item currently stored in this node. */
public E getData() {
return data;
}

/** Overwrites the item stored in this Node with the given data item. */
public void setData(E data) {
this.data = data;
}

/**
* Returns this Node's left child.
* If there is no left left, returns null.
*/
public TreeNode<E> getLeft() {
return left;
}

/** Causes this Node to point to the given left child Node. */
public void setLeft(TreeNode<E> left) {
this.left = left;
}

/**
* Returns this nodes right child.
* If there is no right child, returns null.
*/
public TreeNode<E> getRight() {
return right;
}

/** Causes this Node to point to the given right child Node. */
public void setRight(TreeNode<E> right) {
this.right = right;
}
}

这是我的二叉搜索树类,底部附近有 toFullString() 方法:

import java.util.*;

/**
* A binary search tree (BST) is a sorted ADT that uses a binary
* tree to keep all elements in sorted order. If the tree is
* balanced, performance is very good: O(n lg n) for most operations.
* If unbalanced, it performs more like a linked list: O(n).
*/
public class BinarySearchTree<E extends Comparable<E>> {

private TreeNode<E> root = null;
private int size = 0;

/** Creates an empty tree. */
public BinarySearchTree() {
}


public BinarySearchTree(Collection<E> col) {
List<E> list = new ArrayList<E>(col);
Collections.shuffle(list);
for (int i = 0; i < list.size() ; i++) {
add(list.get(i));
}
}


/** Adds the given item to this BST. */
public void add(E item) {
this.size++;
if (this.root == null) {
//tree is empty, so just add item
this.root = new TreeNode<E>(item);
}else {
//find where to insert, with pointer to parent node
TreeNode<E> parent = null;
TreeNode<E> curr = this.root;
boolean wentLeft = true;
while (curr != null) { //will execute at least once
parent = curr;
if (item.compareTo(curr.getData()) <= 0) {
curr = curr.getLeft();
wentLeft = true;
}else {
curr = curr.getRight();
wentLeft = false;
}
}

//now add new node on appropriate side of parent
curr = new TreeNode<E>(item);
if (wentLeft) {
parent.setLeft(curr);
}else {
parent.setRight(curr);
}
}
}

/** Returns the greatest (earliest right-most node) of the given tree. */
private E findMax(TreeNode<E> n) {
if (n == null) {
return null;
}else if (n.getRight() == null) {
//can't go right any more, so this is max value
return n.getData();
}else {
return findMax(n.getRight());
}
}

/**
* Returns item from tree that is equivalent (according to compareTo)
* to the given item. If item is not in tree, returns null.
*/
public E get(E item) {
return get(item, this.root);
}

/** Finds it in the subtree rooted at the given node. */
private E get(E item, TreeNode<E> node) {
if (node == null) {
return null;
}else if (item.compareTo(node.getData()) < 0) {
return get(item, node.getLeft());
}else if (item.compareTo(node.getData()) > 0) {
return get(item, node.getRight());
}else {
//found it!
return node.getData();
}
}

/**
* Removes the first equivalent item found in the tree.
* If item does not exist to be removed, throws IllegalArgumentException().
*/
public void remove(E item) {
this.root = remove(item, this.root);
}

private TreeNode<E> remove(E item, TreeNode<E> node) {
if (node == null) {
//didn't find item
throw new IllegalArgumentException(item + " not found in tree.");
}else if (item.compareTo(node.getData()) < 0) {
//go to left, saving resulting changes made to left tree
node.setLeft(remove(item, node.getLeft()));
return node;
}else if (item.compareTo(node.getData()) > 0) {
//go to right, saving any resulting changes
node.setRight(remove(item, node.getRight()));
return node;
}else {
//found node to be removed!
if (node.getLeft() == null && node.getRight() == null) {
//leaf node
return null;
}else if (node.getRight() == null) {
//has only a left child
return node.getLeft();
}else if (node.getLeft() == null) {
//has only a right child
return node.getRight();
}else {
//two children, so replace the contents of this node with max of left tree
E max = findMax(node.getLeft()); //get max value
node.setLeft(remove(max, node.getLeft())); //and remove its node from tree
node.setData(max);
return node;
}
}
}

/** Returns the number of elements currently in this BST. */
public int size() {
return this.size;
}

/**
* Returns a single-line representation of this BST's contents.
* Specifically, this is a comma-separated list of all elements in their
* natural Comparable ordering. The list is surrounded by [] characters.
*/
@Override
public String toString() {
return "[" + toString(this.root) + "]";
}

private String toString(TreeNode<E> n) {
//would have been simpler to use Iterator... but not implemented yet.
if (n == null) {
return "";
}else {
String str = "";
str += toString(n.getLeft());
if (!str.isEmpty()) {
str += ", ";
}
str += n.getData();
if (n.getRight() != null) {
str += ", ";
str += toString(n.getRight());
}
return str;
}
}

public String toFullString() {
StringBuilder sb = new StringBuilder();
toFullString(root, sb);
return sb.toString();
}

/**
* Preorder traversal of the tree that builds a string representation
* in the given StringBuilder.
* @param n root of subtree to be traversed
* @param sb StringBuilder in which to create a string representation
*/
private void toFullString(TreeNode<E> n, StringBuilder sb)
{

if (n == null)
{
return;
}



sb.append(n.getData().toString());
sb.append("\n");


if (n.getLeft() != null) {
sb.append("<");
} else if (n.getRight() != null) {
sb.append(">");
}

if (n.getLeft() != null || n.getRight() != null)
{
toFullString(n.getLeft(), sb);
toFullString(n.getRight(), sb);
}
}


/**
* Tests the BST.
*/
public static void main(String[] args) {
Collection collection = new ArrayList();
collection.add(15);
collection.add(12);
collection.add(18);
collection.add(10);
collection.add(16);
collection.add(20);
collection.add(11);
collection.add(17);
BinarySearchTree bst = new BinarySearchTree(collection);
//System.out.println(bst);
String temp = bst.toFullString();
System.out.println(temp);
}
}

任何有关递归 toFullString 方法的帮助将不胜感激。

最佳答案

在设计递归解决方案时,您需要考虑两个层面。

  1. 如何处理递归中的当前项?
  2. 我如何从这个项目转到下一个项目,传递了哪些信息?

由于我们要打印出树中的每个项目,因此每个递归调用中都会有一个打印语句。但是,每行中打印的字符串包含有关为到达当前节点而遍历的先前步骤的信息。我们如何处理这些信息?它需要从之前的递归调用传递到下一个递归调用。

这是一组可能的规则:

  1. 如果当前项是叶子,则打印出当前结果。
  2. 如果当前项有左节点,添加< , 递归作用于左节点。
  3. 如果当前项目有一个正确的节点,添加> ,并递归地作用于正确的节点。

我们添加什么<>到?从递归调用到调用,我们需要一个参数来携带当前在递归中发生的先前步骤。您不想简单地打印出 <>当你遍历树时,因为你需要记住当前的步骤集来打印出每个节点的前缀。可能有第二个辅助方法采用与原始 toFullString() 相同的参数。 ,而是一个自定义的第三个参数来承载当前的一组先前步骤。

所以逻辑可能看起来像这样:

  • 如果没有当前前缀,将前缀初始化为"" ,因为根最初没有到达它的步骤。
  • 如果当前节点是叶子节点,添加一行当前前缀+叶子节点值的输出。
  • 如果当前节点有左节点,递归调用toFullString()在左侧节点上,添加 <到当前的前缀字符串,这是流传下来的。
  • 如果当前节点有右节点,递归调用toFullString()在右侧节点上,添加 >到当前的前缀字符串,这是流传下来的。

关于java - 二叉搜索树的字符串表示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13435323/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com