1. 为什么使用二叉树
为什么使用树?因为二叉树通常结合两种数据结构的有点:有序数组,链表。在树中查找数据和有序数组一样快,在树中删除数据,添加数据和链表一样快。有序数组中,插入数据很慢,链表中查找数据太慢。
1)二叉树和有序数组的查找,都是二分对半查找,复杂度为logN;
2)如果二分查找是两半都查找,则复杂度为NlogN;
2. 树的基本术语
1)根:也叫根节点,最上面那个节点。一棵树只有一个根。
2)父节点
3)子节点
4)叶子节点:叶子节点下面不再有节点。
5)子树
6)层:根叫做第0层。
3. 二叉树
树中每个节点最多只有两个子节点,这样的树称为二叉树。二叉树左子节点小于父节点,右子节点大于等于父节点。
4. 二叉树实现
4.1 Node类
树的每个节点均包含当前节点的数据;除叶子节点以外的其他节点均包含对其子节点的引用。
// 节点类
class Node {
Node left;
Node right;
int id;
double height;
}
4.2 Tree类
单链表操作的核心是头结点,二叉树操作的核心就是根节点,因为只有根节点可以直接访问;因此二叉树的成员变量就是根节点。同时二叉树要求能够查找,插入和删除。
// 二叉树类
class BinaryTree {
private Node root;
public void find(int id) {}
public void insert(int id, double dd) {}
public void delete(int id) {}
}
4.2.1 插入节点
需要三个节点引用,newNode引用传入的节点;currentNode用来遍历树以寻找插入位置,这个节点最终会遍历到null位置;father节点用来引用currentNode的父节点,当currentNode指向null时,使father.left节点引用newNode节点。
public void insert(int id, double height) {
Node newNode = new Node();
newNode.id = id;
newNode.height = height;
if (root == null)
root = newNode;
else {
Node father;
Node currentNode = root;
while (currentNode != null) {
father = currentNode;
if (id < currentNode.id) {
currentNode = currentNode.left;
if (currentNode == null) {
father.left = newNode;
return;
}
}
else {
currentNode = currentNode.right;
if (currentNode == null) {
father.right = newNode;
return;
}
}
}
}
}
4.2.2 查找节点
用一个节点引用root节点,然后二分查找就是了。
public Node find(int id) {
Node currenNode = root;
// 循环查找
while (currenNode.id != id) {
if (id < currenNode.id)
currenNode = currenNode.left;
else
currenNode = currenNode.right;
if (currenNode == null)
return null;
}
return currenNode;
}
4.2.3 遍历树
二叉树的遍历总共四种方式:先根,中根,后根,按层遍历。二叉树最常用的是中根遍历。遍历树的最简单的方法是递归。
先根遍历:ABDFGHIEC
1)访问当前节点;
2)调用自身访问左子树;
4)调用自身访问右子树;
中根遍历:
1
3)后根:
4)按层遍历: