二分探索木

/****************************/
/* 二分探索木               */
/*      coded by Y.Suganuma */
/****************************/
import java.io.*;
import java.util.*;

/********************/
/* クラスListの定義 */
/********************/
class List
{
	int st;
	List left, right;
				// コンストラクタ
	List ()
	{
		st = -1;
	}

	List (int s)
	{
		st = s;
	}

	/***************************************/
	/* データの追加                        */
	/*      dt : Listクラスのオブジェクト  */
	/*      return : =1 : 追加             */
	/*               =0 : 同じデータが存在 */
	/***************************************/
	int add(List dt)
	{
		List lt = this;
		int k, sw = -1;
						// トップ
		if (lt.st < 0) {
			lt.st = dt.st;
			sw    = 1;
		}
						// トップでない
		else {
			while (sw < 0) {
				k = dt.st - lt.st;
								// 同じデータがある
				if (k == 0)
					sw = 0;
								// 大きい
				else if (k > 0) {
					if (lt.right == null) {
						lt.right = dt;
						sw       = 1;
					}
					else
						lt = lt.right;
				}
								// 小さい
				else {
					if (lt.left == null) {
						lt.left = dt;
						sw      = 1;
					}
					else
						lt = lt.left;
				}
			}
		}
	
		return sw;
	}

	/***************************************/
	/* データの削除                        */
	/*      st : 数値                      */
	/*      return : =1 : 削除した         */
	/*               =0 : 削除できなかった */
	/***************************************/
	int del(int st)
	{
		List lt, lt1 = this, lt2 = this, dt;
		int k, rl = 0, sw = 0;
	
		if (lt2.st >= 0) {
			while (sw == 0 && lt2 != null) {
				k = st - lt2.st;
						// 削除
				if (k == 0) {
					sw = 1;
					if (lt2.right == null) {
								// 子供無し
						if (lt2.left == null) {
							if (rl == 0)
								lt2.st = -1;
							else {
								if (rl > 0)
									lt1.right = null;
								else
									lt1.left = null;
							}
						}
								// 右無し
						else {
							if (rl == 0) {
								lt2.st    = (lt2.left).st;
								lt2.right = (lt2.left).right;
								lt2.left  = (lt2.left).left;
							}
							else {
								if (rl > 0)
									lt1.right = lt2.left;
								else
									lt1.left = lt2.left;
							}
						}
					}
	
					else {
								// 左無し
						if (lt2.left == null) {
							if (rl == 0) {
								lt2.st    = (lt2.right).st;
								lt2.left  = (lt2.right).left;
								lt2.right = (lt2.right).right;
							}
							else {
								if (rl > 0)
									lt1.right = lt2.right;
								else
									lt1.left = lt2.right;
							}
						}
								// 左右あり
						else {
							dt = lt2.left;
							if (rl == 0) {
								lt         = lt2.right;
								lt2.st    = lt.st;
								lt2.right = lt.right;
								lt2.left  = lt.left;
							}
							else {
								if (rl > 0)
									lt1.right = lt2.right;
								else
									lt1.left = lt2.right;
							}
							lt1.add(dt);
						}
					}
				}
						// 次のデータ
				else {
					lt1 = lt2;
					if (k > 0) {
						lt2 = lt2.right;
						rl  = 1;
					}
					else {
						lt2 = lt2.left;
						rl  = -1;
					}
				}
			}
		}
	
		return sw;
	}

	/***********************************/
	/* データの探索                    */
	/*      st : 数値                  */
	/*      return : =1 : 見つかった   */
	/*               =0 : 見つからない */
	/***********************************/
	int search(int st)
	{
		List lt = this;
		int k, sw = 0;
	
		if (lt.st >= 0) {
			while (sw == 0 && lt != null) {
				k = st - lt.st;
						// 見つかった
				if (k == 0)
					sw = 1;
						// 次のデータ
				else if (k > 0)
					lt = lt.right;
				else
					lt = lt.left;
			}
		}
	
		return sw;
	}

	/**********************/
	/* リストデータの出力 */
	/**********************/
	void output()
	{
		List nt = this;
						// 出力
		if (nt.st >= 0) {
			System.out.print(nt.st);
			if (nt.right != null)
				System.out.print(" right " + (nt.right).st);
			if (nt.left != null)
				System.out.print(" left " + (nt.left).st);
			System.out.println();
						// 次の出力
			if (nt.right != null)
				(nt.right).output();
			if (nt.left != null)
				(nt.left).output();
		}
	}
}

/****************/
/* main program */
/****************/
public class Test
{
	public static void main (String[] args)
	{
		List base = new List ();
		List lt;
		int i1, k, ct = 0, sw, s[] = new int [100000];
		long tm1, tm2, tm3;
		Random rn = new Random((long)12345);
					// データの追加
		System.out.printf("二分探索木\n");
		tm1 = System.currentTimeMillis();
		while (ct < 5000000) {
			k  = rn.nextInt();
			lt = new List (k);
			sw = base.add(lt);
			if (sw > 0) {
				ct++;
				if (ct < 100000)
					s[ct] = k;
			}
		}
		tm2 = System.currentTimeMillis();
		System.out.printf("   保存: %d ms\n", tm2-tm1);
					// 探索
		for (i1 = 0; i1 < 100000; i1++)
			base.search(s[i1]);
		tm3 = System.currentTimeMillis();
		System.out.printf("   探索: %d ms\n", tm3-tm2);
		System.out.printf("   データ数: %d\n", ct);
	}
}

--------------------------------------------------------------

/******************************/
/* 二分探索木(TreeSetの利用) */
/*      coded by Y.Suganuma   */
/******************************/
import java.io.*;
import java.util.*;

/****************/
/* main program */
/****************/
public class Test
{
	public static void main (String[] args)
	{
		TreeSet <Integer> data = new TreeSet <Integer> ();
		int i1, k, ct = 0, s[] = new int [100000];
		boolean sw;
		long tm1, tm2, tm3;
		Random rn = new Random((long)12345);
					// データの追加
		System.out.printf("二分探索木(TreeSetの利用)\n");
		tm1 = System.currentTimeMillis();
		while (ct < 5000000) {
			k  = rn.nextInt();
			sw = data.add(k);
			if (sw) {
				ct++;
				if (ct < 100000)
					s[ct] = k;
			}
		}
		tm2 = System.currentTimeMillis();
		System.out.printf("   保存: %d ms\n", tm2-tm1);
					// 探索
		for (i1 = 0; i1 < 100000; i1++)
			data.contains(s[i1]);
		tm3 = System.currentTimeMillis();
		System.out.printf("   探索: %d ms\n", tm3-tm2);
		System.out.printf("   データ数: %d\n", ct);
	}
}
		

  このプログラムを実行すると以下のような出力が得られます.
二分探索木
  保存: 5718 ms
  探索: 35 ms
  データ数: 5000000
二分探索木(TreeSetの利用)
   保存: 9791 ms
   探索: 85 ms
   データ数: 5000000