二叉树的一些学习

转: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;
 
}

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

原文地址:https://www.cnblogs.com/isawu/p/11135866.html