ナカナカピエロ おきらくごくらく

写真付きで日記や趣味を書くならgooブログ

二分探索木(Javaサンプルプログラム)・続き

2021-08-22 19:23:42 | 
二分探索木(Javaサンプルプログラム)・続き


●ExecuteBinTree.java

package treeInt;

public class ExecuteBinTree {
	public static void main(String[] args) {
		BinTree tree = new BinTree();
		int size = 10;
		while(tree.count < size){
			tree.insert(new java.util.Random().nextInt(size+1));
		}

		System.out.println(tree);

		System.out.println("前順 (preorder) : ");
		tree.preorder();

		System.out.println("間順 (inorder) : ");
		tree.inorder();

		System.out.println("後順 (postorder) : ");
		tree.postorder();
		
		for(int i=0;i<=size+1;i++) {
			tree.search(i);
		}
		
		System.out.println(tree);
		
		System.out.print("削除したい数値を入れてください:");
		int dch=new java.util.Scanner(System.in).nextInt();
		tree.delete(dch);
		System.out.println(tree);
	}
}


コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

二分探索木(Javaサンプルプログラム)

2021-08-22 19:18:59 | 日記
二分探索木(Javaサンプルプログラム)

以下の記事を参考にして、二分探索木のJavaプログラムを作成してみました。

【1日1Java】ジェネリックスを使って二分探索木を実装
二分木図を印刷する方法は?

削除メソッドについては以下の記事を参考にしました。

二分探索木削除操作

備考:
・NodeはジェネリックにせずIntegerにして一切のジェネリックは排除。
・なるべくコードを見やすいようにクリーニングしました。
・削除メソッドは上記一番目のコードを無理やり3番目の記事のコードに置き換えているため
 整合性に欠けます。
・中身のアルゴリズムに関しては上記記事を参考にしてください。

●BinTreeNode.java

package treeInt;

// ツリーノードの実装
public class BinTreeNode {
	Integer element;      // 数値をノードの要素に持つ。   
	BinTreeNode left;     // 左ノード
	BinTreeNode right;    // 右ノード

	public BinTreeNode() {
	}

	public BinTreeNode(Integer e) {
		this.element=e;
	}

	// ツリーを辿って階層構造をCUIイメージで表示するためのメソッド
	// 再帰を使って表示している。
	public StringBuilder toString(StringBuilder prefix, boolean isTail, StringBuilder sb) {
		if (right != null) {
			right.toString(
			new StringBuilder().append(prefix)
				.append(isTail ? "|   " : "    "), false, sb);
		}
		sb.append(prefix)
			.append(isTail ? "+-- " : "+-- ").append(element).append("\n");
		if (left != null) {
			left.toString(
			new StringBuilder().append(prefix)
				.append(isTail ? "    " : "|   "), true, sb);
		}
		return sb;
	}

	@Override
	public String toString() {
		return this.toString(new StringBuilder(), true, new StringBuilder()).toString();
	}

}



●BinTree.java

package treeInt;

public class BinTree {
	BinTreeNode root;
	int count; // 登録数をカウント

	public void search(Integer e) {
		if (root == null) {
			return;
		} else {
			BinTreeNode parent = null;
			BinTreeNode current = root;
			search(e, parent, current);
		}
	}

	public void search(Integer e, BinTreeNode parent, BinTreeNode current) {
		if (e == current.element) {
			System.out.println(e + " ⇒ Search success");
			return;
		} else if (e <= current.element && current.left != null) {
			search(e, current, current.left);
		} else if (e > current.element && current.right != null) {
			search(e, current, current.right);
		}
	}

	public void insert(Integer e) {
		// rootが初期状態であれば最初に初期化して数値をノードに登録する
		if (root == null) {
			root = new BinTreeNode(e);
			count = 0;
		} else {
			// 親のノードをnull,現在のノードをルートに設定してサブメソッドを呼び出す
			BinTreeNode parent = null;
			BinTreeNode current = root;
			insert(e, parent, current);
		}
	}

