树-中

二叉搜索树

**定义:**它是一种对排序和查找都很有用的特殊二叉树;
一个二叉搜索树是一棵二叉树,它可以为空。如果不为空,它将满足以下性质:
非空左子树的所有键值小于其根结点的键值。
非空右子树的所有键值大于其根结点的键值。
左、右子树都是二叉搜索树。
查找操作
静态查找(二分查找)
动态查找
二叉搜索树查找操作

Position Find( ElementType X, BinTree BST )
{
    if( !BST )
        return NULL; /*查找失败*/
    if( X > BST->Data )
        return Find( BST->Right, X ); /*在右子树中继续查找*/
    else if( X < BST->Data )
        return Find( BST->Left, X ); /*在左子树中继续查找*/
    else /* X == BST->Data */
        return BST; /*查找成功,返回结点的找到结点的地址*/
}

最大数查找
最大元素一定是在树的最右分枝的端结点上

Position FindMin( BinTree BST )
{
    if( !BST )
        return NULL; /*空的二叉搜索树,返回NULL*/
    else if( !BST->Left )
        return BST;  /*找到最左叶结点并返回*/
    else
        return FindMin( BST->Left ); /*沿左分支继续查找*/
}

最小数查找
最小元素一定是在树的最左分枝的端结点上

Position FindMax( BinTree BST )
{
    if( !BST )
        while( BST->Right )
             BST = BST->Right;
      /*沿右分支一直向下,直到最右端点*/
      return BST;
}

二叉搜索树的插入
分析:插入完以后必须要保证依然还是二叉树,将元素X插入二叉搜索树BST中关键是要找到元素应该插入的位置。位置的确定可以利用与查找函数Find类似的方法,如果在树BST中找到X,说明要插入的元素已存在,可放弃插入操作。如果没找到X,查找终止的位置就是X应插入的位置。

BinTree Insert( BinTree BST, ElementType X )
{
    if( !BST )  /*若原树为空,生成并返回一个结点的二叉搜索树*/
    {
        BST = (BinTree)malloc(sizeof(struct TNode));
        BST->Data = X;
        BST->Left = BST->Right = NULL;
    }
    else   /* 开始找要插入元素的位置 */
    {
        if( X < BST->Data )
            BST->Left = Insert( BST->Left, X );
        /*递归插入左子树*/
        else  if( X > BST->Data )
            BST->Right = Insert( BST->Right, X );
        /*递归插入右子树*/
        /* else X已经存在,什么都不做 */
    }
    return BST;
}

例题
以一年十二个月的英文缩写为键值,按从一月到十二月顺序输入它们,即输入序列为(Jan, Feb, Mar, Apr, May, Jun, July, Aug, Sep, Oct, Nov, Dec),将产生什么样的二叉搜索树?

分析:就是按照非空左子树的所有键值小于其根结点的键值,非空右子树的所有键值大于其根结点的键值。
在这里插入图片描述

二叉搜索树的删除

有三种情况要考虑
1.要删除的是叶结点——可以直接删除,然后再修改其父结点的指针
2.要删除的结点只有一个孩子结点——删除之前需要改变其父结点的指针,指向要删除结点的孩子结点。
3.要删除的结点有左、右两棵子树——为了保持二叉搜索树的有序性,替代被删除的元素的位置可以有两种选择:一种是取其右子树中的最小元素;另一个是取其左子树中的最大元素。

BinTree Delete( BinTree BST, ElementType X )
{
    Position Tmp;
    if( !BST )
        printf("要删除的元素未找到");
    else
    {
        if( X < BST->Data )
            BST->Left = Delete( BST->Left, X );   /* 从左子树递归删除 */
        else if( X > BST->Data )
            BST->Right = Delete( BST->Right, X ); /* 从右子树递归删除 */
        else   /* BST就是要删除的结点 */
        {
            /* 如果被删除结点有左右两个子结点 */
            if( BST->Left && BST->Right )
            {
                Tmp = FindMin( BST->Right ); /*从右子树中找最小的元素填充删除结点*/
                BST->Data = Tmp->Data;
                /* 从右子树中删除最小元素 */
                BST->Right = Delete( BST->Right, BST->Data );
            }
            else   /* 被删除结点有一个或无子结点 */
            {
                Tmp = BST;
                if( !BST->Left )
                    BST = BST->Right; /* 只有右孩子或无子结点 */
                else
                    BST = BST->Left;  /* 只有左孩子 */
                free( Tmp );
            }
        }
    }
    return BST;
}

