【二叉树】总结篇

  •    面对问题,理解了思路,但是没有任何想法的时候,不妨从n=1 n=2开始分析下,然后找到递推公式进而成功accept!
 
 
【二叉树的构建】
    • 已知前序和中序遍历序列可以确定这个二叉树。
    • 已知中序和后序遍历序列可以确定这个二叉树。
    • 层次遍历和后序遍历也可以确定二叉树。
    • 二叉排序树和其他遍历序列的结合可以确定二叉树。
 
构建的思路是:
    因为树的定义,本身就是一个递归的定义,那么由遍历序列构建树的时候,解决问题的思路往往就是由已知条件,
找出树的根节点,然后把大问题,划分成小的问题,现在小的问题是,左右两个子树的问题,返现左右两个子树和原问题是一模一样的,
所以可以用递归来解决问,联系子问题和大问题的纽带是当前这颗树的根节点。
递归结束条件是子问题里面只剩下一个节点的情况。
 
 
【二叉树的遍历】
 
二叉树的问题好多本质上是二叉树的遍历问题。深入理解递归遍历和迭代遍历的流程是解决问题的关键。
二叉树的前序、中序、后序遍历都可以看成是DFS,即深度优先遍历,共有3!=6种DFS方法,
其他的三种是root->r->l, r->root->l,r->l->root。注意不要小看这三种不常见的DFS。威力无穷而且代码短小。
尤其是root->r->l这种深度遍历经常用到,后面的两种r->root->l,r->l->root不经常用到,管理是理解这中遍历本质上都是DFS。
二叉树的镜像问题,以及两个二叉树的对比问题,用这种DFS代码短小简洁。
 

root->r->l先遍历根节点,然后在遍历这个根节点的右子树的根节点,然后递归对右子树做遍历,

遍历完事儿之后再递归遍历左子树。注意这种遍历方法很常用。

 

前序,中序,后序遍历的非递归实现都是用栈实现的,root->r->l的非递归实现也是用栈实现的。其实只不过说递归用的是系统栈而已。

二叉树的层次遍历是用队列实现的。

 
 
 
【二叉树的递归】
 
    二叉树本身就是一个递归的数据结构,因此往往关于二叉树的问题都能用递归的方法来解决,其实也可以借助队列或者栈用迭代来解决。
递归一定是深度搜索,二叉树的遍历除了层次遍历以外其他的都是深度搜索,
 
 
【二叉查找树】
 
二叉查找树,第一个要想到的是中序遍历,因为中序遍历的结果是有序的。
 

提到二叉查找树,就得想到二叉查找树的递归定义,左子树的节点值都小于根节点,右子树的节点值都大于根节点。

 
二叉查找树的规律,
有二叉查找树,延伸出AVL树,和红黑树,后两者都是自平衡的二叉查找树。
 
 
根据二叉查找树的定义,找规律的问题,实质上是一个递推的问题(当然可以递推来求解,也可以迭代来求解),
 
二叉查找树(Binary Search Tree),
也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树: 
    若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
    任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
    任意节点的左、右子树也分别为二叉查找树。
    没有键值相等的节点(no duplicate nodes)。
二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低。为O(log n)。
二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、multiset、关联数组等。
 
 
AVL 是自平衡的二叉查找树
在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,
所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。
 
 
红黑树(可以当一个堆用)
mutiset 就是红黑树实现的,mutiset允许值重复,
 
红黑树是一种自平衡二叉查找树,是在计算机科学中用到的一种数据结构,典型的用途是实现关联数组。
但它的操作有着良好的最坏情况运行时间,并且在实践中是高效的: 它可以在O(log n)时间内做查找,插入和删除,这里的n是树中元素的数目。
 
虽然mutiset使用红黑树(一种自平衡的二叉查找树)实现的,是可以当作一个堆来使用的效率很高,一下代码模拟了入堆和出堆的过程。
大顶堆:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
#include <iostream>
#include <set>
using namespace std;

int main()
{
    //初始化数据到红黑树中,
    int num[] = {35216487};
    multiset<int, greater<int> > intMultiSet;
    for (int i = 0; i < 8; ++i)
    {
        intMultiSet.insert(num[i]);
    }

    while(!intMultiSet.empty())
    {
        multiset<int, greater<int> >::iterator iterGreatest = intMultiSet.begin();
        cout << *iterGreatest << " ";
        intMultiSet.erase(iterGreatest);
    }
    cout << endl;
    return 0;
}
 
输出:8 7 6 5 4 3 2 1
 
小顶堆:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 
#include <iostream>
#include <set>
using namespace std;

int main()
{
    //初始化数据到红黑树中,
    int num[] = {35216487};
    multiset<int, less<int> > intMultiSet;
    for (int i = 0; i < 8; ++i)
    {
        intMultiSet.insert(num[i]);
    }

    while(!intMultiSet.empty())
    {
        multiset<int, less<int> >::iterator iterSmallest = intMultiSet.begin();
        cout << *iterSmallest << " ";
        intMultiSet.erase(iterSmallest);
    }
    cout << endl;
    return 0;
}

输出:1 2 3 4 5 6 7 8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/codemylife/p/3652410.html