	public void insert(Integer e, BinTreeNode parent, BinTreeNode current) {
		// 登録する数値が既に会った場合は何もせずにリターンする
		if (e == current.element) {
			return;
		} else {
			// そうでなければサブノードを再帰的に辿る。
			// 親のノードを現在のノードに設定して下位のノードを辿る準備をする
			parent = current;
			// 登録する数値が現在のノードの数値よりも小さい場合は左ノード、
			// 大きい場合は右ノードを現在のノードに設定する。
			current = (e <= current.element) ? current.left : current.right;
			// 現在のノードがnullになったら登録処理を行う。
			if (current == null) {
				current = new BinTreeNode(e);
				count++;
				// 親のノードよりも小さければ左ノードに追加
				// そうでなければ右ノードに追加する。
				if (e <= parent.element) {
					parent.left = current;
				} else {
					parent.right = current;
				}
			} else {
				// まだ登録できないため再帰的に辿っていく
				insert(e, parent, current);
			}
		}
	}

	public void delete(Integer e) {
		if (root == null) {
			return;

		} else {
			BinTreeNode parent = null;
			BinTreeNode current = root;
			deleteNode(current, e);
		}
	}

	// currentの最も左の方向にあるノードを返す
	// それがcurrentのサブツリーエントリの中の最も小さいノードである。
	public BinTreeNode minNode(BinTreeNode current) {
		BinTreeNode tmp = current;
		while (tmp != null && tmp.left != null)
			tmp = tmp.left;
		return tmp;
	}

	// ツリーから与えられたノードを削除する。
	public BinTreeNode deleteNode(BinTreeNode current, int e) {
		// currentが空ならば、current(null)を返す。
		if (current == null)
			return current;
		// 削除すべきノードは、leftのサブツリーにある
		if (e < current.element)
			current.left = deleteNode(current.left, e);
		// 削除すべきノードは、rightのサブツリーにある
		else if (e > current.element)
			current.right = deleteNode(current.right, e);
		// currentのノードが削除されるべきである
		else {
			// Case 1 + Case 2
			// leftがnullであるということは、2つの場合のどちらかという意味がある
			if (current.left == null) {
				return current.right;
			}
			// Case 2
			// ノードはleftを持っているが、rightを持っていない。
			// だから単一の子だけをもっている。
			else if (current.right == null) {
				return current.left;
			}
			// Case 3
			// 最初にsuccessorを見つける
			// successorは二分木をinorderで探索して次(next)にくるelementを持っているノード
			// だからrightサブツリー内のもっともleft方向のノードである。
			BinTreeNode successor = minNode(current.right);
			// currentノードをsuccessorに置き換える
			current.element = successor.element;
			// 今単純にcurrentの右からsuccessorを削除する
			current.right = deleteNode(current.right, successor.element);
			count--;
		}
		return current;
	}

	// 前順 (preorder)
	public void preorder() {
		preorder(root);
		System.out.println();
	}

	public void preorder(BinTreeNode treeNode) {
		if (treeNode == null) {
			return;
		}
		System.out.print(treeNode.element + " ");
		preorder(treeNode.left);
		preorder(treeNode.right);
	}

	// 間順 (inorder)
	public void inorder() {
		inorder(root);
		System.out.println();
	}

	public void inorder(BinTreeNode treeNode) {
		if (treeNode == null) {
			return;
		}
		inorder(treeNode.left);
		System.out.print(treeNode.element + " ");
		inorder(treeNode.right);
	}

	// 後順 (postorder)
	public void postorder() {
		postorder(root);
		System.out.println();
	}

	public void postorder(BinTreeNode treeNode) {
		if (treeNode == null) {
			return;
		}
		postorder(treeNode.left);
		postorder(treeNode.right);
		System.out.print(treeNode.element + " ");
	}

	@Override
	public String toString() {
		return root.toString();
	}
}



