質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

2660閲覧

java 逆ポーランド記法への変換のための2分木作成

tamintya

総合スコア34

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/12/16 15:32

編集2021/12/17 01:18

逆ポーランド記法への変換のために2分木を作成したい

中置記法を逆ポーランド記法に変換するために中置記法を2分木に入れ後順で読んでいきたいのですが、
追加された後の根を取得することができないのでその方法を知りたいです。

追記
質問の意図はnullが戻ってきてしまう原因を教えてほしいです。

発生している問題・エラーメッセージ

要素が追加された後の根を取得したい

###実行結果

命令文入力:1 + 2 * 3 text[0] = 1 text[1] = + text[2] = 2 text[3] = * text[4] = 3 text[0+1]= + text[0]= 1 text[2+1]= * text[2]= 2 text[4]= 3 null

該当のソースコード

java

1import java.util.Scanner; 2import java.util.ArrayList; 3import java.util.List; 4import java.util.Stack; 5 6class Data{ 7 String order;//命令文 8 String num;//数値 9} 10 11public class Step3{ 12 public static void main(String[] args){ 13 Data data[] = new Data[256]; 14 15 //標準入力読み込み 16 System.out.print("命令文入力:"); 17 Scanner scan = new Scanner(System.in); 18 String line = scan.nextLine(); 19 String[] textm = line.split(" ");//空白区切り 20 21 //確認 22 for(int i=0;i<textm.length;i++){ 23 System.out.println("text[" + i + "] = " + textm[i]); 24 } 25 26 //中置記法を二分木にする 27 CheakNum cn = new CheakNum();//数字か判定 28 BinaryTree tree = new BinaryTree(); 29 Node node = new Node(null,null,null); 30 for(int i=0;i<textm.length;i++){ 31 32 if(cn.cheaknum(textm[i])){//数字の場合 33 if(i == textm.length-1){//最後の場合 34 tree.maketreeRight(node,textm[i]);//右に追加 35 System.out.println("text[" + i + "]= " + textm[i]); 36 }else{ 37 tree.maketree(node,textm[i+1]);//演算子を追加 38 System.out.println("text[" + i+1 + "]= " + textm[i+1]); 39 tree.maketree(node,textm[i]);//数字を追加 40 System.out.println("text[" + i + "]= " + textm[i]); 41 i++; 42 } 43 } 44 } 45 46 //二分木を後順で読み込む 47 List<String> list = new ArrayList<String>(); 48 list = (Search(node,list)); 49 50 String[] text = new String[256]; 51 for(int i=0;i<list.size();i++){ 52 text[i] = list.get(i); 53 } 54 } 55 56 57 public static List<String> Search(Node root, List<String> list){ 58 if(root != null){ 59 Search(root.left,list); 60 Search(root.right,list); 61 list.add(root.word); 62 //確認 63 System.out.print(" " + root.word); 64 System.out.println(); 65 } 66 return list; 67 } 68 69} 70 71 72public class BinaryTree{ 73 public static Node maketree(Node root, String text){ 74 CheakNum cn = new CheakNum(); 75 if(root == null){//空の場合 76 return new Node(text,null,null); 77 }else if(cn.cheaknum(text)){//数字の場合 78 maketree(root.left, text); 79 }else{ 80 maketree(root.right, text); 81 } 82 return root; 83 } 84 85 public static Node maketreeRight(Node root, String text){ 86 if(root == null){ 87 return new Node(text,null,null); 88 }else{ 89 maketree(root.right, text); 90 } 91 return root; 92 } 93} 94 95 96public class CheakNum{ 97 public static boolean cheaknum(String word){ 98 switch(word){ 99 case "+": 100 case "-": 101 case "*": 102 case "/": 103 return false; 104 105 default: 106 return true; 107 } 108 } 109} 110 111 112//追記 113class Node{ 114 String word; 115 Node right; 116 Node left; 117 118 Node(String word,Node left,Node right){ 119 this.word = word; 120 this.left = left; 121 this.right = right; 122 } 123}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/12/16 16:59

パッと見ですが、 Node クラスがありません。 また、これだけコードを作られた後で「根が…」とはどういう訳でしょう。 処理の開始点である根から処理するようにコードを書くのが本来のはずで、それが分からなくなるコードとは一体どう作られたのでしょうか。
tamintya

2021/12/17 00:25

すみません、Node クラスは載せるのを忘れてしまいました。 「根が…」というのはBinaryTree クラスで値を木に追加しているはずなのにnullが帰ってきてしまう理由を、 return がうまく作動していないのではと考えたので、値が代入され完成した2分木の始まりを取得したいという意味です。
tamintya

2021/12/17 01:20

うまくいかない原因を勝手に決めつけてしまい質問の意図が分かりにくくなってしまっていたので、質問文を追記しました。
jimbe

2021/12/17 08:47 編集

どこで根となる変数に値を設定しているのでしょうか。 Node node = new Node(null,null,null); の node が根のつもりのようですが、 この代入の他に node に値を設定している個所が見当たりません。 > BinaryTree クラスで値を木に追加しているはず どの部分のことでしょう。
tamintya

2021/12/17 14:02

指摘ありがとうございます。確かに上のコードでは木に値を追加できてないですね。 まずそこから直してみます。
guest

回答2

0

ベストアンサー

ざっくりと加減乗除だけ(括弧無し)で、ツリーを作って見ます。

java

1package teratail_java.q374212; 2 3import java.util.Scanner; 4import java.util.regex.Pattern; 5 6class Node{ 7 private static final Pattern NUM_PATTERN = Pattern.compile("[0123456789]+"); 8 9 final String word; 10 final boolean isNumber; 11 Node right; 12 Node left; 13 14 Node(String word) { 15 this(word, null, null); 16 } 17 Node(String word, Node left, Node right) { 18 this.word = word; 19 this.left = left; 20 this.right = right; 21 isNumber = NUM_PATTERN.matcher(word).matches(); 22 } 23 //自分も相手も演算子で、自分のほうが優先順位が高いと true 24 boolean isPrioritize(Node other) { 25 return (word.equals("*") || word.equals("/")) && 26 (other.word.equals("+") || other.word.equals("-")); 27 } 28 void print() { print(""); } 29 void print(String indent) { 30 System.out.println("'"+word+"'"); 31 32 System.out.print(indent+" R:"); 33 if(right == null) System.out.println("null"); 34 else right.print(indent+" "); 35 36 System.out.print(indent+" L:"); 37 if(left == null) System.out.println("null"); 38 else left.print(indent+" "); 39 } 40} 41 42public class Step3{ 43 public static void main(String[] args){ 44 String[] textm = input();//命令文入力 45 46 //中置記法を二分木にする 47 Node root = null; 48 for(int i=0; i<textm.length; i++) { 49 Node node = new Node(textm[i], null, null); 50 if(node.isNumber) { 51 if(root == null) { //(1つ目は数字のはず) 52 root = node; 53 } else { 54 Node t = root; 55 while(t.right != null) t = t.right; 56 t.right = node; 57 } 58 } else if(node.isPrioritize(root)) { 59 node.left = root.right; 60 root.right = node; 61 } else { 62 node.left = root; 63 root = node; 64 } 65 } 66 67 //確認 68 System.out.print("root:"); 69 root.print(); 70 } 71 72 private static String[] input() { 73 System.out.print("命令文入力:"); 74 try(Scanner scan = new Scanner(System.in);) { //標準入力読み込み 75 String line = scan.nextLine(); 76 return line.split(" ");//空白区切り 77 } 78 } 79} 80

実行結果

plain

1命令文入力:1 2root:'1' 3 R:null 4 L:null

plain

1命令文入力:1 + 2 2root:'+' 3 R:'2' 4 R:null 5 L:null 6 L:'1' 7 R:null 8 L:null

plain

1命令文入力:1 + 2 + 3 2root:'+' 3 R:'3' 4 R:null 5 L:null 6 L:'+' 7 R:'2' 8 R:null 9 L:null 10 L:'1' 11 R:null 12 L:null

plain

1命令文入力:1 * 2 + 3 2root:'+' 3 R:'3' 4 R:null 5 L:null 6 L:'*' 7 R:'2' 8 R:null 9 L:null 10 L:'1' 11 R:null 12 L:null

plain

1命令文入力:1 + 2 * 3 2root:'+' 3 R:'*' 4 R:'3' 5 R:null 6 L:null 7 L:'2' 8 R:null 9 L:null 10 L:'1' 11 R:null 12 L:null

plain

1命令文入力:1 * 2 + 3 * 4 2root:'+' 3 R:'*' 4 R:'4' 5 R:null 6 L:null 7 L:'3' 8 R:null 9 L:null 10 L:'*' 11 R:'2' 12 R:null 13 L:null 14 L:'1' 15 R:null 16 L:null

plain

1命令文入力:1 + 2 * 3 / 4 - 5 2root:'-' 3 R:'5' 4 R:null 5 L:null 6 L:'+' 7 R:'/' 8 R:'4' 9 R:null 10 L:null 11 L:'*' 12 R:'3' 13 R:null 14 L:null 15 L:'2' 16 R:null 17 L:null 18 L:'1' 19 R:null 20 L:null

括弧を処理できるようにして BinaryTree を (FormulaBinaryTree) オブジェクトとして復活させると以下の風になりました。

java

1package teratail_java.q374212; 2 3import java.util.*; 4import java.util.regex.Pattern; 5 6class Node { 7 public static enum Priority { 8 LOW, HIGH, NUMBER; 9 boolean over(Priority other) { return ordinal() > other.ordinal(); } 10 } 11 private static final Pattern NUM_PATTERN = Pattern.compile("[0123456789]+"); 12 13 final String word; 14 Node right, left; 15 final boolean isNumber; 16 private Priority priority; 17 18 Node(String word) { 19 this(word, null, null); 20 } 21 Node(String word, Node left, Node right) { 22 this.word = word; 23 this.left = left; 24 this.right = right; 25 isNumber = NUM_PATTERN.matcher(word).matches(); 26 priority = isNumber ? Priority.NUMBER 27 : word.equals("*") || word.equals("/") ? Priority.HIGH 28 : Priority.LOW; 29 } 30 void setPriority(Priority priority) { this.priority = priority; } 31 /** 32 * 自分のほうが優先順位が高いと true 33 */ 34 boolean isPrioritize(Node other) { return priority.over(other.priority); } 35 36 void print() { print(""); } 37 void print(String indent) { 38 System.out.println("'"+word+"'"); 39 printLink(indent, " R:", right); 40 printLink(indent, " L:", left); 41 } 42 private void printLink(String indent, String label, Node link) { 43 System.out.print(indent+label); 44 if(link == null) System.out.println("null"); 45 else link.print(indent+" "); 46 } 47} 48 49class FormulaBinaryTree { 50 private Node root = null; 51 52 FormulaBinaryTree(String[] tokens) { 53 Deque<Node> stack = new LinkedList<>(); //null が入れられる必要がある為 ArrayDeque は不可 54 for(String token : tokens) { 55 if(doBrackets(token, stack)) continue; 56 57 Node node = new Node(token); 58 if(node.isNumber) { 59 root = setNumberNode(root, node); 60 } else if(node.isPrioritize(root)) { //演算子優先順位による入れ替え 61 node.left = root.right; 62 root.right = node; 63 } else { 64 node.left = root; 65 root = node; 66 } 67 } 68 } 69 70 private Node setNumberNode(Node root, Node node) { 71 if(root == null) return node; //(1つ目は数字のはず) 72 //右端へ 73 Node t = root; 74 while(t.right != null) t = t.right; 75 t.right = node; 76 return root; 77 } 78 /** 79 * 括弧処理 80 * こっそり括弧内を別ツリーとして生成を続けさせ、閉じ括弧で元のツリーに合成する 81 */ 82 private boolean doBrackets(String token, Deque<Node> stack) { 83 if(token.equals("(")) { 84 stack.push(root); 85 root = null; 86 return true; 87 } 88 if(token.equals(")")) { 89 root.setPriority(Node.Priority.NUMBER); //括弧部分は数値の優先度 90 root = setNumberNode(stack.pop(), root); 91 return true; 92 } 93 return false; 94 } 95 96 //構造確認用 97 void print() { 98 System.out.print("root:"); 99 root.print(); 100 } 101} 102 103public class Step3 { 104 public static void main(String[] args){ 105 String[] textm = input();//命令文入力 106 107 //中置記法を二分木にする 108 FormulaBinaryTree fbt = new FormulaBinaryTree(textm); 109 110 //確認 111 fbt.print(); 112 } 113 114 private static String[] input() { 115 System.out.print("命令文入力:"); 116 try(Scanner scan = new Scanner(System.in);) { //標準入力読み込み 117 String line = scan.nextLine(); 118 return line.split(" ");//空白区切り 119 } 120 } 121}

plain

1命令文入力:( 1 + ( 2 - 3 * 4 ) ) / 5 2root:'/' 3 R:'5' 4 R:null 5 L:null 6 L:'+' 7 R:'-' 8 R:'*' 9 R:'4' 10 R:null 11 L:null 12 L:'3' 13 R:null 14 L:null 15 L:'2' 16 R:null 17 L:null 18 L:'1' 19 R:null 20 L:null

投稿2021/12/18 09:28

編集2021/12/18 14:16
jimbe

総合スコア13209

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tamintya

2021/12/18 13:50

回答ありがとうございます。 現在コード修正している途中なので参考にさせてもらいます。
guest

0

+, -, *, / に優先順位は無いのでしょうか?
また、( ) も無いのでしょうか?

質問のコードをどう修正すればよいか分からなかったので、
新たに書いてみました。

java

1import java.util.Scanner; 2 3class Node { 4 String word; 5 Node left, right; 6 7 Node(String s, Node l, Node r) { word = s; left = l; right = r; } 8} 9 10class Expr { 11 private String[] text; 12 private int pos; 13 private String token; 14 15 Expr(String s) { text = s.split(" "); } 16 17 Node expr() { 18 Node node = term(); 19 while (token.equals("+") || token.equals("-")) { 20 String s = token; 21 Node right = term(); 22 node = new Node(s, node, right); 23 } 24 return node; 25 } 26 27 Node term() { 28 Node node = factor(); 29 while (token.equals("*") || token.equals("/")) { 30 String s = token; 31 Node right = factor(); 32 node = new Node(s, node, right); 33 } 34 return node; 35 } 36 37 Node factor() { 38 Node node = null; 39 if (get().equals("(")) { 40 node = expr(); 41 token = token.equals(")") ? get() : "x"; 42 } 43 else if (token.isEmpty()) token = "x"; 44 else { node = new Node(token, null, null); get(); } 45 return node; 46 } 47 48 String get() { return token = pos < text.length ? text[pos++] : ""; } 49 50 boolean ok() { return token.isEmpty(); } 51 52 void print(Node node) { 53 if (node == null) return; 54 print(node.left); 55 print(node.right); 56 System.out.print(node.word + " "); 57 } 58} 59 60class Main { 61 public static void main(String[] args){ 62 System.out.print("式入力:"); 63 Scanner scan = new Scanner(System.in); 64 String line = scan.nextLine(); 65 Expr e = new Expr(line); 66 Node root = e.expr(); 67 if (e.ok()) { 68 e.print(root); 69 System.out.println(); 70 } 71 else System.out.println(" Error"); 72 } 73}

投稿2021/12/16 19:51

編集2021/12/16 20:09
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tamintya

2021/12/17 01:05

回答ありがとうございます。 優先順位や括弧については作ったコードもあるのですが、今回のコードのように値がほとんど表示されなかったので原因を調べるために今回のコードを作ったので省いています。 回答してくださったコードについては確認した後にまた返事をします。
tamintya

2021/12/17 14:17

コードを確認したところ ・Node factor の"x"の意味 ・長い式を入力するとErrorになってしまう理由 が分からないです。
kazuma-s

2021/12/17 14:25

"x" は演算子でない文字で、構文解析が終了するようにして、ok() でエラーの発生を検出します。 長い式の具体例を挙げてください。
tamintya

2021/12/18 13:52

説明ありがとうございます。理解することができました。 長い式のErrorはスペースを入れる際に2桁の数字の間にもスペースをいれてしまっていたこちらのミスでした。すみません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問