zoukankan      html  css  js  c++  java
  • 二叉树的一些学习

    转:https://xiaozhuanlan.com/topic/5036471892

    二叉树性质
    1)在二叉树的第i层上最多有2i-1 个节点 。(i>=1)
    2)二叉树中如果深度为k,那么最多有2k-1个节点。(k>=1)
    3)n0=n2+1 n0表示度数为0的节点数,n2表示度数为2的节点数。
    4)在完全二叉树中,具有n个节点的完全二叉树的深度为[log2n]+1,其中[log2n]是向下取整。
    5)若对含 n 个结点的完全二叉树从上到下且从左至右进行 1 至 n 的编号,则对完全二叉树中任意一个编号为 i 的结点有如下特性:
      (1) 若 i=1,则该结点是二叉树的根,无双亲, 否则,编号为 [i/2] 的结点为其双亲结点;
      (2) 若 2i>n,则该结点无左孩子, 否则,编号为 2i 的结点为其左孩子结点;
      (3) 若 2i+1>n,则该结点无右孩子结点, 否则,编号为2i+1 的结点为其右孩子结点。


    二叉树遍历
    前序遍历 :通俗的说就是从二叉树的根结点出发,当第一次到达结点时就输出结点数据,按照先向左再向右的方向访问。
    中序遍历 :就是从二叉树的根结点出发,当第二次到达结点时就输出结点数据,按照先向左再向右的方向访问。
    后序遍历 :就是从二叉树的根结点出发,当第三次到达结点时就输出结点数据,按照先向左再向右的方向访问。
    层序遍历 :层次遍历就是按照树的层次自上而下的遍历二叉树。

    *虽然二叉树的遍历过程看似繁琐,但是由于二叉树是一种递归定义的结构,故采用递归方式遍历二叉树的代码十分简单。

    void PreOrderTraverse(BiTree T)
    {
        if(T==NULL)
        return;
        printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
        PreOrderTraverse(T->lchild);    /*再先序遍历左子树*/
        PreOrderTraverse(T->rchild);    /*最后先序遍历右子树*/
    }
    
    
    /*二叉树的中序遍历递归算法*/
    void InOrderTraverse(BiTree T)
    {
        if(T==NULL)
        return;
        InOrderTraverse(T->lchild); /*中序遍历左子树*/
        printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
        InOrderTraverse(T->rchild); /*最后中序遍历右子树*/
    }
    
    
    /*二叉树的后序遍历递归算法*/
    void PostOrderTraverse(BiTree T)
    {
        if(T==NULL)
        return;
        PostOrderTraverse(T->lchild);   /*先后序遍历左子树*/
        PostOrderTraverse(T->rchild);   /*再后续遍历右子树*/
        printf("%c", T->data);  /*显示结点数据,可以更改为其他对结点操作*/
    }

    将二叉树按中序遍历得到一个有序的数组结果,某个节点元素的前后相邻的节点即为前驱节点,后区节点

    前驱节点
    1:如果当前节点的左子树不为空,那么该点的前驱节点为该点左子树中最右的节点。
    2:如果当前节点的左子树为空,那么该点的前驱节点为从该点往上延伸,如果延伸到的点为其父亲节点的右孩子,那么这个父亲节点就是该点的前驱节点。

    后驱节点
    1:如果当前节点的右子树不为空,那么该点的后驱节点为该点右子树中最左的节点。
    2:如果当前节点的右子树为空,那么该点的后驱节点为从该点往上延伸,如果延伸到的点为其父亲节点的左孩子,那么这个父亲节点就是该点的后驱节点。

    struct node
    {
        node left;//左孩子
        node right;//右孩子
        node parent;//父亲节点
        int value;
    };
    
    node getfristornode(node heap)//heap代表当前要找前驱节点的节点
    {
        if(heap==null)//如果当前节点为空,返回空
            return heap;
        if(heap.left!=null)//如果当前节点左子树不为空,那么该节点的后继节点为左子树中最右的节点
            return getrightmost(heap.left);//找到左子数树中最右的节点,并返回
        else                               //如果程序到达这里,说明当前节点的左子数为空
        {
            node parent=heap.parent;
    
           //第一个条件就是判断那种特殊情况的,一直延伸到当前节点没有父亲节点时,那么parent为空,这个条件不满足,函数返回空
           //第二个条件是判断当前节点是否为该父亲节点的右孩子,如果不是,继续执行下面的代码,如果是,说明这个父亲节点就是heap节点的前驱节点
            while (parent!=null&&heap!=parent.right)
            {                                       
                heap=parent;
                parent=heap.parent;
            }
            return parent;
        }
    }
    
    //这个函数是求左子树中最右的节点的函数
    getrightmost(node heap)
    {
        while (heap!=null)
            heap=heap.right;
        return heap.parent;
     
    }

    上面是前驱节点的查找方式,后区节点基本相同,左右换下。

  • 相关阅读:
    是否可能两个ETH私钥对应同一个地址
    使用 neon-wallet-db + neon-js + NEO-cli /rpc 搭建轻钱包服务端
    从源码看 angular/material2 中 dialog模块 的实现
    个人从源码理解JIT模式下angular编译AppModule的过程
    个人从源码理解angular项目在JIT模式下的启动过程
    使用angular的HttpClient搭配rxjs
    把angular项目整合到.net mvc中
    小程序开发整理
    ABC: Always Be Coding
    postgresql的psql常用命令-4
  • 原文地址:https://www.cnblogs.com/isawu/p/11135866.html
Copyright © 2011-2022 走看看