二叉树
- 二叉树的每个元素都恰好有两颗子树(可以是一颗或者为空)
- 二叉树中每个元素的子树是有顺序的,二叉树可以为空
- 二叉树有n个元素,有n-1条边
- 二叉树的高度是h,则至少有h个元素,至多有2^h-1个数据,此时称为满二叉树
- 从二叉树中删除编号为2^h-i个元素,称为完全二叉树
- 完全二叉树的重要特性:1)i=1,根;2)2i>n,该元素无左子树;3)2i+1>n,该元素无右子树
- 根节点和任一节点之间有唯一路径
- 根节点到任一节点的路径长度是该节点的深度,根节点深度永远是0
- 节点至最深节点的路径长度是该节点的高度
- 根节点的高度就是整棵树的高度
二叉树有四种遍历方法:
中序遍历是我们通常的书写形式,
前序遍历
1 | template <class T> |
中序遍历
1 | template <class T> |
后序遍历
1 | template <class T> |
层次遍历
在同一层中从左到右访问树的元素1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18template <class T>
void levelOrder(binaryTreeNode<T> *t)
{
arrayQueue<binaryTreeNode<T>*> q;
while(t!=NULL)
{
visit(t);
if(t->leftChild!=NULL)
q.push(t->leftChild);
if(t->rightChild!=NULL)
q.push(t->rightChild);
try{t=q.front();}
catch(queueEmpty) {return;}
q.pop();
}
}
visit函数
1 | template <class T> |
二叉搜索树BST
- 根节点>左节点 && 根节点<右节点
- 二叉树搜索树的中序遍历可以实现排序 ->amazing!
可以运行的四种遍历方法、二叉搜索树、获取树的高度和二叉搜索树的最大值
1 | #include <iostream> |
平衡二叉搜索树
- 增加不同的平衡条件,二叉搜索树会表现出不同的效率
- 根节点的左子树的左子节点和右子树的右子节点为外侧,左子树的右子节点和右子树的左子节点为内侧
- 插入点位于外侧,可以采用单旋转操作;插入点位于内侧,可以采用双旋转操作
- AVL tree条件:任何节点的左右子树高度最多相差1,即保证对数深度保持平衡
RB-tree(红黑树)
- 红黑树的规则
- 根节点是黑色的
- 如果节点为红,则子节点必须为黑
- 任一节点至树尾端的任何路径,所含的黑节点数必须相同
- 新增节点必须为红,新增节点的父节点必须为黑,如果不能符合上述条件就必须调整颜色并旋转数型
- 认为NULL节点为黑色
- 红黑树插入节点
- 红黑树数据结构中有一个parent指针上溯到父节点
- 成员函数
- get_node() 产生一个节点空间
- put_node()
- clone_node() 配置空间构造内容
- destory_node() 析构内容释放内存
- root() 根节点
- minimum() 求取极小值
- maximum() 求取极大值
- begin() 红黑树最左边最小的节点
- end() 红黑树的终点为header所指处
- empty()
- size()
- max_size() return size_type(-1)
- insert_unique() 将x插入到红黑树中,保持节点独一无二
- insert_equal() 将x插入到红黑树中,允许节点重复
- find() 寻找红黑树中键值为k的节点
红黑树的构造
1
2
3
4
5
6
7
8
9rb_tree<int, int, identity<int>, less<int>> itree; //指定节点的键值、实值大小比较标准
rb_tree(const Compare& comp=Compare()) : node_count(0), key_compare(comp) {init();}
void init() {
header = get_node(); //产生一个节点空间,令header指向它
color(header) = __rb_tree_red; //令header为红色
root=0;
leftmost()=header;
rightmost()=header;
}真正执行插入操作的函数
__insert(base_ptr x_. base_ptr y_, const Value& v); //x_是新值插入点,参数y_是插入点的父节点,参数v是新值
- 调整红黑树,将树的状态调整到符合红黑树的要求,重新令树形平衡,x是新增节点
inline void __rb_tree_rebalance(__rb_tree_node_base* x, __rb_tree_node_base*& root)
- 左旋函数和右旋函数,新增节点必须是红节点,如果插入处的父节点也是红色,需要树形旋转
inline void __rb_tree_rotate_left(__rb_tree_node_base* x, __rb_tree_node_base*& root);
inline void __rb_tree_rotate_right(__rb_tree_node_base* x, __rb_tree_node_base*& root);