001:import java.util.ArrayList;
002:
003:/**
004: * 2分探索木 Binary Search Tree
005: *       @see <A HREF="http://www.geocities.jp/h2fujimura/mutter/tree/binary-search-tree.html">2分探索木</A>
006: *       @auther Hikaru Fujimura
007: *       @version 2005.08.25
008: */
009:public class BinaryTree<T extends Comparable> {
010:
011:	T                value;   // データ
012:	BinaryTree<T>    parent;  // 親のノード
013:	BinaryTree<T>    left;    // 左部分木
014:	BinaryTree<T>    right;   // 右部分木
015:
016:/** 部分木の生成 */
017:	private BinaryTree(T v, BinaryTree<T> p, BinaryTree<T> l, BinaryTree<T> r) {
018:		value = v;
019:		parent = p;
020:		left = l;
021:		right = r;
022:	}
023:
024:/**
025: * 要素 v だけをもつ2分探索木の生成します。
026: * 生成した木を部分木として、NIL とおきかえるには、
027: * setAsLeaf メソッドを使用してください。
028: *        @param  v   根に設定する値
029: */
030:	BinaryTree(T v) {
031:		if(v==null) throw new IllegalArgumentException();
032:		value  = v;
033:		parent = null;
034:		left   = new BinaryTree<T>(null, this, null, null);
035:		right  = new BinaryTree<T>(null, this, null, null);
036:	}
037:
038:/**
039: * 空木の生成します。
040: * NIL としても使われます。
041: */
042:	BinaryTree() {
043:		this(null, null, null, null);
044:	}
045:
046:/**
047: * NIL の判定。
048: *        @return value フィールドが null のとき true、そうでないとき false
049: */
050:	boolean isNIL() { return value==null; }
051:
052:/**
053: * 根の判定。
054: *        @return parent フィールドが null のとき true、そうでないとき false
055: */
056:	boolean isRoot() { return parent==null; }
057:
058:/** 値の取得 */
059:	T getValue()              { return value; }
060:/** 親の取得 */
061:	BinaryTree<T> getParent() { return parent; }
062:/** 左部分木の取得 */
063:	BinaryTree<T> getLeft()   { return left; }
064:/** 右部分木の取得 */
065:	BinaryTree<T> getRight()  { return right; }
066:
067:/**
068: * 値の設定。
069: *      @throws IllegalArgumentException() パラメタが null の場合
070: */
071:	void setValue(T v) {
072:		if(v==null) throw new IllegalArgumentException("null");
073:		value = v;
074:	}
075:
076:/**
077: * 葉の作成。
078: * この部分木(通常 NIL)を v を値とする葉に書き換えます。
079: * parent フィールドは不変です。
080: *      @throws IllegalArgumentException() パラメタが null の場合
081: */
082:	BinaryTree<T> setAsLeaf(T v) {
083:		if(v==null) throw new IllegalArgumentException("null");
084:		value  = v;
085:		left   = new BinaryTree<T>(null, this, null, null);
086:		right  = new BinaryTree<T>(null, this, null, null);
087:		return this;
088:	}
089:
090:/**
091: * 文字列としての値
092: */
093:	public String toString() {
094:		if(this.value==null) return "null";
095:		return value.toString();
096:	}
097:
098:/**
099: * 浅いコピー
100: */
101:	public BinaryTree<T> clone() {
102:		if(isNIL()) return new BinaryTree<T>();
103:		else {
104:			BinaryTree<T> newLeft = left.clone();
105:			BinaryTree<T> newRight = right.clone();
106:			BinaryTree<T> newNode = new BinaryTree<T>(value, null, newLeft, newRight);
107:			newLeft.parent = newNode;
108:			newRight.parent = newNode;
109:			return newNode;
110:		}
111:	}
112:
113:/**
114: * 文字列への変換(デバッグ用)
115: */
116:	String toLongString() {
117:		if(isNIL()) return "NIL";
118:		StringBuffer s = new StringBuffer("[");
119:		if(value==null) s.append("null");
120:		else            s.append(value.toString());
121:		s.append(",");
122:		if(left==null)         s.append("null");
123:		else if(left.isNIL())  s.append("NIL");
124:		else                   s.append(left.toLongString());
125:		s.append(",");
126:		if(right==null)        s.append("null");
127:		else if(right.isNIL()) s.append("NIL");
128:		else                   s.append(right.toLongString());
129:		s.append("]");
130:		return s.toString();
131:	}
132:
133:/**
134: * この木を ArrayList へ変換します。
135: *       @return ノードの値を昇順に含む ArrayList
136: */
137:	ArrayList<T> toArrayList() { 
138:		ArrayList<T> a = new ArrayList<T>();
139:		if(isNIL()) return a;
140:		a.addAll(left.toArrayList());
141:		a.add(value);
142:		a.addAll(right.toArrayList());
143:		return a;
144:	}
145:
146:/**
147: * この2分探索木をさがし、 値v を含む部分木を返します。
148: *
149: *         @param v    探す値
150: *         @return     根の値が v である部分木、または NIL (見つからない場合)
151: */
152:	BinaryTree<T> search(T v) {
153:		if(isNIL())                   return this;
154:		if(v.compareTo(value)<0)      return left.search(v);
155:		else if(v.compareTo(value)>0) return right.search(v);
156:		else                          return this;
157:	}
158:
159:/**
160: * この2分探索木に 値v を挿入します。
161: *
162: *         @param v    挿入する値
163: *         @return     元の2分探索木、空木に挿入した場合は新しい木
164: */
165:	BinaryTree<T> insert(T v) {
166:		if(isNIL()) return new BinaryTree<T>(v);   // empty tree
167:		BinaryTree<T> x = search(v);               // search v
168:		while(!x.isNIL()) {                        // found?
169:			x = (x.right).search(v);               // yes, check right subtree
170:		}
171:		x.setAsLeaf(v);
172:		return this;
173:	}
174:
175:/**
176: * この2分探索木から 値v を削除します。
177: *
178: *         @param v    削除する値
179: *         @return     元の2分探索木(削除後)
180: */
181:	BinaryTree<T> delete(T v) {
182:		if(isNIL()) return this;                  // empty tree
183:		BinaryTree<T> t = search(v);              // search
184:		if(t.isNIL()) return this;                // not found
185:		if(t.left.isNIL() && t.right.isNIL()) {   // no child
186:			t.value = null;                       // change to NIL
187:			t.left = null;                        //
188:			t.right = null;                       //
189:			return this;                          // only parent chain
190:		}
191:		if(t.left.isNIL()) {                      // no left subtree
192:			t = t.replace(t.right);               // replace here by right subtree
193:			if(t.isRoot()) return t;
194:			else           return this;
195:		}
196:		if(t.right.isNIL()) {                     // no right subtree
197:			t = t.replace(t.left);                // replace here by left subtree
198:			if(t.isRoot()) return t;
199:			else           return this;
200:		}                                         // now, t has 2 subtree
201:		BinaryTree<T> x = t.left;                 // get smaller subtree
202:		while(!x.right.isNIL()) {                 // as far as right subtree exist
203:			x = x.right;                          // get greater value
204:		}                                         // 
205:		T prev = x.value;                         // maximun value that less than v
206:		x.replace(x.left);                        // replace here by left
207:		t.value = prev;                           // replace v
208:		return this;                              // and return
209:	}
210:
211:/**
212: * この部分木をパラメタに指定された部分木で置換します。
213: *
214: *         @param t    部分木
215: *         @return     元の2分探索木、または t (元の部分木が根の場合)
216: */
217:	private BinaryTree<T> replace(BinaryTree<T> t) {
218:		t.parent = parent;
219:		if(this.isRoot()) return t;
220:		if(parent.left==this) parent.left = t;
221:		else                  parent.right = t;
222:		return this;
223:	}
224:
225:/**
226: * この木の指定された個所を右回転します。
227: *         @param here 回転する中心のノード(部分木)
228: *         @return     元の2分探索木(回転後)
229: */
230:	BinaryTree<T> rotateRight(BinaryTree<T> here) {
231:		if(isNIL()) return this;
232:		if(here.left.isNIL()) return this;
233:		boolean atRoot = false;
234:		if(here.isRoot()) atRoot = true;
235:		BinaryTree<T> father = here.parent;
236:		BinaryTree<T> newTop = here.left;
237:		here.parent = newTop;
238:		here.left = here.left.right;
239:		newTop.parent = father;
240:		newTop.right = here;
241:		if(atRoot) return newTop;
242:		else {
243:			if(father.left==here) father.left = newTop;
244:			else                  father.right = newTop;
245:			return this;
246:		}
247:	}
248:
249:/**
250: * この木の指定された個所を左回転します。
251: *         @param here 回転する中心のノード(部分木)
252: *         @return     元の2分探索木(回転後)
253: */
254:	BinaryTree<T> rotateLeft(BinaryTree<T> here) {
255:		if(isNIL()) return this;
256:		if(here.right.isNIL()) return this;
257:		boolean atRoot = false;
258:		if(here.isRoot()) atRoot = true;
259:		BinaryTree<T> father = here.parent;
260:		BinaryTree<T> newTop = here.right;
261:		here.parent = newTop;
262:		here.right = here.right.left;
263:		newTop.parent = father;
264:		newTop.left = here;
265:		if(atRoot) return newTop;
266:		else {
267:			if(father.left==here) father.left = newTop;
268:			else                  father.right = newTop;
269:			return this;
270:		}
271:	}
272:
273:/**
274: * 兄弟を取得します。
275: *         @return     親の子で、自分でない方の部分木。 この木が根の場合は null を返します。
276: */
277:	BinaryTree<T> getBrother() {
278:		if(isRoot()) return null;
279:		if(parent.left==this) return parent.right;
280:		else                  return parent.left;
281:	}
282:
283:/**
284: * 叔父を取得します。
285: *         @return     親の親の子の内で、自分の親でない方の部分木、叔父までたどれない場合は null
286: */
287:	BinaryTree<T> getUncle() {
288:		if(isRoot()) return null;
289:		if(parent.isRoot()) return null;
290:		BinaryTree<T> grandPa = parent.parent;
291:		if(grandPa.left.isNIL()) return null;
292:		if(grandPa.left==parent) return grandPa.right;
293:		else                     return grandPa.left;
294:	}
295:}