scanfで <<-,1,->,2,<-,3,->> と入力して、それを二分木にする関数を作っているんですが、scanfで読み込むために宣言したcharの配列buffを解析する関数がわからないので教えてほしいです。
※ <,,~>が一つの節点を表していて、- は子の節点がないことを意味します。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
回答3件
0
正規表現でやってみた(Cだとちょっと面倒かしら...)
C++
1#include <iostream> 2#include <string> 3#include <regex> 4 5using namespace std; 6 7struct node { 8 node* left; 9 string value; 10 node* right; 11}; 12 13node* parse(const string& str) { 14 node* result = new node(); 15 regex re(R"_(<(<.*>|-),([^<>,]+),(<.*>|-)>)_"); 16 smatch match; 17 if ( regex_match(str, match, re) ) { 18 result->left = match.str(1) == "-" ? nullptr : parse(match.str(1)); 19 result->value = match.str(2); 20 result->right = match.str(3) == "-" ? nullptr : parse(match.str(3)); 21 } else { 22 result->left = nullptr; 23 result->value = str; 24 result->right = nullptr; 25 } 26 return result; 27} 28 29void print(node* p) { 30 if ( p ) { 31 cout << (p->left ? " left ":"(null)"); 32 cout << " [" << p->value << "] "; 33 cout << (p->left ? "right ":"(null)"); 34 cout << endl; 35 } else { 36 cout << "(null)\n"; 37 } 38} 39 40int main() try { 41 node* root = parse("<<-,1,->,2,<-,3,->>"); 42 print(root); 43 print(root->left); 44 print(root->right); 45} catch ( const regex_error& err ) { 46 cout << err.code() << ':' << err.what() << endl; 47}
投稿2016/06/24 05:26
総合スコア16612
0
構文解析というのは、それ自体がかなり手間のかかる作業です。
とはいえ、この規模の問題だとそこまで規模も大きくならないので、再帰的下向き構文解析のようなものを手で書いても、じゅうぶん書ける範囲です。
スクリプト言語を作る場合など、構文自体が巨大なものになる場合は、構文解析器を作るツールを活用するのがいいでしょう。C/C++の場合はyacc/bisonあたりが定番ですし、C#用のものも存在します。
投稿2016/06/24 02:56
総合スコア146979
0
正規表現使ったらいいんじゃないですか?
投稿2016/06/24 02:42
総合スコア28675
正規表現を再帰的に適用せんならんだろけど...うまくいくかしら...
カンマでスプリットしてリストに突っ込んで再帰でもループでも。
構文解析はそれが一番楽です。
木を作るのには普通はノードとなるオブジェクトや構造体を作ってそれを繋いでいくんですが、この事例のように二分木で大きさが分かっている場合にはもっと簡単な方法が使えます。
まずはノードの数(カンマの数からわかるはずです)を数えて十分な大きさの配列を用意し、そこに埋めていくだけです。
配列の要素 0 はルートを表し、1 と2 は 0 の子、3 と 4 は1 の子、5 と 6 は 2 の子という風に、添え字をと節の位置が 1 対 1 対応しますので、位置を簡単に計算でき、極めて高速に処理できます。
これを使うと、ノードの親子関係をたどらなくても処理中のノードをどこに保存すればいいかわかるので、再帰を使わず簡単なループで処理できます。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。

2016/06/24 06:36
2016/06/24 07:50