Java 从字符串输入构建树
当提供字符串输入时,如何生成树,我被困在逻辑上。例如,当我输入以下表单时- (1(2(3)(4))(5(6)() 表示树将是这样的-Java 从字符串输入构建树,java,tree,binary-tree,user-input,traversal,Java,Tree,Binary Tree,User Input,Traversal,当提供字符串输入时,如何生成树,我被困在逻辑上。例如,当我输入以下表单时- (1(2(3)(4))(5(6)() 表示树将是这样的- 1 / \ 2 5 / \ /\ 3 4 6 () 我可以从普通的树中创建树。添加(数据),然后通过判断新节点是否大于或小于父节点来寻找要自我添加的新节点。但是我不知道如何实现以二进制数据结构形式存储上述字符串 以下是我到目前为止所做的尝试- public
1
/ \
2 5
/ \ /\
3 4 6 ()
我可以从普通的树中创建树。添加(数据),然后通过判断新节点是否大于或小于父节点来寻找要自我添加的新节点。但是我不知道如何实现以二进制数据结构形式存储上述字符串
以下是我到目前为止所做的尝试-
public class BinaryTree {
static Node root;
public static void levelorder(Node<?> n) {
Queue<Node<?>> nodequeue = new LinkedList<Node<?>>();
if (n != null)
nodequeue.add(n);
while (!nodequeue.isEmpty()) {
Node<?> next = nodequeue.remove();
System.out.print(next.data + " ");
if (next.getLeft() != null) {
nodequeue.add(next.getLeft());
}
if (next.getRight() != null) {
nodequeue.add(next.getRight());
}
}
}
private static String[] breakString(String elements) {
int indexOfOpenBracket = elements.indexOf("(");
int indexOfLastBracket = elements.lastIndexOf(")");
String removedPString = elements.substring(indexOfOpenBracket + 1,
indexOfLastBracket);
String[] breakRemovedPString = removedPString.split(" ");
if (breakRemovedPString[1].contains("(")) {
add(breakRemovedPString[0], breakRemovedPString[1], breakRemovedPString[2]);
}
return breakRemovedPString;
}
static void add(String parent, String leftString, String rightString) {
Node<String> nodeToAdd = new Node<String>(parent);
if (root == null) {
root = nodeToAdd;
root.left = new Node<String>(leftString);
root.right = new Node<String>(rightString);
} else {
}
}
public static void main(final String[] args) {
String treeString = "(1 (2) (3))";
breakString(treeString);
levelorder(root);
System.out.println();
}
}
公共类二进制树{
静态节点根;
公共静态void levelorder(节点n){
队列>();
如果(n!=null)
nodequeue.add(n);
而(!nodequeue.isEmpty()){
Node next=nodequeue.remove();
System.out.print(next.data+“”);
if(next.getLeft()!=null){
nodequeue.add(next.getLeft());
}
if(next.getRight()!=null){
nodequeue.add(next.getRight());
}
}
}
私有静态字符串[]breakString(字符串元素){
int indexOfOpenBracket=elements.indexOf(“”);
int indexOfLastBracket=elements.lastIndexOf(“)”;
String removedPString=elements.substring(indexOfOpenBracket+1,
IndexOflast(括号);
字符串[]breakRemovedPString=removedPString.split(“”);
if(breakRemovedPString[1]。包含(“”){
添加(breakRemovedPString[0],breakRemovedPString[1],breakRemovedPString[2]);
}
回程断路器;
}
静态无效添加(字符串父项、字符串左字符串、字符串右字符串){
Node nodeToAdd=新节点(父节点);
if(root==null){
root=nodeToAdd;
root.left=新节点(leftString);
root.right=新节点(rightString);
}否则{
}
}
公共静态void main(最终字符串[]args){
字符串treeString=“(1(2)(3))”;
断开字符串(treeString);
levelorder(根);
System.out.println();
}
}
请对此问题提出一些实现建议。这是一个经典的解析问题。最简单的方法可能是递归下降法。下面是树语言的语法:
T -> ( number T T )
| ( number )
| ()
要将其转换为解析器,我们可以对LL(1)形式进行形式转换,然后编写代码。我将让您详细阅读并展示结果
package treereader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Reader;
enum Token { LPAREN, RPAREN, NUMBER, EOF, ERROR };
class Scanner {
final Reader in;
final char [] buf = new char[1];
final StringBuilder token = new StringBuilder();
private static final char EOF_MARK = Character.MIN_VALUE;
Scanner(Reader in) {
this.in = in;
read();
}
final void read() {
try {
if (in.read(buf) < 1) {
buf[0] = EOF_MARK;
}
} catch (IOException ex) {
System.err.println("i/o error");
buf[0] = EOF_MARK;
}
}
Token getNext() {
while (Character.isWhitespace(buf[0])) {
read();
}
if (Character.isDigit(buf[0])) {
token.setLength(0);
do {
token.append(buf[0]);
read();
} while (Character.isDigit(buf[0]));
return Token.NUMBER;
}
if (buf[0] == '(') {
read();
return Token.LPAREN;
}
if (buf[0] == ')') {
read();
return Token.RPAREN;
}
if (buf[0] == EOF_MARK) {
return Token.EOF;
}
return Token.ERROR;
}
String getString() {
return token.toString();
}
}
class Node {
public void print(PrintStream out) {
out.print("()");
}
}
class UnaryNode extends Node {
int val;
public UnaryNode(int val) {
this.val = val;
}
@Override
public void print(PrintStream out) {
out.print("(" + val + ")");
}
}
class BinaryNode extends Node {
int val;
Node left, right;
public BinaryNode(int val, Node left, Node right) {
this.val = val;
this.left = left;
this.right = right;
}
@Override
public void print(PrintStream out) {
out.print("(" + val + " ");
left.print(out);
out.print(' ');
right.print(out);
out.print(')');
}
}
class Parser {
final Scanner scanner;
Token lookAhead;
Parser(Reader in) {
scanner = new Scanner(in);
lookAhead = scanner.getNext();
}
void advance() {
lookAhead = scanner.getNext();
}
void match(Token token) throws IOException {
if (lookAhead == token) {
advance();
} else {
throw new IOException("Expected " + token + ", found " + lookAhead);
}
}
Node parse() throws IOException {
Node tree;
match(Token.LPAREN);
if (lookAhead == Token.NUMBER) {
int val = Integer.valueOf(scanner.getString());
advance();
if (lookAhead == Token.LPAREN) {
Node left = parse();
Node right = parse();
tree = new BinaryNode(val, left, right);
} else {
tree = new UnaryNode(val);
}
} else {
tree = new Node();
}
match(Token.RPAREN);
return tree;
}
}
public class TreeReader {
public static void main(String[] args) {
try {
Parser parser = new Parser(new BufferedReader(new FileReader(new File(args[0]))));
Node tree = parser.parse();
tree.print(System.out);
} catch (IOException ex) {
System.err.println(ex.getMessage());
}
}
}
包装树阅读器;
导入java.io.BufferedReader;
导入java.io.File;
导入java.io.FileReader;
导入java.io.IOException;
导入java.io.PrintStream;
导入java.io.Reader;
枚举标记{LPAREN,RPAREN,NUMBER,EOF,ERROR};
类扫描器{
最终读者;
最终字符[]buf=新字符[1];
最终StringBuilder标记=新StringBuilder();
私有静态最终字符EOF_标记=Character.MIN_值;
扫描仪(读卡器输入){
this.in=in;
read();
}
最终无效读取(){
试一试{
if(in.read(buf)<1){
buf[0]=EOF_标记;
}
}捕获(IOEX异常){
系统错误println(“i/o错误”);
buf[0]=EOF_标记;
}
}
令牌getNext(){
while(Character.isWhitespace(buf[0])){
read();
}
if(Character.isDigit(buf[0])){
token.setLength(0);
做{
token.append(buf[0]);
read();
}while(Character.isDigit(buf[0]);
返回Token.NUMBER;
}
如果(buf[0]=='('){
read();
返回Token.LPAREN;
}
如果(buf[0]==')'){
read();
return Token.RPAREN;
}
如果(buf[0]==EOF_标记){
返回Token.EOF;
}
返回Token.ERROR;
}
字符串getString(){
返回token.toString();
}
}
类节点{
公共作废打印(打印流输出){
输出。打印(“()”);
}
}
类UnaryNode扩展了Node{
int-val;
公共一元节点(int-val){
this.val=val;
}
@凌驾
公共作废打印(打印流输出){
打印输出(“+val+”);
}
}
类BinaryNode扩展节点{
int-val;
左、右淋巴结;
公共二进制节点(int-val、左节点、右节点){
this.val=val;
this.left=左;
这个。右=右;
}
@凌驾
公共作废打印(打印流输出){
打印(“(“+val+”);
左。打印(输出);
输出。打印(“”);
对,打印(输出);;
输出打印(');
}
}
类解析器{
最终扫描仪;
象征性前瞻;
解析器(读取器中){
扫描仪=新扫描仪(英寸);
lookAhead=scanner.getNext();
}
作废预付款(){
lookAhead=scanner.getNext();
}
无效匹配(令牌)引发IOException{
如果(前瞻==令牌){
前进();
}否则{
抛出新IOException(“预期“+令牌+”,发现“+前瞻性”);
}
}
Node parse()引发IOException{
节点树;
匹配(Token.LPAREN);
if(前瞻==令牌号){
int val=Integer.valueOf(scanner.getString());
前进();
if(lookAhead==Token.LPAREN){
Node left=parse();
Node right=parse();
树=新的二进制节点(val、左、右);
}否则{
树=新的一元节点(val);
}
}否则{
树=新节点();
}
匹配(Token.RPAREN);
回归树;
}
}
公共类树阅读器{
公共静态void main(字符串[]args){
试一试{
Parser Parser=newparser(newbufferedreader(newfilereader)(新文件(args[0]));
节点树=parser.parse();
树。打印(系统输出);
}捕获(IOEX异常){
System.err.println(例如getMessage());
}
}
}
您必须使用附加的数据结构来解析和评估字符串,就像堆栈一样。使用队列d