二分探索木(Javaサンプルプログラム)・続き
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

二分探索木(削除操作に苦戦)

2021-08-22 18:56:55 | 日記
二分探索木(削除操作に苦戦)

今日は、日曜日。曇り時々晴れ。

昨日、ブログを更新した後、寝ずにうだうだしていて、二分探索木の演習課題を作っていた。

そもそも二分探索木のプログラムを作らねばならないため、以下の記事のコードを

参考にして作った。

【1日1Java】ジェネリックスを使って二分探索木を実装
二分木図を印刷する方法は?

これをジェネリックにせずにIntegerに限定して改良してノードの追加とスキャン

(preorder/inorder/postorder)のみをサポートしたサンプルコードを作成。結局、昨日の

23時過ぎまでかかっていた。一応、その成果コードと相談を含めて、関係者各位にメールした。

よって今日は疲れ果てて、ずっと寝ていた。

10時~松ちゃんのワイドナショーを観ながら、朝食兼昼食を食べて寝た。

16時頃、教育関係の取締役からアドバイスのメールが届いたの気づき、起きて再び、

二分探索木の演習課題の続きをやった。

さらに追加機能としてノードのサーチ・削除をサポートしたが、上記資料の削除アルゴリズム

にバグがあり、急遽、以下の記事のC++コードを参考にして削除機能を実装した。

二分探索木削除操作

何とか動いたので、これで良しとして、教育関係の取締役にはメールを返した。

教育関係の取締役は平衡木(AVL)のサポートも注文に入っていたが、とても無理だと思い、

断念する意向も伝えた。

これから夕飯食って、シャワー浴びて寝る。

Javaの演習課題残項目は以下。

・不足分のJava演習課題
・SQL(正規化・データ分析)
・Webアプリケーション(SpringFramework)

明日は、リアル出勤だが、今日の成果をベースに"二分木"の演習課題改訂に着手したい。

今日も一日のコロナ感染数は全国で22285人、神奈川県は2524人、東京都は4392人。。

たはたは。。。コロナ感染者拡大中。もう心が潰えそう。。。

【今後の予定】
・2021年07月~ 職業訓練校Java&Python&Web技術者(3か月)
・2021年09月~ 職業訓練校Java&DB&Web技術者(3か月)
・2021年11月~ 職業訓練校(3か月)
・2022年01月~ 職業訓練校(3か月)
・2022年02月~ 職業訓練校(2か月)

【詳細TODOリスト】
・訓練校7月生対応
・訓練校9月生対応

・高度な教育講座の検討ww(笑)

【今日の読書】
5日でわかるOpenCVプログラミング入門 日経ソフトウエア
ビジュアルテキスト パターン認識 荒井 秀一(P.88/256読了)
多変量統計解析法 田中 豊
心を知るための人工知能: 認知科学としての記号創発ロボティクス (越境する認知科学) 谷口 忠大
物理学者のすごい思考法 (インターナショナル新書) 橋本 幸士
統計学への確率論、その先へ―ゼロからの測度論的理解と漸近理論への架け橋 清水 泰隆
代数幾何学入門:代数学の基礎を出発点として 永井 保成
ランダム行列の数理と科学 渡辺澄夫
認知バイアス 心に潜むふしぎな働き (ブルーバックス) 鈴木 宏昭
絵で見てわかるSQL Serverの仕組み 平山 理(P.84/314読了)
ベイズ統計の理論と方法 渡辺 澄夫
経済・ファイナンスのための カルマンフィルター入門 (統計ライブラリー) 森平 爽一郎
数理科学 2020年 11 月号 [雑誌]
人工知能 機械学習はどこまで進化するのか (別冊日経サイエンス239) 竹内郁雄
データ分析の力 因果関係に迫る思考法 (光文社新書) 伊藤 公一朗
応用に役立つ50の最適化問題 (応用最適化シリーズ) 藤澤 克樹
コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする