定義二叉樹的節點:包含左節點,右節點和當前結點的值
/**
* 定義二叉搜索樹的節點
* @param <AnyType>
*/
private static class BinaryNode<AnyType>{
BinaryNode(AnyType theElement){
this(theElement, null, null);
}
//通過構造函數創建節點
BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right){
this.theElement = theElement;
this.left = left;
this.right = right;
}
AnyType theElement;
BinaryNode left;
BinaryNode right;
}
節點之間的比較方法:通過自定義的Comparator或默認的Compare方法
/**
* 定義比較方法:若傳入了比較方式,則用傳入的比較方式,否則用默認方式
* 返回為0表示 lhs = rhs
* 返回為負數表示 lhs < rhs
* 返回為正數表示 lhs > rhs
* @param lhs
* @param rhs
* @return
*/
private int myCompare(AnyType lhs, AnyType rhs){
if (cmp != null){
return cmp.compare(lhs, rhs);
} else {
return ((Comparable)lhs).compareTo(rhs);
}
}
查找結點:比較傳入的元素與當前結點元素的值,若傳入的元素小于當前節點的元素,則繼續查找當前結點的左子樹,若大于,則繼續查找當前結點的右子樹,若等于,表示找到該節點,返回true。
/**
* 搜索二叉樹中是否包含某個元素節點
* @param x
* @param t
* @return
*/
private boolean contains(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return false;
}
//比較元素與當前結點的元素
int compareResult = myCompare(x, t.theElement);
//小于當前元素,則搜索左子樹
if (compareResult < 0){
contains(x, t.left);
}
//大于當前元素,則搜索右子樹
else if (compareResult > 0){
contains(x, t.right);
}
//等于情況,表示存在,直接返回
return true;
}
插入節點:若當前結點為空,則將新節點放置此處,否則判斷傳入的值與當前節點的值,若傳入的值小于當前結點的值則繼續搜索當前結點的左子樹,若大于,則繼續搜索當前結點的右子樹。
/**
* 實現插入操作
* @param x
* @param t
* @return
*/
private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
//當前節點為空,則將該節點在此處
if (t == null){
return new BinaryNode<AnyType>(x, null, null);
}
//進行比較
int compareResult = myCompare(x, t.theElement);
//元素小于當前結點元素,則加入到左子樹
if (compareResult < 0){
t.left = insert(x, t.left);
} else if (compareResult > 0){
t.right = insert(x, t.right);
} else {
//do nothing
}
return t;
}
刪除某個節點:先根據給定的值找到要刪除的節點,若沒有找到該節點,則不會進行刪除操作。
a. 刪除的節點為葉子節點,即沒有孩子,則直接刪除即可,不會破壞樹的結構。
Paste_Image.png
b. 若節點中只包含左子樹,或只包含右子樹,則直接刪除該節點,并將其左子樹或右子樹設置為父節點的左子樹或右子樹即可。
Paste_Image.png
c. 當刪除的節點中包含左右子樹時,一般的策略是用其右子樹的最小數據代替要刪除的節點,并遞歸刪除該節點。因為右子樹的最小節點是不可能有左子樹的,因此第二次刪除較為容易。
Paste_Image.png
如上圖,我們要刪除的節點是5,則找到該節點,然后找到節點值為5的右子樹的最小節點,即節點值為6的節點--->將節點值為6的節點代替要刪除的節點5---->然后遞歸刪除原本的節點6
/**
* 實現移除某個節點
* @param x
* @param t
* @return
*/
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return t;
}
//比較大小
int compareResult = myCompare(x, t.theElement);
//元素小于當前結點元素,則搜索左子樹
if (compareResult < 0){
t.left = remove(x, t.left);
}
//元素大于當前結點元素,則搜索右子樹
else if (compareResult > 0){
t.right = remove(x, t.right);
}
//相等,表示找到對應的節點,如果該節點存在左右孩子
else if (t.left != null && t.right != null){
//搜索到右子樹的最小節點,并替代當前結點
t.theElement = (AnyType) findMin(t.right).theElement;
//并遞歸刪除右子樹的最小節點
t.right = remove(t.theElement, t.right);
}
//否則,將不為空的孩子節點替代掉當前結點
else {
t = (t.left != null) ? t.left : t.right;
}
return t;
}
查找最大的節點:不斷向右邊搜索節點,直到該節點不存在右邊子節點。
查找最小的節點:不斷向左邊搜索節點,直到該節點不存在左邊子節點。
/**
* 實現獲取二叉樹中最小的節點
* 遞歸查找左子樹,直到當前結點的左節點為空,則返回當前節點
* @param t
* @return
*/
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
if (t == null){
return null;
} else if (t.left == null){
return t;
}
return findMin(t.left);
}
/**
* 實現獲取二叉樹中最大的節點
* 遞歸查找右子樹,直到當前節點的右節點為空,返回當前節點
* @param t
* @return
*/
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
if (t == null){
return null;
} else if (t.right == null){
return t;
}
return findMax(t.right);
}
實現三種遍歷樹的方式:
/**
* 前序遍歷
* 訪問順序為:根節點->左節點->右節點
* @param node
*/
public void preOrder(BinaryNode<AnyType> node){
if (node != null){
System.out.print(node.right + " ");
preOrder(node.left);
preOrder(node.right);
}
}
/**
* 中序遍歷
* 訪問順序為:左節點->根節點->右節點
* @param node
*/
public void inOrder(BinaryNode<AnyType> node){
if (node != null){
inOrder(node.left);
System.out.print(node.theElement + " ");
inOrder(node.right);
}
}
/**
* 后序遍歷
* 訪問順序為:左節點->右節點->根節點
* @param node
*/
public void postOrder(BinaryNode<AnyType> node){
if (node != null){
postOrder(node.left);
postOrder(node.right);
System.out.print(node.theElement + " ");
}
}
完整代碼:
package BinaryTree;
import org.omg.CORBA.Any;
import java.nio.BufferUnderflowException;
import java.util.Comparator;
/**
* Created by Administrator on 2017/3/7/007.
* 實現搜索二叉樹的基本操作
*/
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {
/**
* 定義二叉搜索樹的節點
* @param <AnyType>
*/
private static class BinaryNode<AnyType>{
BinaryNode(AnyType theElement){
this(theElement, null, null);
}
//通過構造函數創建節點
BinaryNode(AnyType theElement, BinaryNode<AnyType> left, BinaryNode<AnyType> right){
this.theElement = theElement;
this.left = left;
this.right = right;
}
AnyType theElement;
BinaryNode left;
BinaryNode right;
}
/**
* 定義二叉樹的根節點
*/
private BinaryNode<AnyType> root;
/**
* 定義比較方式
*/
private Comparator<? super AnyType> cmp;
public BinarySearchTree(){
this(null);
}
/**
* 構造函數,傳入比較方式
* @param c
*/
public BinarySearchTree(Comparator<? super AnyType> c){
root = null;
cmp = c;
}
/**
* 定義比較方法:若傳入了比較方式,則用傳入的比較方式,否則用默認的方法
* @param lhs
* @param rhs
* @return
*/
private int myCompare(AnyType lhs, AnyType rhs){
if (cmp != null){
return cmp.compare(lhs, rhs);
} else {
return ((Comparable)lhs).compareTo(rhs);
}
}
/**
* 使二叉樹變為空
*/
public void makeEmpty(){
root = null;
}
/**
* 檢查二叉樹是否為空
* @return
*/
public boolean isEmpty(){
return root == null;
}
/**
* 檢查二叉樹中是否包含某個元素
* @param x
* @return
*/
public boolean contains(AnyType x){
return contains(x, root);
}
/**
* 搜索查找二叉樹中最小的元素
* @return
*/
public AnyType findMin(){
if (isEmpty()) throw new BufferUnderflowException();
return findMin(root).theElement;
}
/**
* 搜索查找二叉樹中最大的元素
* @return
*/
public AnyType findMax(){
if (isEmpty()) throw new BufferUnderflowException();
return findMax(root).theElement;
}
/**
* 插入元素
* @param x
*/
public void insert(AnyType x){
root = insert(x, root);
}
/**
* 刪除元素
* @param x
*/
public void remove(AnyType x){
root = remove(x, root);
}
/**
* 搜索二叉樹中是否包含某個元素節點
* @param x
* @param t
* @return
*/
private boolean contains(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return false;
}
//比較元素與當前結點的元素
int compareResult = myCompare(x, t.theElement);
//小于當前元素,則搜索左子樹
if (compareResult < 0){
contains(x, t.left);
}
//大于當前元素,則搜索右子樹
else if (compareResult > 0){
contains(x, t.right);
}
//等于情況,表示存在,直接返回
return true;
}
/**
* 實現獲取二叉樹中最小的節點
* 遞歸查找左子樹,直到當前結點的左節點為空,則返回當前節點
* @param t
* @return
*/
private BinaryNode<AnyType> findMin(BinaryNode<AnyType> t){
if (t == null){
return null;
} else if (t.left == null){
return t;
}
return findMin(t.left);
}
/**
* 實現獲取二叉樹中最大的節點
* 遞歸查找右子樹,直到當前節點的右節點為空,返回當前節點
* @param t
* @return
*/
private BinaryNode<AnyType> findMax(BinaryNode<AnyType> t){
if (t == null){
return null;
} else if (t.right == null){
return t;
}
return findMax(t.right);
}
/**
* 實現插入操作
* @param x
* @param t
* @return
*/
private BinaryNode<AnyType> insert(AnyType x, BinaryNode<AnyType> t){
//當前節點為空,則將該節點在此處
if (t == null){
return new BinaryNode<AnyType>(x, null, null);
}
//進行比較
int compareResult = myCompare(x, t.theElement);
//元素小于當前結點元素,則加入到左子樹
if (compareResult < 0){
t.left = insert(x, t.left);
} else if (compareResult > 0){
t.right = insert(x, t.right);
} else {
//do nothing
}
return t;
}
/**
* 實現移除某個節點
* @param x
* @param t
* @return
*/
private BinaryNode<AnyType> remove(AnyType x, BinaryNode<AnyType> t){
if (t == null){
return t;
}
//比較大小
int compareResult = myCompare(x, t.theElement);
//元素小于當前結點元素,則搜索左子樹
if (compareResult < 0){
t.left = remove(x, t.left);
}
//元素大于當前結點元素,則搜索右子樹
else if (compareResult > 0){
t.right = remove(x, t.right);
}
//相等,表示找到對應的節點,如果該節點存在左右孩子
else if (t.left != null && t.right != null){
//搜索到右子樹的最小節點,并替代當前結點
t.theElement = (AnyType) findMin(t.right).theElement;
//并遞歸刪除右子樹的最小節點
t.right = remove(t.theElement, t.right);
}
//否則,將不為空的孩子節點替代掉當前結點
else {
t = (t.left != null) ? t.left : t.right;
}
return t;
}
/**
* 前序遍歷
* 訪問順序為:根節點->左節點->右節點
* @param node
*/
public void preOrder(BinaryNode<AnyType> node){
if (node != null){
System.out.print(node.right + " ");
preOrder(node.left);
preOrder(node.right);
}
}
/**
* 中序遍歷
* 訪問順序為:左節點->根節點->右節點
* @param node
*/
public void inOrder(BinaryNode<AnyType> node){
if (node != null){
inOrder(node.left);
System.out.print(node.theElement + " ");
inOrder(node.right);
}
}
/**
* 后序遍歷
* 訪問順序為:左節點->右節點->根節點
* @param node
*/
public void postOrder(BinaryNode<AnyType> node){
if (node != null){
postOrder(node.left);
postOrder(node.right);
System.out.print(node.theElement + " ");
}
}
}