c语言第八课(树)

#define ElementType int

struct BinaryTreeNode

{

    ElementType data;

    struct BinaryTreeNode *left;       //树的左孩子

    struct BinaryTreeNode *right;      //树的右孩子

    struct BinaryTreeNode *parent;    //树的双亲

};

typedef struct BinaryTreeNode BTNode;

1.树:元素之间具有分层类似的结构,由于结构特征,常采用递归方式定义。

树的定义:除根结点外,每个结点有一个前驱结点,除叶子外,每个结点都有至少一个后驱结点。
基本术语:

结点:树中的元素,

路径:从根结点到叶子是一条路径,每棵树有多条路径。

双亲:每个结点的前驱称为该结点的双亲,根结点没有双亲。

孩子:每个结点的子节点,即它的后驱称为该结点的孩子,叶子没有孩子。

兄弟:有相同双亲的结点互为兄弟。

后裔:一个结点的所以子数都为该结点的后裔。

祖先:从根到该结点路径上的所以结点都是该结点的祖先,双亲也是它的祖先之一。

结点的度:结点拥有的后驱数(子节点数)

叶子:度为0的结点,没有后驱的节点,也可以说所有分支的最后一个结点都是叶子。

分支结点:度不为0的结点(不是叶子都是分支结点)

树的度:树中结点的最大的度,即为树的度。也可以说是树的最大分支数。

结点层次:根结点为1,其余为双亲层次加一,即本身为第几层。

树的高度:一棵树的最大层次。

int GetTreeHeight(BTNode* node)

{

    if(node==NULL)

       return 0;

       int leftHeight=GetTreeHeight(node->left);

       int rightHeight=GetTreeHeight(node->right);

       return (leftHeight>rightHeight? leftHeight:rightHeight)+1;

}

无序树:任意子树之间的次序不重要,可以交换位置。

有序树:树中结点从左到右有次序的。

森林:是树的集合,0个或多个不相交的树组成森林。

2、二叉树

定义:结点的有限次数(可以为空)或是由一个根与两个互不相交的子树,称为该树的左子树与右子树

ps:树中可以有多颗子树,而二叉树最多只能有两个子树。

性质:二叉树最多可以有2n-1个节点,当n=0时,该树为空二叉树。

高度:包含n个元素的二叉树的高度至少为[log2(n+1)],并且,平衡二叉树的最大检索次数也为[log2(n+1)]。

叶子:叶子的个数一定比度为2的结点多1。

路径(边):路径(边)为n-1条。

满二叉树:高为n的二叉树恰为2n-1个结点的树

完全二叉树:只有最下两层结点的度可以小于二,且最小层集中在左边。

完全二叉树高度[log2(n+1)]

  1. 遍历算法

先序遍历:先访问根,再遍历左子树,最后遍历右子树

void PrevPrint(BTNode *node)

{

    if(node!=NULL)

    {

      printf("%d ",node->data);

      PrevPrint(node->left);

      PrevPrint(node->right);

    }

}

中序遍历:先遍历左子树,再访问根,最后遍历右子树

void MidPrint(BTNode *node)

{

    if(node!=NULL)

    {

      MidPrint(node->left);

      printf("%d ",node->data);

      MidPrint(node->right);

    }

}

后序遍历:先遍历左子树,再遍历右子树,最后访问根

void PostPrint(BTNode *node)

{

    if(node!=NULL)

    {

      PostPrint(node->left);

      PostPrint(node->right);

      printf("%d ",node->data);

    }

}

  1. 平衡二叉树(AVL)(红黑树)

定义:左右子树的高度差不超过1。
左左插入:(在左子树的左边插入):右旋

 BTNode* RotateRight(BTNode* node)

{

    BTNode *t=node->left;    

    node->left=t->right;

    t->right=node;

    return t;

}

右右插入:(在右子树的右边插入):左旋

BTNode* RotateLeft(BTNode* node)

{

    BTNode *t=node->right;

    node->right=t->left;

    t->left=node;

    return t;

}

左右插入:(在左子树的右边插入)左右旋(先左旋再右旋)

BTNode* RotateLeftRight(BTNode* node)

{

    node->left=RotateLeft(node->left);

    return RotateRight(node);

}

右左插入:(在右子树的左边插入)右左旋(先右旋再左旋)

BTNode* RotateRightLeft(BTNode* node)

{

    node->right=RotateRight(node->right);

    return RotateLeft(node);

}

树的删除:

void DeleteElement(LBTree *tree, ElementType element)

{

    BTNode *targetNode=SearchNode(tree->root,element);

    if(targetNode==NULL)

    return ;

    if(targetNode->left==NULL&&targetNode->right==NULL)

    {//如果左右子树都为空,判断本身为双亲的那边的子树,然后将指向待删结点的指针指向空

       if(targetNode->parent->left==targetNode)

        targetNode->parent->left=NULL;

        else

        targetNode->parent->right=NULL;

        free(targetNode);

    }

    else if(targetNode->right==NULL)

    {//如果右子树为空,判断本身为双亲的那边的子树,将待删结点的左子树指向待删结点的指针指向它的双亲,最后放掉内存

        targetNode->left->parent=targetNode->parent;

        if(targetNode->parent->left==targetNode)

        targetNode->parent->left=targetNode->left;

        else

        targetNode->parent->right=targetNode->left;

        free(targetNode);

    }

    else if(targetNode->left==NULL)

    {//如果左子树为空,判断本身为双亲的那边的子树,将待删结点的右子树指向待删结点的指针指向它的双亲,最后放掉内存

        targetNode->right->parent=targetNode->parent;

        if(targetNode->parent->right==targetNode)

        targetNode->parent->right=targetNode->right;

        else

        targetNode->parent->left=targetNode->right;

        free(targetNode);

    }

    else if(targetNode->left!=NULL&&targetNode->right!=NULL)

    {//如果左右子树都不为空,则找右子树的最小值

        BTNode *MinNode=targetNode->right;

      //不断向带删结点右子树的左子树遍历,直到个左子树指向空

        while(MinNode->left!=NULL)

        {

            MinNode=MinNode->left;

        }   

         //将右子树的最小值和待删结点的值替换

        targetNode->data=MinNode->data;

        if(MinNode->parent!=targetNode)

        {//如果最小值的双亲不是待删结点,则指向最小值的指针指向最小值的右孩子

            MinNode->parent->left=MinNode->right;

        }

        else

        {  

 //如果最小值双亲为待删结点,即待删结点的右子树没有左孩子

直接将待删结点右孩子的指针指向最小值的右孩子

  targetNode->right=MinNode->right;

        }

        free(MinNode);

    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值