数据结构学习—树(2)

二叉搜索树(Binary Search Tree)

1.非空左子树的所有键值小于其根节点的键值
2.非空右子树的所有键值大于其根节点的键值
3.左右子树都是二叉搜索树

二叉搜索树的删除

  1. 要删除的是叶节点:直接删除,并再修改其父节点指针—置为NULL
    在这里插入图片描述

  2. 要删除的节点只有一个孩子节点:将其父节点的指针指向要删除节点的孩子节点
    在这里插入图片描述

  3. 要删除的节点有左、右两颗子树:右子树最小元素或左子树最大元素替代被删除的节点
    在这里插入图片描述

二叉搜索的基本运算

#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct TreeNode *Tree;
typedef struct TreeNode *Position;
struct TreeNode{
    int Data;
    Tree Left,Right;
};


int Retrieve(Position P) {
    return P->Data;
}

Tree MakeEmpty(Tree BST) //树置空
{
    if(BST != NULL)
    {
        MakeEmpty(BST->Left);
        MakeEmpty(BST->Right);
        free(BST);
    }
    return NULL;
}

Position Find(int x, Tree BST) //找到值为x的元素在树中位置,使用递归方式
{
    if(!BST) return NULL;
    if(x > BST->Data)
        return Find(x,BST->Right);
    else if ( x < BST->Data)
        return Find(x, BST->Left);
    else
        return BST;
}

Position IterFind(int x, Tree BST) 找到值为x的元素在树中位置,使用循环迭代方式
{
    while(BST){
        if(x > BST->Data)
            BST = BST->Right;
        else if(x < BST->Data)
            BST = BST->Left;
        else
            return BST;
    }
    return NULL;
}

Position FindMax(Tree BST)  //找到树中的最大值
{
    if(!BST) return NULL;
    else if (!BST->Right)
        return BST;
    else
        return FindMax(BST->Right);
}

Position FindMin(Tree BST) //找到树中的最小值,使用递归方式
{
    if(!BST) return NULL;
    else if (!BST->Left)
        return BST;
    else
        return FindMin(BST->Left);
}

Position FindMin_1(Tree BST)  //找到树中的最小值,使用迭代方式
{
    if(BST)
        while(BST->Left){
            BST = BST->Left;
        }
    return BST;
}

Tree Insert(int x, Tree BST)    //在BST中插入一个元素
{
    if(!BST){
        BST = malloc(sizeof( struct TreeNode ));
        BST->Data = x;
        BST->Left = BST->Right =NULL;
    } else
        if (x < BST->Data)
            BST->Left = Insert(x, BST->Left);
        else if (x > BST->Data)
            BST->Right = Insert(x, BST->Right);
     return BST;
}

Tree Delete(int x, Tree BST)  //找到树中的x元素,并删除
{
    Position Tmp;
    if(!BST) printf("未找到需要删除的元素");
    else if(x < BST->Data)
        BST->Left = Delete(x, BST->Left);
    else if(x > BST->Data)
        BST->Right = Delete(x, BST->Right);
    else
        if(BST->Left && BST->Right) {
            Tmp = FindMin(BST->Right);
            BST->Data = Tmp->Data;
            BST->Right = Delete(BST->Data,BST->Right);
        } else{
            Tmp = BST;
            if(!BST->Left)
                BST = BST->Right;
            else if (!BST->Right)
                BST = BST->Left;
            free(Tmp);
        }
    return BST;
}

int main(void)
{
    int data[N] = { 16, 24, 51, 12, 32, 2, 15, 44,33,9 };
    int i, e;
    Tree T;
    Position P;

    T = MakeEmpty(NULL);
    for(i = 0; i < N; ++i)
        T = Insert(data[i], T);
    P = FindMin(T);
    printf("Min: %d\n", P->Data);
    P = FindMax(T);
    printf("Max: %d\n", P->Data);
    T = Delete(2, T);
    printf("在删除掉元素x后");
    P = FindMin(T);
    printf("Min: %d\n", P->Data);
    P = FindMax(T);
    printf("Max: %d\n", P->Data);
    return 0;
}

平衡二叉树

平衡因子(Balance Factor):BF(T)= H L H_{L} HL- H R H_{R} HR,其中 H L 和 H_{L}和 HLH_{R}$分别为T的左、右子树高度。
平衡二叉树:空树或任一节点的左右子树高度差的绝对值不超过1,即|BF(T)| ≤ \leq 1
在这里插入图片描述

