二叉树:结构类似树。
节点:二叉树的元素。
根节点:二叉树中的第一个元素。
子节点,父节点,兄弟节点,叶子节点,左子节点,右子节点
节点的3个概念(根节点到叶子节点的最长路径计算):
高度:3,2,1,0
深度:0,1,2,3
层:1,2,3,4
树的高度等于根节点的高度。
满二叉树:1,叶子节点都在底层;2,除了叶子节点外,所有节点都有左右子节点。
完全二叉树:1,叶子节点都在最底2层;2,最后一层叶子节点都在左边;3,除了最后一层,其他叶子节点都达到最
大。
二叉树存储结构:基于链表的链式存储法,基于数组的顺序存储法。
二叉树的3种遍历,打印顺序:
前序: 节点本身→左子树→右子树
中序:左子树→节点本身→右子树
后序:左子树→右子树→节点本身
前序遍历的递推公式:
preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)
中序遍历的递推公式:
inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)
后序遍历的递推公式:
postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r
前序遍历(Java递归实现):
public static void recursion(Node node) {// 前序遍历
if (node == null) {
return;
}
System.out.println(node.value);
recursion(node.left);
recursion(node.right);
}
遍历的时间复杂度为O(n)
Java实现二叉树的CRUD
public class BinaryTree {
private static class Node {
int key;// 节点key
Object value;// 节点value
Node left;// 左节点
Node right;// 右节点
public Node(int key, Object value) {// 带参数构造函数
this.key = key;
this.value = value;
}
}
private Node data;// 根节点
public Object get(int key) {// 根据key查找value
if (null == data) {
return null;
}
if (key == data.key) {// 如果key等于根节点
return data.value;
}
Node temp = this.data;
while (temp != null) {// 循环二叉树的左右节点,查找key相等的value
if (temp.key > key) {
temp = temp.left;
} else if (temp.key < key) {
temp = temp.right;
} else {
return temp.value;
}
}
return null;
}
public void put(int key, Object value) {// 给二叉树添加元素
if (data == null) {// 根节点的情况
data = new Node(key, value);
} else {
Node temp = this.data;
while (temp != null) {
if (key > temp.key) {// key大于节点key,并且节点的有子节点为null,则右子节点添加元素。
if (temp.right == null) {
temp.right = new Node(key, value);
return;
}
temp = temp.right;
} else if (key < temp.key) {
if (temp.left == null) {
temp.left = new Node(key, value);
return;
}
temp = temp.left;
} else {// 相等就更新(可以考虑修改为可以重复元素:1,同一个节点存入多个key,value;2
,继续遍历在下一个子节点添加元素)
temp.value = value;
return;
}
}
}
}
public void delete(int key) {// 根据key删除元素
if (data == null) {
return;
}
Node temp = data;// 删除节点位置
Node tempParent = null;// temp的父节点
while (temp != null && temp.key != key) {// 获取需要删除的节点位置
tempParent = temp;
if (key > temp.key) {
temp = temp.right;
} else {
temp = temp.left;
}
}
if (temp == null) {// 如果删除的元素不存在。
return;
}
// 目标节点有左右节点的情况,把右节点的最小子节点和当前节点换位置,并删除右节点的最小节点。
if (temp.right != null && temp.left != null) {
Node minParent = temp;
Node min = temp.right;
while (min.left != null) {// 循环获取右节点的最小子节点
minParent = min;
min = min.left;
}
temp.value = min.value;// 取右节点的最小子节点的值赋给当前节点
// 后续的删除操作就是删除min了。
temp = min;
tempParent = minParent;
}
Node child = null;// temp的孩子
if (temp.left != null) {// 如果要删除的节点只有左节点,我们只需要直接将父节点指向要删除节点的
左节点
child = temp.left;
} else if (temp.right != null) {
child = temp.right;
} else {
// 如果要删除的节点没有子节点,我们只需要直接将父节点指向null
}
// 删除temp操作: 就是temp的父节点指向temp的子节点。
if (tempParent == null) {// 删除根节点
data = null;
} else if (temp == tempParent.left) {// 删除的节点是父节点的左节点
tempParent.left = child;
} else if (temp == tempParent.right) {
tempParent.right = child;
}
}
/*
前序遍历的递推公式:
preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)
中序遍历的递推公式:
inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)
后序遍历的递推公式:
postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r
*/
public static void recursion(Node node) {// 前序遍历
if (node == null) {
return;
}
System.out.println(node.value);
recursion(node.left);
recursion(node.right);
}
public static void main(String[] args) {
BinaryTree binaryTree = new BinaryTree();
binaryTree.put(3, "c");
binaryTree.put(4, "d");
binaryTree.put(5, "e");
binaryTree.put(6, "f");
binaryTree.delete(4);
System.out.println(binaryTree.get(4));
System.out.println(binaryTree.get(6));
recursion(binaryTree.data);//遍历输出二叉树的value
}
}
平衡二叉查找树:二叉树的任意节点的左右子树的高度差距不能大于1。
红黑树定义:
1,根节点时黑色的
2,所有叶子结点为NULL,就是不存数据
3,红色节点不能相邻,就是要被黑色节点隔开
4,每个节点到所有黑色的叶子结点的路径时一样的,红色的节点不算
红黑树就是平衡二叉树,为了减少查询的时间复杂度。红黑树的查找时间复杂度为O(n)。