介紹
使用Java實現一個int值類型的排序二叉樹
二叉樹
二叉樹是一個遞歸的數據結構,每個節點最多有兩個子節點。
通常二叉樹是二分查找樹,每個節點它的值大於或者等於在它左子樹節點上的值,小於或者等於在它右子樹節點上的值,如下圖
為了實現二叉樹,我們使用一個Node類來表示節點,節點存儲int類型的值,還有對子節點的引用。
package com.java.node.BinaryTree;
public class Node {
int data;
Node left;
Node right;
public Node(int data) {
this.data = data;
this.left = null;
this.right = null;
}
}
然后添加樹的root節點
package com.java.node.BinaryTree;
public class BinaryTree {
Node root;
}
通常的操作
添加節點
首先我們必須找到新節點的位置,是為了保持樹排序。我們必須從root節點開始,必須遵循下面的規則:
- 如果新節點小於當前的值,我們將會進入左子樹
- 如果新節點大於當前的節點。我們將會進入右子樹
- 當當前的節點是null時,我們已經到達葉子節點,我們可以添加新節點到這個位置。
我們將會創建遞歸方法做添加節點操作
private Node addNode(Node current, int value) {
if (current == null) {
return new Node(value);
}
if (value < current.data) {
current.left = addNode(current.left, value);
} else if (value > current.data) {
current.right = addNode(current.right, value);
} else {
return current;
}
return current;
}
public void addNode(int value) {
root = addNode(root, value);
}
可以使用方法創建一個二叉樹了
public BinaryTree createBinaryTree() {
BinaryTree bt = new BinaryTree();
bt.addNode(6);
bt.addNode(4);
bt.addNode(8);
bt.addNode(10);
return bt;
}
查找一個節點
private boolean containNode(Node current, int value) {
if (current == null) {
return false;
}
if (value == current.data) {
return true;
}
return value < current.data ? containNode(current.left, value) : containNode(current.right, value);
}
public boolean containNode(int value) {
return containNode(root, value);
}
刪除一個節點
private Node deleteNode(Node current, int value) {
if (current == null) {
return null;
}
if (value == current.data) {
if (current.left == null && current.right == null) {
return null;
}
if (current.left == null) {
return current.right;
}
if (current.right == null) {
return current.left;
}
int smallestValue = findSmallestValue(current.right);
current.data = smallestValue;
current.right = deleteNode(current.right, smallestValue);
return current;
}
if (value < current.data) {
current.left = deleteNode(current.left, value);
return current;
}
current.right = deleteNode(current.right, value);
return current;
}
private int findSmallestValue(Node root) {
return root.left == null ? root.data : findSmallestValue(root.right);
}
遍歷樹
我們將以不同的方式遍歷樹,以depth-first,breadth-first方式遍歷樹。
以Depth-First遍歷樹
Depth-first查詢是一種在查詢兄弟節點之前,盡可能的查詢每個子節點。
in-order,pre-order,post-order方式都是以depth-first方式遍歷樹的。
in-order遍歷是首先遍歷左子樹,然后root節點,最后是右子樹。
public void traverseInOrder(Node root) {
if (root != null) {
traverseInOrder(root.left);
System.out.println(root.data);
traverseInOrder(root.right);
}
}
pre-order遍歷首先是root節點,然后是左子樹,最后是右子樹。
public void traversePreOrder(Node root) {
if (root != null) {
System.out.println(root.data);
traversePreOrder(root.left);
traversePreOrder(root.right);
}
}
post-order遍歷首先是遍歷左子樹,然后是右子樹,最后是root節點。
public void traversePostOrder(Node root) {
if (root != null) {
traversePostOrder(root.left);
traversePostOrder(root.right);
System.out.println(root.data);
}
}
以Breadth-First遍歷
它在遍歷下一級的節點之前,會遍歷當前級的所有節點。
這種類型的遍歷也叫做level-order,遍歷樹從root節點開始,從左到右。
為了實現,使用隊列來存儲每個級別的節點。我們將會從列表中獲取每個節點。然后添加他的子節點到隊列中。
public void traverseLevelOrder(Node root) {
if (root == null) {
return;
}
Queue<Node> nodes = new LinkedList<Node>();
nodes.add(root);
while(!nodes.isEmpty()) {
Node node = nodes.remove();
System.out.println(node.data);
if (node.left != null) {
nodes.add(node.left);
}
if (node.right != null) {
nodes.add(node.right);
}
}
}