二叉樹是一種非常重要的數據結構,它同時具有數組和鏈表各自的特點:它可以像數組一樣快速查找,也可以像鏈表一樣快速添加。但是他也有自己的缺點:刪除操作復雜。
我們先介紹一些關於二叉樹的概念名詞。
二叉樹:是每個結點最多有兩個子樹的有序樹,在使用二叉樹的時候,數據並不是隨便插入到節點中的,一個節點的左子節點的關鍵值必須小於此節點,右子節點的關鍵值必須大於或者是等於此節點,所以又稱二叉查找樹、二叉排序樹、二叉搜索樹。
完全二叉樹:若設二叉樹的高度為h,除第 h 層外,其它各層 (1~h-1) 的結點數都達到最大個數,第h層有葉子結點,並且葉子結點都是從左到右依次排布,這就是完全二叉樹。
滿二叉樹——除了葉結點外每一個結點都有左右子葉且葉子結點都處在最底層的二叉樹。
深度——二叉樹的層數,就是深度。
二叉樹的特點總結:
(1)樹執行查找、刪除、插入的時間復雜度都是O(logN)
(2)遍歷二叉樹的方法包括前序、中序、後序
(3)非平衡樹指的是根的左右兩邊的子節點的數量不一致
(4) 在非空二叉樹中,第i層的結點總數不超過 , i>=1;
(5)深度為h的二叉樹最多有個結點(h>=1),最少有h個結點;
(6)對於任意一棵二叉樹,如果其葉結點數為N0,而度數為2的結點總數為N2,則N0=N2+1;
二叉樹的Java代碼實現
首先是樹的節點的定義,下面的代碼中使用的是最簡單的int基本數據類型作為節點的數據,如果要使用節點帶有更加復雜的數據類型,換成對應的對象即可。
/**
*
* @ClassName: com.tree.TreeNode
* @Description: 節點
* @author zhaokaiqiang
* @date 2014-12-5 下午4:43:24
*
*/
public class TreeNode {
// 左節點
private TreeNode lefTreeNode;
// 右節點
private TreeNode rightNode;
// 數據
private int value;
private boolean isDelete;
public TreeNode getLefTreeNode() {
return lefTreeNode;
}
public void setLefTreeNode(TreeNode lefTreeNode) {
this.lefTreeNode = lefTreeNode;
}
public TreeNode getRightNode() {
return rightNode;
}
public void setRightNode(TreeNode rightNode) {
this.rightNode = rightNode;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public boolean isDelete() {
return isDelete;
}
public void setDelete(boolean isDelete) {
this.isDelete = isDelete;
}
public TreeNode() {
super();
}
public TreeNode(int value) {
this(null, null, value, false);
}
public TreeNode(TreeNode lefTreeNode, TreeNode rightNode, int value,
boolean isDelete) {
super();
this.lefTreeNode = lefTreeNode;
this.rightNode = rightNode;
this.value = value;
this.isDelete = isDelete;
}
@Override
public String toString() {
return "TreeNode [lefTreeNode=" + lefTreeNode + ", rightNode="
+ rightNode + ", value=" + value + ", isDelete=" + isDelete
+ "]";
}
}
下面給出二叉樹的代碼實現。由於在二叉樹中進行節點的刪除非常繁瑣,因此,下面的代碼使用的是利用節點的isDelete字段對節點的狀態進行標識
/**
*
* @ClassName: com.tree.Tree
* @Description: 二叉樹的定義
* @author zhaokaiqiang
* @date 2014-12-8 上午7:51:49
*
*/
public class BinaryTree {
// 根節點
private TreeNode root;
public TreeNode getRoot() {
return root;
}
/**
* 插入操作
*
* @param value
*/
public void insert(int value) {
TreeNode newNode = new TreeNode(value);
if (root == null) {
root = newNode;
root.setLefTreeNode(null);
root.setRightNode(null);
} else {
TreeNode currentNode = root;
TreeNode parentNode;
while (true) {
parentNode = currentNode;
// 往右放
if (newNode.getValue() > currentNode.getValue()) {
currentNode = currentNode.getRightNode();
if (currentNode == null) {
parentNode.setRightNode(newNode);
return;
}
} else {
// 往左放
currentNode = currentNode.getLefTreeNode();
if (currentNode == null) {
parentNode.setLefTreeNode(newNode);
return;
}
}
}
}
}
/**
* 查找
*
* @param key
* @return
*/
public TreeNode find(int key) {
TreeNode currentNode = root;
if (currentNode != null) {
while (currentNode.getValue() != key) {
if (currentNode.getValue() > key) {
currentNode = currentNode.getLefTreeNode();
} else {
currentNode = currentNode.getRightNode();
}
if (currentNode == null) {
return null;
}
}
if (currentNode.isDelete()) {
return null;
} else {
return currentNode;
}
} else {
return null;
}
}
/**
* 中序遍歷
*
* @param treeNode
*/
public void inOrder(TreeNode treeNode) {
if (treeNode != null && treeNode.isDelete() == false) {
inOrder(treeNode.getLefTreeNode());
System.out.println("--" + treeNode.getValue());
inOrder(treeNode.getRightNode());
}
}
}
在上面對二叉樹的遍歷操作中,使用的是中序遍歷,這樣遍歷出來的數據是增序的。
下面是測試代碼:
public class Main {
public static void main(String[] args) {
BinaryTree tree = new BinaryTree();
// 添加數據測試
tree.insert(10);
tree.insert(40);
tree.insert(20);
tree.insert(3);
tree.insert(49);
tree.insert(13);
tree.insert(123);
System.out.println("root=" + tree.getRoot().getValue());
// 排序測試
tree.inOrder(tree.getRoot());
// 查找測試
if (tree.find(10) != null) {
System.out.println("找到了");
} else {
System.out.println("沒找到");
}
// 刪除測試
tree.find(40).setDelete(true);
if (tree.find(40) != null) {
System.out.println("找到了");
} else {
System.out.println("沒找到");
}
}
}
二叉樹的常見問題及其解決程序 http://www.linuxidc.com/Linux/2013-04/83661.htm
【遞歸】二叉樹的先序建立及遍歷 http://www.linuxidc.com/Linux/2012-12/75608.htm
在JAVA中實現的二叉樹結構 http://www.linuxidc.com/Linux/2008-12/17690.htm
【非遞歸】二叉樹的建立及遍歷 http://www.linuxidc.com/Linux/2012-12/75607.htm
二叉樹遞歸實現與二重指針 http://www.linuxidc.com/Linux/2013-07/87373.htm
二叉樹先序中序非遞歸算法 http://www.linuxidc.com/Linux/2014-06/102935.htm
輕松搞定面試中的二叉樹題目 http://www.linuxidc.com/linux/2014-07/104857.htm