平衡二叉树

什么是平衡二叉树??,怎样计算平均查找长度ASL
在这里插入图片描述

第一个图的ASL=(1+2×2+3×3+4×3+5×2+6×1)/12 = 3.5;
第二个图的ASL=(1+2×2+3×4+4×5)/12 = 3.0;
第三个图的ASL=(1+2×1+3×1+4×1+5×1+6×1+7×1+8×1+9×1+10×1+11×1+12×1)/12 = 6.5;

平衡因子:BF(T)=h(L)-h®;其中h(L)和h®分别为T的左、右子树的高度;
平衡二叉树,又称为“AVL树” 。 AVL树或者是一棵空树,或者是具有下列性质的非空二叉搜索树:“任一结点左、右子树高度差的绝对值不超过1 。”即|BF(T) |≤ 1

在这里插入图片描述

平衡二叉树的调整
作用就是要保证二叉树平衡

1.右单旋
在这里插入图片描述

在这里插入图片描述

2.左单旋

在这里插入图片描述

3.左右双旋
在这里插入图片描述

4.右左双旋

在这里插入图片描述

PAT例题
将给定的一系列数字插入初始为空的AVL树,请你输出最后生成的AVL树的根结点的值。输入格式:输入的第一行给出一个正整数N(≤20),随后一行给出N个不同的整数,其间以空格分隔。输出格式:在一行中输出顺序插入上述整数到一棵初始为空的AVL树后,该树的根结点的值。
输入样例1:5
88 70 61 96 120
输出样例1:
70
输入样例2:
7
88 70 61 96 120 90 65
输出样例2:
88

#include <stdio.h>
#include <stdlib.h>
typedef struct Node Node;
struct Node
{
    int Data;
    struct Node *Left,*Right;
}*head = NULL;
Node *New(int d)
{
    Node *node = (Node *)malloc(sizeof(Node));
    node -> Data = d;
    node -> Left = node -> Right = NULL;
    return node;
}
Node *ll(Node *node)
{
    Node *l = node -> Left;
    node -> Left = l -> Right;
    l -> Right = node;
    return l;
}
Node *rr(Node *node)
{
    Node *r = node -> Right;
    node -> Right = r -> Left;
    r -> Left = node;
    return r;
}
Node *lr(Node *node)
{
    node -> Left = rr(node -> Left);
    return ll(node);
}
Node *rl(Node *node)
{
    node -> Right = ll(node -> Right);
    return rr(node);
}
int max(int a,int b)
{
    return a > b ? a : b;
}
int Height(Node *node)
{
    return node == NULL ? 0 : max(Height(node -> Left),Height(node -> Right)) + 1;
}
Node* Insert(Node *node,int d)
{
    if(node == NULL)
    {
        node = New(d);
    }
    else if(d < node -> Data)
    {
        node -> Left = Insert(node -> Left,d);
    }
    else
    {
        node -> Right = Insert(node -> Right,d);
    }
    if(Height(node -> Left) - Height(node -> Right) == 2)
    {
        if(d < node -> Left -> Data)
        {
            node = ll(node);
        }
        else
        {
            node = lr(node);
        }
    }
    else if(Height(node -> Left) - Height(node -> Right) == -2)
    {
        if(d > node -> Right -> Data)
        {
            node = rr(node);
        }
        else
        {
            node = rl(node);
        }
    }
    return node;
}
int main()
{
    int n,d;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i = 0; i < n; i ++)
        {
            scanf("%d",&d);
            head = Insert(head,d);
        }
        printf("%d",head -> Data);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值