zoukankan      html  css  js  c++  java
  • 数据结构---树---总结

    一,一些定义

    树的深度定义:对于树中的节点n(i),n(i)的深度定义为,从根到n(i)的唯一路径的长度。

    树的高度定义:对于树中的节点n(i),n(i)的高度定义为,从n(i)到树中叶子节点的最长路径的长度。因为树中可能有多个叶子结点,n(i)到每个叶子结点都会有路径,路径最长的即为n(i)的高度。

    二,表达式树

    表达式树的树叶是操作数,非叶结点是操作符。

    表达式树可用来进行表达式求值。对表达式树中序遍历,就会得到一个符合人类习惯的表达式,这是一个中缀表达式。关于中缀表达式,参考:  

    对表达式树后序遍历,就得到一个后缀表达式,关于后缀表达式,参考:

    那,如何构造表达式树呢?

    即:给定一个后缀表达式,如何将之转换成中缀表达式?---后缀表达式转换成中缀表达式的过程,即为构造表达式树的过程。

    幸运的是:后缀表达式转换成中缀表达式的过程 与 后缀表达式求值的过程非常相似。

    算法如下:

    输入:后缀表达式

    输出:(表达式树)中缀表达式

    扫描后缀表达式,一次读入一个符号

    ①若它是操作数,则建立一个单节点树并将它推入栈中

    ②若它是操作符,则从栈中弹出两颗树T1(先弹出) 和 T2。该树的树根就是操作符,左、右儿子分别是T2 和 T1,然后再将该树压入栈中。

    代码如下:

    另外一篇博客--链接

    三,查找树---二叉查找树

    二叉查找树:对于树中每个节点X,它的左子树所有项的值小于X,它的右子树所有项的值大于X。中序遍历二叉查找树 生成一个有序序列。

    二叉查找树的特点:让很多操作都可以在O(logN)的时间内完成。注意,我这里说的是 “可以”,因为:二叉查找树并不是平衡二叉树。

    插入操作:

    比如,当序列是有序的时,二叉查找树就退化成链表。

    例如:1,2,3,4,5作为输入,构造二叉查找树

    对于1,作为树的根结点。对于2,作为根结点的右孩子。对于3,作为2的右孩子。对于4,作为3的右孩子,对于5,作为4的右孩子。

    这样的二叉查找树的高度为O(N)。 那么相关的操作也降为O(N)

    删除操作:

    当删除二叉查找树中的某个节点时,不通改变二叉查找树的特点。故,一般采用如下方式删除:

    不直接删除该节点,而是删除以该节点为根的左子树中的最右下节点, 或者删除以该节点为根的,右子树中的最左下节点。

    由于删除操作可能会改变二叉查找树的高度,如果总是删除”最右下节点“ 或者 ”最左下节点“ 会导致节点严重偏向一边,故可采用随机删除法,即随机地选择”最右下节点“ 或 ”最左下节点“删除。

    现在考虑以下几种操作,及它们采用不同的数据结构实现时的时间复杂度情况:

    findMin   二叉查找树--O(logN);  线性表--O(N); HashSet--O(N)

    HashSet可以遍历每个Entry,然后找出最小的,故时间复杂度为O(N)

    findMax  二叉查找树--O(logN);  线性表--O(N); HashSet--O(N)

    如果数组有序,findMax操作可为O(1)。但是对于链表而言,findMax只能为O(N)

    insert   二叉查找树--O(logN);  线性表--O(N); HashSet--O(1)

    在数组中插入时,需要移动元素,平均时间复杂度为O(N)。但对于链表,插入操作可以为O(1)

    delete   二叉查找树--O(logN);  线性表--O(N); HashSet--O(1)

    在数组中删除时,需要移动元素,平均时间复杂度为O(N)。但对于链表,删除操作可以为O(1)

    contains   二叉查找树--O(logN);  数组--O(N); HashSet--O(1)

    需要遍历数组一次,才能判断是否包含该元素。当是有序序列时,数组可以采用二分查找,复杂度降为O(logN)

    二叉查找树的实现如下:

    三,AVL树--平衡二叉树

    正是由于二叉查找树的高度随序列而变化。如,当输入序列有序时,构造出来的二叉查找树退化为链表,高度为O(N)。那么相关的操作,如findMax、findMin的时间复杂度也降为O(N)

    AVL树要求每棵树的左右子树的高度相关不能超过1,从而保证操作不会退化为O(N)的复杂度。但是AVL树的实现比较复杂。

    四,伸展树

    相对于AVL的复杂,伸展树要容易实现一些。

    伸展树保证对树的连续M次操作的最坏时间复杂度为O(MlogN)。根据摊还分析,摊还到每一次操作的时间复杂度为 MlogN / M = O(logN)

  • 相关阅读:
    TOJ1017: Tour Guide
    tzcacm去年训练的好题的AC代码及题解
    Educational Codeforces Round 40 (Rated for Div. 2)
    AtCoder Regular Contest 092
    浙南联合训练赛20180318
    [Offer收割]编程练习赛50
    牛客练习赛13
    AtCoder Regular Contest 091
    Codeforces Round #470 (rated, Div. 2, based on VK Cup 2018 Round 1)
    csa Round #73 (Div. 2 only)
  • 原文地址:https://www.cnblogs.com/hapjin/p/5387993.html
Copyright © 2011-2022 走看看