java實現二插樹
產生原因:希望一種數據結構能同時具備數組查找快的優點以及鏈表插入和刪除快的優點,於是樹誕生了。
因爲手寫過鏈表,對於學習二插樹也很容易上手,主要就是爲了準備面試用的
- 首先把每個節點抽象成java對象
package com.dqw.tree;
/**
*
* @ClassName: Node
* @Description:TODO
* @author: 丁乾文
* @date: 2019年4月23日 上午10:31:51
*/
public class Node{
/**
* 節點數據
*/
private int data;
/**
* 左子節點的引用
*/
private Node leftChild;
/**
* 右子節點的引用
*/
private Node rightChild;
/**
* 是否被刪除
*/
private boolean isDelete;
public int getData() {
return data;
}
public void setData(int data) {
this.data = data;
}
public Node getLeftChild() {
return leftChild;
}
public void setLeftChild(Node leftChild) {
this.leftChild = leftChild;
}
public Node getRightChild() {
return rightChild;
}
public void setRightChild(Node rightChild) {
this.rightChild = rightChild;
}
public boolean isDelete() {
return isDelete;
}
public void setDelete(boolean isDelete) {
this.isDelete = isDelete;
}
}
- 對樹進行整刪查詢遍歷操作
package com.dqw.tree;
/**
*
* @ClassName: Tree
* @Description:TODO
* @author: 丁乾文
* @date: 2019年4月23日 上午10:30:23
*/
public class Tree {
/**
* 根節點
*/
public Node root;
/**
* 1.查找值比當前節點值大,則搜索右子樹;
2.查找值等於當前節點值,停止搜索(終止條件);
3.查找值小於當前節點值,則搜索左子樹;
* @Title: find
* @Description: TODO
* @param: @param key
* @param: @return
* @return: Node
* @throws
*/
public Node find(int key) {
Node current = root;
while (current != null) {
if (current.getData() > key) {// 當前值比查找值大,搜索左子樹
current = current.getLeftChild();
} else if (current.getData() < key) {// 當前值比查找值小,搜索右子樹
current = current.getRightChild();
} else {
if(current.isDelete()) {//被刪除的返回null
return null;
}
return current;
}
}
// 當整個樹遍歷完全,即current == null,那麼說明沒找到查找值,返回null。
return null;
}
/**
* 要插入節點,必須先找到插入的位置。與查找操作相似,由於二叉搜索樹的特殊性,
* 待插入的節點也需要從根節點開始進行比較,小於根節點則與根節點左子樹比較,
* 反之則與右子樹比較,直到左子樹爲空或右子樹爲空,則插入到相應爲空的位置 ,
* 在比較的過程中要注意保存父節點的信息 及待插入的位置是父節點的左子樹還是右子樹,
* 才能插入到正確的位置。 @Title: insert @Description:
* TODO @param: @param key @param: @return @return: boolean @throws
*/
public boolean insert(int data) {
Node newNode = new Node();
newNode.setData(data);
if (root == null) {//當前樹爲空樹,沒有任何節點
root = newNode;
return true;
} else {
Node current = root;
Node parentNode = null;
while (current != null) {
parentNode = current;
if (current.getData() > data) {// 當前值比插入值大,搜索左子節點
current = current.getLeftChild();
if (current == null) {// 左子節點爲空,直接將新值插入到該節點
parentNode.setLeftChild(newNode);
return true;
}
} else {//當前值比插入值小,搜索右子節點
current = current.getRightChild();
if (current == null) {// 右子節點爲空,直接將新值插入到該節點
parentNode.setRightChild(newNode);
return true;
}
}
}
}
return false;
}
/**
* 刪除節點
* @Title: delete
* @Description: TODO
* @param: @param key
* @param: @return
* @return: boolean
* @throws
*/
public boolean delete(int key) {
Node current = root;
Node parent = root;
boolean isLeftChild = false;
// 查找刪除值,找不到直接返回false
while (current.getData() != key) {
parent = current;
if (current.getData() > key) {
isLeftChild = true;
current = current.getLeftChild();
} else {
isLeftChild = false;
current = current.getRightChild();
}
if (current == null) {
return false;
}
}
// 如果當前節點沒有子節點
if (current.getLeftChild() == null && current.getRightChild() == null) {
if (current == root) {
root = null;
} else if (isLeftChild) {
parent.setLeftChild(null);
} else {
parent.setRightChild(null);
}
return true;
}else {
current.setDelete(true);//標記被刪除,不改變樹的順序,如果修改的話非常麻煩
}
return false;
}
/**
* 中序遍歷
* @Title: infixOrder
* @Description: TODO
* @param: @param current
* @return: void
* @throws
*/
public void infixOrder(Node current){
if(current != null){
infixOrder(current.getLeftChild());
System.out.print(current.getData()+" ");
infixOrder(current.getRightChild());
}
}
/**
* 前序遍歷
* @Title: preOrder
* @Description: TODO
* @param: @param current
* @return: void
* @throws
*/
public void preOrder(Node current){
if(current != null){
System.out.print(current.getData()+" ");
infixOrder(current.getLeftChild());
infixOrder(current.getRightChild());
}
}
/**
* 後序遍歷
* @Title: postOrder
* @Description: TODO
* @param: @param current
* @return: void
* @throws
*/
public void postOrder(Node current){
if(current != null){
infixOrder(current.getLeftChild());
infixOrder(current.getRightChild());
System.out.print(current.getData()+" ");
}
}
/**
* 找到最大值
* @Title: findMax
* @Description: TODO
* @param: @return
* @return: Node
* @throws
*/
public Node findMax() {
Node current = root;
Node maxNode = current;
while (current != null) {
maxNode = current;
current = current.getRightChild();
}
return maxNode;
}
/**
* 找到最小值
* @Title: findMin
* @Description: TODO
* @param: @return
* @return: Node
* @throws
*/
public Node findMin() {
Node current = root;
Node minNode = current;
while (current != null) {
minNode = current;
current = current.getLeftChild();
}
return minNode;
}
}
- 測試代碼
import com.dqw.tree.Tree;
/**
* 測試用
* @ClassName: Main
* @Description:TODO
* @author: 丁乾文
* @date: 2019年4月23日 上午10:34:58
*/
public class Main {
public static void main(String[] args) {
Tree tree = new Tree();
tree.insert(10);
tree.insert(15);
tree.insert(22);
tree.delete(22);
System.out.println(tree.find(22));
tree.postOrder(tree.root);
}
}