設x是二叉搜索樹中的一個結點。如果y是x左子樹中的一個結點,那麼y.key<=x.key。如果y是x右子樹中的一個結點,那麼y.key >= x.key。
結構圖可參看:
public class Node{
//依次保存左右節點以及父節點
Node left;
Node right;
Node parent;
//存放數據值
private Object data;
public Node(){
}
public Node(Object data){
this.data = data;
}
public Node(Object data, Node parent, Node left, Node right){
this.data = data;
this.parent = parent;
this.left = left;
this.right = right;
}
public String toString(){//只返回data的值
return data + "";
}
public boolean equals(Object obj){//判斷兩個對象是否相等
if(this == obj){
return true;
}
if(obj.getClass() == Node.class){ //getClass()進行類型判斷 instanceof: 判斷左邊對象是否是右邊類的實例 --boolean類型的值
Node target = (Node)obj;
return data.equals(target.data)
&& left == target.left
&& right == target.right
&& parent == target.parent;
}
return false;
}
}
//中序
public List<Node> in_order(){
return in_order(root);
}
public List<Node> in_order(Node node){
List<Node> list = new ArrayList<Node>();
if(node.left != null){
list.addAll(in_order(node.left));
}
list.add(node);
if(node.right != null){
list.addAll(in_order(node.right));
}
return list;
}
//查詢
public Node tree_search(T data){
return tree_search(root, data);
}
private Node tree_search(Node node, T data){// 根據元素去訪問這個值
if(node == null){
return null;
}
//x.compareTo(y) x=y -- 0, x > y - 1, x < y - -1
int cmp = data.compareTo(node.data);
if(cmp < 0){
return tree_search(node.left, data);
}
else if(cmp > 0){
return tree_search(node.right,data);
}
else{
return node;
}
}
//返回最大 和最小關鍵字元素
public Node mininum(){
return mininum(root);
}
public Node mininum(Node node){
while(node.left != null){
node = node.left;
}
return node;
}
public Node maxinum(){
return maxinum(root);
}
public Node maxinum(Node node){
while(node.right != null){
node = node.right;
}
return node;
}
//尋找前驅和後繼 簡單的遵循一條路徑沿樹向下 或者 沿樹向上。
public Node successor(Node node){
if(node.right != null){
return mininum(node.right);
}
Node newNode = node.parent;
while(newNode != null && node == newNode.right){
node = newNode;
newNode = newNode.parent;
}
return newNode;
}
public Node presuccessor(Node node){
if(node.left != null){
return mininum(node.left);
}
Node newNode = node.parent;
while(newNode != null && node == newNode.left){
node = newNode;
newNode = newNode.parent;
}
return newNode;
}
//插入數據
public Node insert(T data) {
// 如果根節點爲空
if(root == null){
root = new Node(data, null, null, null);
}
else{
Node current = root;
Node parent = null;
int cmp = 0;
//搜索到合適的葉子節點,以該節點爲父節點添加新的節點
while(current != null){//找到合適的位置 假定的"null"會被我指定的值替換
parent = current;
cmp = data.compareTo(current.data);
if(cmp < 0){
current = current.left;
}
else{
current = current.right;
}
}
//創建新節點, 通過直接的比較知道了它的父節點的值, 接下來就是通過比較 判斷是他父節點的 左還是右節點
Node newNode = new Node(data, parent, null, null);
if(cmp > 0){
parent.right = newNode;
}
else{
parent.left = newNode;
}
return newNode;
}
return null;
}
- 如果z沒有左孩子(圖12-4(a)),那麼用其右孩子來替換z,這個右孩子可以是NIL,也可以不是。當z的右孩子是NIL時,此時這種情況歸爲z沒有孩子結點的情形。當z的右孩子非NIL時,這種情況就是z僅有一個孩子結點的情形,該孩子是其右孩子。
- 如果z僅有一個孩子且爲其左孩子(圖12-4(b)),那麼用其左孩子來替換z。
- 否則,z既有一個左孩子又有一個右孩子。我們要查找z的後繼y,這個後繼位於z的右子樹中並且沒有左孩子(見練習12.2-5)。現在需要將y移出原來的位置進行拼接,並替換樹中的z。
- 如果y是z的右孩子(圖12-4(c)),那麼用y替換z,並僅留下y的右孩子。
- 否則,y位於z的右子樹中但並不是z的右孩子(圖12-4(d))。在這種情況下,先用y的右孩子替換y,然後再用y替換z。
//刪除指定節點
public void delete(T element){
//獲取要刪除的節點 注意這裏是通過查找而不是new
Node target = tree_search(element);
if(target == null){
return;
}
else{
Node newNode = null;
//沒有左孩子, 刪除改節點之後把自己的右節點補上來即可
if(target.left == null){
transplant(target, target.right);
}
//由一個左孩子, 沒有右孩子
else if(target.right == null){
transplant(target, target.left);
}
else{
//如果它有右子樹(或者叫右子樹非空) 那麼它的後繼一定是他右子樹的最小值
newNode = mininum(target.right);
if(newNode.parent != target){
transplant(newNode, newNode.right);
newNode.right = target.right;
newNode.right.parent = newNode;
}
transplant(target, newNode);
newNode.left = target.left;
newNode.left.parent = newNode;
}
}
}
private void transplant(Node node1, Node node2) {
if(node1.parent == null){
Node current = root;
current = node2;
}
else if(node1 == node1.parent.left){
node1.parent.left = node2;
}
else{
node1.parent.right = node2;
}
if(node2 != null){
node1.parent = node2.parent;
}
}
測試部分和截圖:
//構建二叉排序樹
public SortBinTree(){
root = null;
}
public SortBinTree(T data){
root = new Node(data, null, null, null);
}
測試:public static void main(String[] args) {
SortBinTree<Integer> sbt = new SortBinTree<Integer>(15);
SortBinTree.Node node = sbt.insert(5);
sbt.insert(20);
sbt.insert(10);
sbt.insert(3);
sbt.insert(8);
sbt.insert(30);
System.out.println(sbt.in_order());
System.out.println("最小關鍵元素值" + sbt.mininum());
System.out.println("最大關鍵元素值" +sbt.maxinum());
sbt.insert(17);
System.out.println(sbt.in_order());
System.out.println("節點5的前驅是:" + sbt.presuccessor(node));
System.out.println("節點5的後繼是:" + sbt.successor(node));
sbt.delete(8);
System.out.println(sbt.in_order());
}