zoukankan      html  css  js  c++  java
  • 树(上)

    1 树和树的表示

      在客观世界中有许多事物存在层次关系

      如: 人类社会的家谱; 社会的组织结构; 图书信息管理等等

      分层次组织在管理上有更高的效率

      对于信息管理, 常用的操作有增加删除和查询, 在树中查询是重点

      关于查找

        查找: 根据某个给定的关键字K, 从集合R中找出关键字与K相同的记录

        静态查找: 集合中的记录是固定的, 没有插入和删除操作

        动态查找: 集合中的记录是动态变化的, 可以查询, 插入和删除

      静态查找

        方法1:顺序查找

        

        Tb1指向一个存储空间, 有两部分内容, 一个是指向数组, 另一个是表中数据的个数

        一般把数组首或者尾作为哨兵, 用于减少一次循环终结的判断

        

        时间复杂度为O(n)

        方法2: 二分查找

        条件: 元素是有序排列的, 用数组来存储

        

        对N每次除以2直到N变为1, 因而时间复杂度为O(logN) 

      对于序列1~11, 根据二分查找的提示, 可以形成判定树

      

      判定树上的节点查找到的比较次数刚好是节点所在的层数

      查找成功的查找次数 <= 判定树的深度

      n个节点的判定树的深度为 [long2n]+1 (向下取整再加1)

      平均成功查找次数ASL = (层数*层所在的节点个数)求和/总结点数

        ASL = (4*4+4*3+2*2+1)/11=3

    1.1 树的定义

      树: n个节点构成的有限集合

        当n=0时, 为空树

      非空树的性质:

        根root, 用r表示

        其余节点可分为m个互不相交的有限集合, 其中每个集合本身又是一棵树, 叫做原来树的子树

        

        子树是不相交的

        除了根节点, 每个节点有且仅有一个父节点

        一棵树N个节点的树有N-1条边

        树是保证节点连通的最小的连接方式

      树的基本术语

        结点的度: 结点的子树的个数

        树的度: 树的所有结点中最大的度数

        叶结点: 度为0的结点(没有子树)

        父结点: 若A有子树, 则A是子树的根节点B的父结点

        子结点: 孩子结点, B就是A的子结点

        兄弟结点: A有多个子树, 子树1的根节点B, 子树2的根节点C, 那么B和C就是兄弟结点

        路径和路径长度: 结点到结点的路径, 路径所包含的边的个数就是长度

        祖先节点: B的父节点A的父节点以及它的父节点, 到根为止都是B的祖先结点

        子孙结点

        结点的层次: 规定根结点的层次为1层

        树的深度: 树的最大层次

    1.2 树的表示

      首先由于树的结构比较复杂, 有父子关系需要存储, 因此不采用数组的方式存储树

      一般的, 采用链表的形式来存储树

      

      

      这样的结构虽然表明了树, 但是由于每个节点的数据结构不统一, 需要改进, 一般的改进策略是孩子兄弟表示法

      孩子兄弟表示法

      结构中有两个指针域, 一个指向第一个孩子, 另一个执行相邻的兄弟

      

      对于n个结点, 有2n个指针域, 有n-1条边, 因此空余的指针域为(2n-n+1)=n+1

      对于这样的表示方式, 如果顺时针旋转45度, 也是一个树的样子, 这个样子就是二叉树

      二叉树是度为2的树

      一般地解决二叉树的问题能够解决树的很多问题, 二叉树是树研究的重点

    2 二叉树及其存储结构

    2.1 二叉树的定义和性质

      (1) 二叉树的定义

      二叉树:一个有穷的结点集合

        这个集合可以为空

        若不为空, 则它由根节点和其左子树右子树两个不相交的二叉树组成

      二叉树可以被理解为区分左右顺序的度为2的树

      二叉树的五种基本形态

      

      (2) 特殊二叉树

      

      只有左子树或者只有右子树

      

      

      也就是说, 完全二叉树只要是在编号上都能在完美二叉树上对应, 就是完全二叉树

      

      (3) 二叉树的性质

      第i层最大的结点数为2i-1

      深度为k的二叉树的最大结点数为2k-1

      对于非空二叉树, 叶结点个数 = 度为2的非叶结点个数 + 1

      

      证明方式为: 对于非空二叉树, 存在度为0, 1 ,2的结点, 个数分别记为n0, n1, n2

      根据 边=所有点-1=n0 + n1 +n2 -1

      同时度为0, 1, 2的结点分别提供了0, 1, 2条边

      因此 边 = 0*n0 + 1*n1 + 2*n2

      得到 n0 + n1 +n2 -1 = 0*n0 + 1*n1 + 2*n2

      (4) 二叉树的抽象数据类型定义

      

      最重要的操作方法是遍历

      

    2.2 二叉树的存储结构

      (1) 顺序存储结构

      可以用数组存储完全二叉树

      完全二叉树: 按从上到下, 从左到右顺序存储n个结点的完全二叉树的结点父子关系 

      

      存储为

      

      同时可以通过计算得到一个结点的父亲节点, 左孩子, 右孩子

        父亲节点是[i/2]向下取整

        左孩子是 2i

        右孩子是 2i+1

      但是如果一般的二叉树采用这样的方式存储的话, 需要填充一部分不存在的元素, 因此会造成很大程度上的空间浪费

      (2) 链表存储

      

    3 二叉树的遍历

      二叉树一般还是使用链式存储, 二叉树的遍历是基于链式存储的二叉树来的

    3.1 递归方式遍历

      (1) 先序遍历

      根->左->右

      

      

      (2) 中序遍历

      左->根->右

      

      

      (3) 后序遍历

      左->右->根

      

      

      先序, 中序和后序遍历过程, 遍历过程中经过结点的路线一样, 只是访问输出各结点的时间不同

      每个节点实际上有三次输出的机会, 这就对应了先序, 中序和后

      

    3.2 非递归方式

      (1) 中序遍历

      实现方法:

        遇到一个结点, 就把它压栈, 并遍历它的左子树, (遍历左/右子树的时候从第一步开始执行)

        左子树遍历完成, 弹出栈顶元素

        再访问刚才弹出元素的右子树

      实现代码

      

      (2) 先序遍历

      根据结论, 先序遍历是在第一次遇到结点的时候就输出, 中序遍历是在第二次遇见的时候输出, 也就是可以将输出语句放到Push操作时就行了

      

      (3) 层次遍历

      层次遍历的问题在于, 需要保存左右儿子的信息或者当前元素的信息    

      使用队列来实现层次遍历

        先将根加入队列

        从队列中去除一个元素, 并按照顺序将其左右儿子存入队列

        输出该元素, 继续第二步骤

      

    3.3 遍历二叉树的应用

      (1) 获取叶子结点

      在遍历算法中检查左右子树是否都为空, 为空就输出

      

      (2) 求二叉树的高度

      求解思想: 二叉树的高度就是 左子树和右子树两个较大的高度+1

      通过递归就可以得到二叉树的高度了

      

      (3) 二元运算表达式树及其遍历

      表达式树:

      

      通过遍历表达式树可以得到不同的结果

      

      但是我们会发现, 得到的中缀表达式会受到运算符优先级的影响, 需要在输出结点的时候加上括号

      (4) 根据两个遍历序列得到整个二叉树

      前提, 必须要有中序, 光是前序和后序是无法得到整个树的

      

      实现的方法是

      根据中序序列得到一个根节点, 然后在先序序列中找到该结点, 那么在先序序列中前面部分就是左子树

      根据这个左子树的长度, 可以在中序序列中找到中序序列的左子树

      根据这两个左子树又可以继续找, 直到确定所有元素的位置

      

      

     

  • 相关阅读:
    Django--form验证及错误处理
    Django--form保存用户输入内容
    Django--static静态文件引用
    Django--ajax
    Django--form基础
    Django--cookie&session
    Django--缓存
    Django--中间件
    oracle——session
    oracle——DDL
  • 原文地址:https://www.cnblogs.com/weihuchao/p/6933601.html
Copyright © 2011-2022 走看看