#include <stdio.h>
#include <stdlib.h>


typedef struct AVLNode *Position;
typedef Position AVLTree; //AVL树类型
struct AVLNode{
    int Data; //结点数据
    AVLTree Left;      // 指向左子树
    AVLTree Right;     // 指向右子树
    int Height;        // 树高
};

int Max ( int a, int b )
{
    return a > b ? a : b;
}



int GetHeight(AVLTree A){
    if(A==NULL)
        return 0;
    return Max( GetHeight(A->Left), GetHeight(A->Right) )+1;
}

AVLTree SingleLeftRotation ( AVLTree A )
{  // 注意:A必须有一个左子结点B
     // 将A与B做左单旋,更新A与B的高度,返回新的根结点B

    AVLTree B = A->Left;
    A->Left = B->Right;
    B->Right = A;
    A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;
    B->Height = Max( GetHeight(B->Left), A->Height ) + 1;

    return B;
}

AVLTree SingleRightRotation ( AVLTree A )
{  // 注意:A必须有一个右子结点B
     // 将A与B做右单旋,更新A与B的高度,返回新的根结点B

    AVLTree B = A->Right;
    A->Right = B->Left;
    B->Left = A;
    A->Height = Max( GetHeight(A->Left), GetHeight(A->Right) ) + 1;
    B->Height = Max( GetHeight(B->Right), A->Height ) + 1;
    return B;
}

AVLTree DoubleLeftRightRotation ( AVLTree A )
{  // 注意:A必须有一个左子结点B,且B必须有一个右子结点C
     // 将A、B与C做两次单旋,返回新的根结点C

     // 将B与C做右单旋,C被返回
    A->Left = SingleRightRotation(A->Left);
     // 将A与C做左单旋,C被返回
    return SingleLeftRotation(A);
}

AVLTree DoubleRightLeftRotation ( AVLTree A )
{  // A必须有一个左子结点B,且B必须有一个右子结点C
     // 将A、B与C做两次单旋,返回新的根结点C

     // 将B与C做右单旋,C被返回
    A->Left = SingleLeftRotation(A->Right);
     // 将A与C做左单旋,C被返回
    return SingleRightRotation(A);
}

AVLTree Insert( AVLTree T, int X )
{  // 将X插入AVL树T中,并且返回调整后的AVL树
    if ( !T ) {  // 若插入空树,则新建包含一个结点的树
        T = (AVLTree)malloc(sizeof(struct AVLNode));
        T->Data = X;
        T->Height = 0;
        T->Left = T->Right = NULL;
    }

    else if ( X < T->Data ) {
         // 插入T的左子树
        T->Left = Insert( T->Left, X);
         // 如果需要左旋
        if ( GetHeight(T->Left)-GetHeight(T->Right) == 2 ) {
            if (X < T->Left->Data)
                T = SingleLeftRotation(T);       // 左单旋
            else
                T = DoubleLeftRightRotation(T);  // 左-右双旋
        }
    }

    else if ( X > T->Data ) {
         // 插入T的右子树
        T->Right = Insert( T->Right, X );
         // 如果需要右旋
        if ( GetHeight(T->Left)-GetHeight(T->Right) == -2 ) {
            if (X > T->Right->Data)
                T = SingleRightRotation(T);      // 右单旋
            else
                T = DoubleRightLeftRotation(T);  // 右-左双旋
        }
    }  // else if (插入右子树) 结束



     // 更新树高
    T->Height = Max( GetHeight(T->Left), GetHeight(T->Right) ) + 1;

    return T;
}
void PreOrderTraverse(AVLTree T)
{
    if(T==NULL)
        return;
    printf("%d",T->Data);// 显示结点数据,可以更改为其它对结点操作
    PreOrderTraverse(T->Left); // 再先序遍历左子树
    PreOrderTraverse(T->Right); // 最后先序遍历右子树
}
int main(){
    int N;
    scanf("%d", &N);
    int num;
    AVLTree T=NULL;
    for(int i=1; i<=N; i++){
        scanf("%d", &num);
        T = Insert(T,num);
    }
    //printf("%d",T->Left->Right->Data);
    PreOrderTraverse(T);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值