二叉查找樹是一種支持動態查詢的數據結構,所謂動態查尋結構:即在當數據集合內容發生改變時,集合內數據的排列組合不用從新構建。這樣的數據結構在查詢時須要不斷變更的場景中是很是高效的,二叉查找樹就是其中一個,而且它是SBT,AVL,紅黑樹的基礎,一直有興趣想要研究下。原理就不介紹了,可參考這個 。今天花了半天時間,本身完成了一個基於數組的Java實現。java
先簡單說明下這幾個方法的實現原理:node
下面是我本身實現的代碼,如有錯誤或可優化的地方,還望各位看官及時指出,我好更正。數組
package com.mycode.structures; import java.util.Collection; /** * 基於數組二叉查找樹實現 * @author Breath_L * @param <T> */ public class BSTree<T extends Comparable<T>> { private static final int DEFAULT_SIZE = 10; private T[] data; private Integer count; public Integer getCount(){ return count; } public BSTree(int size){ data = (T[]) new Object[size]; count = 0; } public BSTree(){ data = (T[]) new Object[DEFAULT_SIZE]; count = 0; } /** * 擴充容量 */ private void expandSize(){ T[] newDate = (T[]) new Object[data.length * 2]; System.arraycopy(data, 0, newDate, 0, data.length); data = newDate; } /** * 判斷二叉樹中是否包含元素 one * @param one * @return 若找到了,返回該元素在數組中的位置,不然返回-1 */ public int search(T one){ if(data[0] == null){ System.out.println("==> This BSTree is Empty!"); return -1; }else{ int index = 0; while(index < data.length && data[index] != null){ int f = one.compareTo(data[index]); if(f == 0){ //找到了返回其位置 return index; }else if(f < 0){ index = 2 * index + 1; }else{ index = 2 * index + 2; } } return -1; } } /** * 添加元素 * @param t */ public void add(T t){ if(data[0] == null){ data[0] = t; count++; return; }else{ int index = 0; while(index < data.length){ if(t.compareTo(data[index])<0){ int left = 2 * index + 1; if(left >= data.length) expandSize(); if(data[left] == null){ data[left] = t; break; }else{ index = left; } }else if(t.compareTo(data[index]) > 0){ int right = 2 * index + 2; if(right >= data.length) expandSize(); if(data[right] == null){ data[right] = t; break; }else{ index = right; } }else{ // 相同元素不處理,算是排重了 break; } } } count++; } public void addAll(Collection<T> all){ for (T t:all){ add(t); } } public void addAll(T[] all){ for (T t:all){ add(t); } } public void delete(T del){ int del_index = this.search(del); if(del_index != -1){ //等於-1 表示沒有,便不作處理 real_delete(del_index); } } /** * 刪除某個節點 * @param index:該節點在數組中的位置 * @return */ private void real_delete(int index){ int lc = 2*index + 1; int rc = 2*index + 2; if(data[lc] != null && data[rc] != null){ // 左子樹、右子樹同時存在的狀況 int left_max_child = findLeftMaxChild(index); data[index] = data[left_max_child]; //刪除節點 real_delete(left_max_child); //遞歸刪除左子樹中值最大的節點 }else if(data[lc] == null && data[rc] == null){ // 都沒有則直接刪除 data[index] = null; }else{ if(data[lc] != null){ replaceNodeWithChild(lc, lc-index); }else{ replaceNodeWithChild(rc, rc-index); } } } /** * 尋找某個節點的左子樹中最大節點 * @param index 某個節點的位置 * @return 最大節點位置 */ private int findLeftMaxChild(int index){ int left = 2*index +1; int bigger = 2*left + 2; while( bigger < data.length && data[bigger] != null){ left = bigger; bigger = 2 * bigger + 2; } return left; } /** * 若子節點C替換了其父節點P,則C的全部子節點都須要被移動(因爲數組的緣由),distance爲C和P在數組中位置之差。 * 其全部子節點在數組中移動的距離爲 distance*(2^x),x爲這些子節點與節點C的距離(相鄰節點距離爲1); * @param node * @param distance */ private void replaceNodeWithChild(int node, int distance){ int left = 2*node+1; int right = 2*node+2; int current_distance = distance*2; //每次遞歸距離*2 if(data[left] != null){ data[left - current_distance] = data[left]; replaceNodeWithChild(left,current_distance); //遞歸遍歷下個節點 } if(data[right] != null){ data[right - current_distance] = data[right]; replaceNodeWithChild(right,current_distance); } } }
原創博客,轉載請註明 http://my.oschina.net/BreathL/blog/54734