1、树

分析HashMap源码的时候,看到JDK8中链表的节点个数超过了泊松分布计算得出的8个节点时,链表将会被转化为红黑树,所以,在分享HaspMap的源码分析文章前,先来分享一下树的数据结构的相关知识。

概念

英文

tree

节点

node

edge

儿子

child

父亲

parent

root

树叶

leaf

兄弟

siblings

祖父

grandparent

孙子

grandchild

祖先

ancestor

后裔

descendant

真祖先

proper ancestor

真后裔

proper descendant

概念

英文

解释

节点到节点的路径

path

路径是节点到节点间所有节点组成的序列

路径的长

length

路径的长是路径上所有边的条数

节点的深度

depth

从根到节点的唯一路径的长

节点的高

height

节点到一片树叶最长路径的长

对数

对数是对求幂的逆运算

如果a的x次方等于N(a>0,且a不等于1),那么数x叫做以a为底N的对数(logarithm),记作x=logaN。其中,a叫做对数的底数,N叫做真数。

1.1、树的实现

将每个节点的所有儿子都放在树节点的链表中。

树的实现

箭头方向

英文

向下箭头

第一儿子

firstChild

水平箭头

下一兄弟

nextSibling

1.2、树的应用-文件目录

目录

文件名

节点

/

遍历

解释

英文

先序遍历

对节点的处理工作是在节点的所有儿子被处理之前进行的

preorder traversal

后续遍历

对节点的处理工作是在节点的所有儿子被处理之后进行的

postorder traversal

2、二叉树

概念

英文

二叉树

binary tree

平均/平衡二叉树

Balanced Binary Tree

二叉排序/查找/搜索树

binary search/sort tree

二叉树

每个节点都不能多于2个儿子的树

2.1、二叉树的实现

节点是由element元素的信息,加上两个到其他节点的引用left和right组成的结构。

class BinaryNode{
Object element;
BinaryNode left;
BinaryNode right;
}

2.2、二叉树的应用-表达式树

表达式树expression tree的树叶是操作数operand,其他的节点为操作符operator。

中序遍历:左、节点、右。

构造表达式树输入:a b + c d e + * *输出:

二叉树BT与二叉查找树BST概览_二叉树

3、二叉查找树 BST

查找树的ADT/Abstract Data Type/抽象数据类型,二叉排序/查找/搜索树。

二叉排序/查找/搜索树

空树或
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的结点。

平均深度,O(log N)

二叉树BT与二叉查找树BST概览_数据结构_02

二叉查找树实现:

public class BinarySearchTree<T extends Comparable<T>> {
//二叉查找树根节点
private BinaryNode<T> root;


//二叉树节点定义
private static class BinaryNode<T extends Comparable<T>> {

T element; //节点值
BinaryNode<T> left; //左节点
BinaryNode<T> right; //右节点

public BinaryNode(T key) {
this(key, null, null);
}

public BinaryNode(T element, BinaryNode<T> left, BinaryNode<T> right) {
this.element = element;
this.left = left;
this.right = right;
}
}
}

查找是否存在:

/**
* 查找是否存在
*
* @param search
* @param root
* @return
*/
private boolean contains(T search, BinaryNode<T> root) {
if (root == null) {
return false;
}

int compareResult = search.compareTo(root.element);

if (compareResult < 0) {
return contains(search, root.left);
} else {
return contains(search, root.right);
}
}

查找最小值:

/**
* 查找最小值
*
* @param root
* @return
*/
private BinaryNode<T> findMin(BinaryNode<T> root) {

if (root == null) {
return null;
}

if (root.left == null) {
return root;
}

return findMin(root.left);
}

查找最大值:

/**
* 查找最大值
*
* @param root
* @return
*/
private BinaryNode<T> findMax(BinaryNode<T> root) {

if (root == null) {
return null;
}

if (root.right == null) {
return root;
}

return findMax(root.right);
}

插入值:

/**
* 插入值
*
* @param insert
* @param root
* @return
*/
private BinaryNode<T> insert(T insert, BinaryNode<T> root) {

if (root == null) {
return new BinaryNode<T>(insert, null, null);
}

int compareResult = insert.compareTo(root.element);
if (compareResult < 0) {
root.left = insert(insert, root.left);
} else if (compareResult > 0) {
root.right = insert(insert, root.right);
}

return root;
}

删除值:

/**
* 删除值
* 如果是树叶,直接删除
* 如果有一个儿子:该节点在其父节点调整自己的链以绕过该节点后被删除
* 如果有两个儿子:用该节点右子树的最小的数据代替该节点的数据,并递归地删除该节点
*
* @param remove
* @param root
* @return
*/
private BinaryNode<T> remove(T remove, BinaryNode<T> root) {
if (root == null) {
return root;
}

int compareResult = remove.compareTo(root.element);
if (compareResult < 0) {
root.left = remove(remove, root.left);
} else if (compareResult > 0) {
root.left = remove(remove, root.right);
} else if (root.left != null && root.right != null) {//两个儿子
root.element = findMin(root.right).element;
root.right = remove(root.element, root.right);
} else {
root = (root.left != null) ? root.left : root.right;
}
return root;
}

前序遍历:

/**
* 前序遍历
* @param node 待遍历二叉查找树BST根节点
*/
private void preOrder(BinaryNode<T> node) {
if (node != null) {
System.out.print(node.key + " ");
preOrder(node.left);
preOrder(node.right);
}
}

中序遍历:

/**
* 中序遍历
* @param node 待遍历BST根节点
*/
private void midOrder(BinaryNode<T> node) {
if (node != null) {
midOrder(node.left);
System.out.print(node.key + " ");
midOrder(node.right);
}
}

后序遍历:

/**
* 中序遍历
* @param node 待遍历BST根节点
*/
private void midOrder(BinaryNode<T> node) {
if (node != null) {
midOrder(node.left);
System.out.print(node.key + " ");
midOrder(node.right);
}
}

4、AVL树

平均二叉/平衡二叉/AVL树

空树或每个节点的左右两子树高度差绝对值<=1的二叉查找树,每个节点的左右两子树都是平衡二叉树。
AVL树/Adelson-Velskii和Landis树是带有平衡条件的二叉查找树。
空树的高度定义为-1。
平衡条件必须要容易保持,它保证了树的深度须是
平均深度,O(根号N)

二叉树BT与二叉查找树BST概览_查找树_03

待续……

下一次树的分享将继续讲AVL树、伸展树、B树以及红黑树的相关知识……

欢迎关注Android技术堆栈,专注于Android技术学习的公众号,致力于提高Android开发者们的专业技能!

二叉树BT与二叉查找树BST概览_数据结构_04