二叉树的学习

https://blog.csdn.net/A__B__C__/article/details/82715694

记录自我理解:

前中后遍历的意思主要针对的是根节点:前序遍历是首先跟节点,然后左右;中序遍历是根节点在中间遍历;后序是根节点最后遍历。

 

二叉树:
1. 完全二叉树
可以看出性质4和5是针对重要的特殊二叉树——完全二叉树的,在此先给出特殊二叉树的定义。

(1)满二叉树
深度k的满二叉树是有2^k-1个结点的二叉树,在满二叉树中,每一层结点都达到了最大个数,除最底层结点的度为0外,其他各层结点的度都为2。

(2)完全二叉树
如果一棵具有n个结点的深度为k的二叉树,它的每一个结点都与高度为k的满二叉树中编号为1 ~ n-1的结点一一对应,则称这棵二叉树为完全二叉树。 
其特点是:上面从第1层到第k-1层的所有各层的结点数都是满的,仅最下面的第k层是满的,或从右往左连续缺少若干结点。

(3)完全二叉树的结论
若完全二叉树有n个结点,当n为奇数时,n1 = 0,n2 = int_DOWN(n/2),n0 = n2 + 1;
当n为偶数时,n1 = 1, n0 = n/2;n2 = n0 - 1。

性质的内容
二叉树具有以下五个性质: 
1. 在二叉树的第i(i>=1)层最多有2^(i - 1)个结点。 
2. 深度为k(k>=0)的二叉树最少有k个结点,最多有2^k-1个结点。 
3. 对于任一棵非空二叉树,若其叶结点数为n0,度为2的非叶结点数为n2,则n0 = n2 +1。 
4. 具有n个结点的完全二叉树的深度为int_UP(log(2,n+1))。 
5. 如果将一棵有n个结点的完全二叉树自顶向下,同一层自左向右连续给结点编号1,2,3,......,n,然后按此结点编号将树中各结点顺序的存放于一个一维数组,并简称编号为i的结点为结点i( i>=1 && i<=n),则有以下关系: 
(1)若 i= 1,则结点i为根,无父结点;若 i> 1,则结点 i 的父结点为结点int_DOWN(i / 2); 
(2)若 2*i <= n,则结点 i 的左子女为结点 2*i; 
(3)若2*i<=n,则结点i的右子女为结点2*i+1; 
(4)若结点编号i为奇数,且i!=1,它处于右兄弟位置,则它的左兄弟为结点i-1; 
(5)若结点编号i为偶数,且i!=n,它处于左兄弟位置,则它的右兄弟为结点i+1; 
(6)结点i所在的层次为 int_DOWN(log(2,i))+1。

平衡二叉树:
基于avl算法,即是avl树(avl tree)
特点:
1.符合二叉树的条件下
2.任何节点的两个子树的高度最大差为1
如果在avl 树,中进行插入和删除节点操作,可能导致avl树失去平衡,那么可以通过旋转重新达到平衡。因此我们说的二叉树也称自平衡二叉树。

红黑树
红黑树和avl树类似,都是在进行插入和删除操作时通过特定的操作保持二叉树的平衡,从而获得较高的查找性能。
特点:
1.节点是红色或黑色
2.根节点是黑色
3.叶子节点(nil,空节点)是黑色
4.每个红色节点的两个子节点都是黑色

前序遍历:
//前序(递归):根节点 --> 左子树 --> 右子树

void PreOrder(BTNode *pRoot)
{
    if (pRoot != NULL)
    {
        printf("%c ", pRoot->d);   //遍历更新节点
        PreOrder(pRoot->_pLeft);   //左子树
        PreOrder(pRoot->_pRight);  //右子树
    }
}

中序遍历:
//中序(递归):左子树 --> 根节点 --> 右子树

void InOrder(BTNOde *pRoot)
{
    if (pRoot != NULL)
    {
        InOrder(pRoot->_pLeft);
        printf("%c ", pRoot->d);
        InOrder(pRoot->_pRight);
    }
}

后序遍历:
//后序(递归):左子树 --> 右子树 --> 根节点唯一

