二叉搜索樹的概念
二叉查找樹(Binary Search Tree),(又:二叉搜索樹,二叉排序樹)它或者是一棵空樹,或者是具有下列性質的二叉樹: 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別爲二叉排序樹。
二叉搜索樹的代碼實現
定義二叉搜索樹的數據結構及基本方法
//定義樹節點
public class Node{
private int key; //節點索引
private int value; //節點值
private int count; //節點個數
private Node left; //左孩子
private Node right; //右孩子
//
public Node(int key,int value){
this.key = key;
this.value = value;
this.left = this.right = null;
}
//返回樹的節點個數
public int size(){
return count;
}
//判斷樹空
public boolean isEmpty(){
return count == 0;
}
}
爲二叉樹插入一個節點
採用遞歸的方法向樹中插入節點,比較節點索引值,若要插入的節點的索引小於當前節點索引,則插入到當前節點的”左邊”,若要插入節點的索引大於當前節點索引,則插入到當前節點的右邊,要插入節點索引與當前節點相等時替換當前節點的節點value,
//向根節點爲root的樹中插入節點
public Node insert(Node root , int key,int value){
if(root == null){
count++;
return new Node(key,value);
}
if(key == root.key)
root.value = value;
if(key < root.key)
root.left = insert(root.left,key,value);
if(key > root.key)
root.right = insert(root.right,key,value);
//返回root
return root;
}
查找索引爲key的節點
//二叉搜索樹查找,按鍵查找
public Node search(Node root,int key){
if(root == null)
return null;
if(root.key == key)
return root;
else if(key < root.key)
return search(root.left,key);
else
return search(root.right,key);
}
刪除樹中索引最小的節點
索引最小的節點在樹的最左下角,在刪除時需要判斷此要刪除的節點是否還有右子樹,若有需要將右子樹替換到被刪除的位置
//刪除最小值
public Node deleteMin(Node root){
//刪除最小值前判斷其是否有右子樹
if(root.left == null){
Node node = root.right;
count--;
return node;
}
root.left = deleteMin(root.left);
return root;
}
刪除樹索引中最大的節點
//刪除最大值
public Node deleteMax(Node root){
//刪除最大節點前判斷其是否有左子樹
if(root.right == null){
Node node = root.left;
count--;
return node;
}
root.right = deleteMax(root.right);
return root;
}
刪除樹中任意節點(相對複雜)
按照索引key找到需要刪除的節點,此時要分情況討論:
1、要刪除的節點左子樹爲空:將此節點的右子樹替換要刪除節點的位置
2、要刪除的節點右子樹爲空:將此節點的左子樹替換要刪除位置
3、左右子樹都不爲空:尋找此節點右子樹的最小索引節點替換要刪除節點位置,或者尋找左子樹的最大索引節點替換要刪除的節點
//刪除二叉搜索樹中的任意節點
public Node deleteNode(Node root,int key){
if(root == null)
return null;
if(key < root.key){
root.left = deleteNode(root.left,key);
return root;
}else if(key > root.key){
root.right = deleteNode(root.right,key);
return root;
}else{
//找到該節點,判斷該節點有無左右子樹
if(root.left == null){
Node node = root.right;
count--;
return node;
}
if(root.right == null){
Node node = root.left;
count--;
return node;
}
//左右子樹都不爲空的情況下,尋找右子樹中最小節點替代要刪除 的節點
//尋找要刪除節點的右子樹中索引最小的節點
Node successor = findMin(root.right);
//刪除要刪除節點的左子樹中的最小索引節點
successor.right = deleteMin(root.right);
successor.left = root.left;
return successor;
}
}
public Node findMin(Node root){
if(root.left != null)
return findMin(root.left);
return root;
}
二叉樹的先序、中序、後序遍歷
二叉樹的先序中序後序遍歷只需要分別在先序中序後序位置輸出節點信息就行了
//先序遍歷
public void preOrder(Node root){
if(root != null){
//先序位置輸出節點信息
System.out.print(root.key+"->");
preOrder(root.left);
preOrder(root.right);
}
}
//中序遍歷
public void inOrder(Node root){
if(root != null){
inOrder(root.left);
//中序位置輸出節點信息
System.out.print(root.key+"->");
inOrder(root.right);
}
}
//後序遍歷
public void postOrder(Node root){
if(root != null){
postOrder(root.left);
postOrder(root.right);
//後序位置輸出節點信息
System.out.print(root.key+"->");
}
}
二叉樹層次遍歷(廣度優先遍歷)
使用隊列作存放需要遍歷的樹節點,最開始將樹的根放入隊列中。在隊列非空的情況下,取出隊首的元素node , 然後將node的左右節點放入隊列中去(如果有的話),重複這個步驟直到樹中節點遍歷完。
//層次遍歷
public void levelOrder(Node root){
Queue<Node> queue = new LinkedList<Node>();
queue.add(root);
while(!queue.isEmpty()){
Node node = queue.poll();
System.out.print(node.key+"->");
if(node.left != null){
queue.add(node.left);
}
if(node.right != null){
queue.add(node.right);
}
}
}