void PostOrder(BTTNode *pRoot)
{
    if (pRoot != NULL)
    {
        PostOrder(pRoot->_pLeft);
        PostOrder(pRoot->_pRight);
        printf("%c ", pRoot->d);
    }
}

层序遍历:

void FloorOrder(BTNode *pRoot)
{
    Status sta;
    pBTNode proot;
    InitStatus(&status);
    
    PushStatus(&sta, pRoot); //根节点入队列
    while (!IsEmpty_Status(&sta))
    {
        proot = PopStatus(&sta);
        printf("%c ", proot->d);
        
        if (proot->_pLeft != NULL)
        {
            PushStatus(&sta, proot->_pLeft);
        }
        if (pRoot->_pRight != NULL)
        {
            PushStatus(&sta, proot->_pRight);
        }
    }
}

获取二叉树的高度:

int Max(int a, int b)
{
    return a>b?a:b;
}
int GetHeight(BTNode *pNode)
{
    if (pRoot == NULL)
    {
        return 0;
    }
    else if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
    {
        return 1;
    }
    else
    {
        return 1 + (Max(GetHeight(pRoot->_pLeft), GetHeight(pRoot->_pRight)));
    }
}

获取二叉树的叶子节点数:

int GetLeaf(BTNode *pRoot)
{
    if (NULL == pRoot)
    {
        return 0;
    }
    else if (pRoot->_pLeft == NULL && pRoot->_pRight == NULL)
    {
        return 1;
    }
    else
    {
        return GetLeaf(pRoot->_pLeft) + GetLeaf(pRoot->_pRight);
    }
}

获取二叉树节点的个数:

int GetNode(BTNode *pRoot)
{
    if (NULL = pRoot)
    {
        return 0;
    }
    else if (NULL == pRoot->_pLeft && NULL == pRoot->_pRight)
    {
        return 1;
    }
    else
    {
        return GetNode(pRoot->_pLeft) + GetNode(pRoot->_pRight) + 1;
    }
}

求二叉树节点的个数:

int GetKNode(BTNode *pRoot, int k, int high)
{
    if (k <= 0 || k < high || pRoot == NULL)
        return 0;
    else if (k == 1)
    {
        return 1;
    }
    else
    {
        return (GetKNode(pRoot->_pLeft, k - 1, high) + GetKNode(pRoot->_pRight, k - 1, high));
    }
}

求二叉树中的一个节点的双亲节点:

pBTNode GetParent(BTNode *pRoot, DataType data) //求一个节点的双亲节点
{
    BTNode *root = pRoot;
    assert(pRoot != NULL);
    if (root->d == data)
    {
        return NULL;
    }
    if (pRoot->_pLeft != NULL || pRoot->_pRight != NULL)
    {
        if (pRoot->_pLeft->d == data || pRoot->_pRight->d == data)
            return pRoot;
        else
        {
            return GetParent(pRoot->_pLeft, data);
            return GetParent(pRoot->_pRight, data);
        }
    }
}

求一个节点的左孩子节点

pBTNode GetLeftChild(BTNode *pRoot, DataType data)  //获取一个节点的左孩子节点
{
    BTNode *ret = NULL;
    if (NULL == cur)
        return NULL;
    if (cur->d == data && cur->_pLeft != NULL)
    {
        return cur->_pLeft;
    }
    ret = LeftNode(cur->_pLeft, data);
    if (NULL == ret)
    {
        ret = LeftNode(Cur->_pRight, data);
    }
    
    return ret;
}

递归求二叉树的镜像:

void swap(BTNode **a, BTNode **b)
{
    BTNode *tmp = *a;
    *a = *b;
    *b = tmp;
}

void BTreeMirrorR(BTNode *pRoot) // 二叉树的镜像(递归)
{
    if (pRoot != NULL)
    {
        if (pRoot->_pLeft != NULL || pRoot->_pRight != NULL)
        {
            swap(&pRoot->_pLeft, &pRoot->_pRight);
            BTreeMirrorR(pRoot->_pLeft);
            BTreeMirrorR(pRoot->_pRight);
        }
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值