您的位置:首页 > 理论基础 > 数据结构算法

【2020-MOOC-浙江大学-陈越、何钦铭-数据结构】树(第四周的笔记和编程作业)

2020-03-20 12:07 716 查看

文章目录

  • 总结
  • 〇、前言

    这两周开始跟着【MOOC-浙江大学-陈越、何钦铭-数据结构】进行数据结构与算法的学习,特此记录复习一下,虽然记不住,但是一直记一直记一直记,成为复读机就好了。

    一、二叉搜索树


    二、平衡二叉树

    三、平衡二叉树的调整




    四、是否同一棵二叉搜索树



    实现在后面的第一题!

    五、课后题

    1、04-树4 是否同一棵二叉搜索树 (25分)


    输入样例:

    4 2
    3 1 4 2
    3 4 1 2
    3 2 4 1
    2 1
    2 1
    1 2
    0

    输出样例:

    Yes
    No
    No

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct TreeNode *Tree;
    struct TreeNode {
    int v;
    Tree Left, Right;
    int flag;
    };
    
    Tree NewNode( int V )
    {
    Tree T = (Tree)malloc(sizeof(struct TreeNode));
    T->v = V;
    T->Left = T->Right = NULL;
    T->flag = 0;
    return T;
    }
    
    Tree Insert( Tree T, int V )
    {
    if ( !T )
    T = NewNode(V);
    else {
    if ( V>T->v )
    T->Right = Insert( T->Right, V );
    else
    T->Left = Insert( T->Left, V );
    }
    return T;
    }
    
    Tree MakeTree( int N )
    {
    Tree T;
    int i, V;
    scanf("%d", &V);
    T = NewNode(V);
    for (i=1; i<N; i++) {
    scanf("%d", &V);
    T = Insert(T, V);
    }
    return T;
    }
    
    int check ( Tree T, int V )
    {
    if ( T->flag ) {
    if ( V<T->v )
    return check(T->Left, V);
    else if ( V>T->v )
    return check(T->Right, V);
    else
    return 0;
    }
    else {
    if ( V==T->v ) {
    T->flag = 1;
    return 1;
    }
    else
    return 0;
    }
    }
    
    int Judge( Tree T, int N )
    {
    int i, V, flag = 0;
    /* flag: 0代表目前还一致,1代表已经不一致*/
    scanf("%d", &V);
    if ( V!=T->v )
    flag = 1;
    else
    T->flag = 1;
    for (i=1; i<N; i++) {
    scanf("%d", &V);
    if ( (!flag) && (!check(T, V)) )
    flag = 1;
    }
    if (flag)
    return 0;
    else
    return 1;
    }
    
    void ResetT ( Tree T ) /* 清除T中各结点的flag标记 */
    {
    if (T->Left) ResetT(T->Left);
    if (T->Right) ResetT(T->Right);
    T->flag = 0;
    }
    
    void FreeTree ( Tree T ) /* 释放T的空间 */
    {
    if (T->Left) FreeTree(T->Left);
    if (T->Right) FreeTree(T->Right);
    free(T);
    }
    
    int main()
    {
    int N, L, i;
    Tree T;
    scanf("%d", &N);
    while (N) {
    scanf("%d", &L);
    T = MakeTree(N);
    for (i=0; i<L; i++) {
    if (Judge(T, N))
    printf("Yes\n");
    else
    printf("No\n");
    ResetT(T); /*清除T中的标记flag*/
    }
    FreeTree(T);
    scanf("%d", &N);
    }
    return 0;
    }

    2、04-树5 Root of AVL Tree (25分)



    Sample Input 1:

    5
    88 70 61 96 120

    Sample Output 1:

    70

    Sample Input 2:

    7
    88 70 61 96 120 90 65

    Sample Output 2:

    88

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    typedef int ElementType;
    typedef struct AVLNode *Position;
    typedef Position AVLTree; /* AVL树类型 */
    struct AVLNode{
    ElementType Data; /* 结点数据 */
    AVLTree Left;     /* 指向左子树 */
    AVLTree Right;    /* 指向右子树 */
    int Height;       /* 树高 */
    };
    
    int Max ( int a, int b )
    {
    return a > b ? a : b;
    }
    
    int GetHeight(AVLTree A)
    {
    int MaxH, HR, HL;
    if(A) {
    HL = GetHeight(A->Left);
    HR = GetHeight(A->Right);
    MaxH = (HL>HR)?HL:HR;
    return MaxH+1;
    }
    return -1;
    }
    
    AVLTree SingleLeftRotation(AVLTree A)
    {
    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)
    {
    AVLTree B = A->Right;
    A->Right = B->Left;
    B->Left = A;
    A->Height = Max(GetHeight(A->Left), GetHeight(A->Right)) + 1;
    A->Height = Max(GetHeight(B->Right), A->Height) + 1;
    
    return B;
    }
    
    AVLTree DoubleLeftRightRotation(AVLTree A)
    {
    A->Left = SingleRightRotation(A->Left);
    
    return SingleLeftRotation(A);
    }
    
    AVLTree DoubleRightLeftRotation(AVLTree A)
    {
    A->Right = SingleLeftRotation(A->Right);
    
    return SingleRightRotation(A);
    }
    
    AVLTree Insert( AVLTree T, ElementType X )
    { /* 将X插入AVL树T中,并且返回调整后的AVL树 */
    if ( !T ) { /* 若插入空树,则新建包含一个结点的树 */
    T = (AVLTree)malloc(sizeof(struct AVLNode));
    T->Data = X;
    T->Height = 0;
    T->Left = T->Right = NULL;
    } /* if (插入空树) 结束 */
    
    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 (插入左子树) 结束 */
    
    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 (插入右子树) 结束 */
    
    /* else X == T->Data,无须插入 */
    
    /* 别忘了更新树高 */
    T->Height = Max( GetHeight(T->Left), GetHeight(T->Right) ) + 1;
    
    return T;
    }
    
    int main()
    {
    int N, i;
    ElementType t;
    AVLTree T=NULL;
    scanf("%d", &N);
    for (i=0; i<N; i++) {
    scanf("%d",&t);
    T= Insert(T,t);
    }
    if(T)
    printf("%d", T->Data);
    return 0;
    }

    3、04-树6 Complete Binary Search Tree (30分)


    Sample Input:

    10
    1 2 3 4 5 6 7 8 9 0

    Sample Output:

    6 3 8 1 5 7 9 0 2 4

    #include <stdlib.h>
    #include <stdio.h>
    #include <math.h>
    int arr[1000], rearr[1000];
    int compare( const void* a, const void* b ){
    return *(int*)a - *(int*)b;
    }
    int getLeftLength(int n){    //利用二叉树的性质:满二叉树第i层有 2^(i-1) 个结点, 高为h的满二叉树有 2^h - 1 个结点(从1开始)
    double h, x, L, t;
    h = (double)(int)( log((double)n+1) / log(2.0) );
    //h = floor( log((double)n+1) / log(2.0) );
    x = n - pow(2.0, h) + 1 ;
    t = pow(2.0, h - 1.0);
    x = x < t ? x : t;
    L = t - 1 + x;
    return (int)L;
    }
    void solve( int left, int right, int root ){
    //初始调用: solve(0, n-1, 0);
    int n, L, leftRoot, rightRoot;
    n = right - left + 1;			//数组中的总个数
    if(n == 0) return ;				//递归退出的条件
    L = getLeftLength(n);			//计算出左子树的结点
    rearr[root] = arr[left + L];	//将新的根结点放入新的数组
    leftRoot = root * 2 + 1;		//左孩子
    rightRoot = leftRoot + 1;		//右孩子
    solve(left, left + L - 1, leftRoot);
    solve(left + L + 1, right, rightRoot);
    }
    int main(){
    int n;
    scanf("%d", &n);
    for(int i = 0; i < n; i++){
    scanf("%d", &arr[i]);
    }
    qsort(arr, n, sizeof(int), compare);
    solve(0, n-1, 0);
    for(int i = 0; i < n; i++){
    if( i != 0 ) printf(" ");
    printf("%d", rearr[i]);
    }
    system("pause");
    return 0;
    }

    4、04-树7 二叉搜索树的操作集 (30分)


    #include <stdio.h>
    #include <stdlib.h>
    
    typedef int ElementType;
    typedef struct TNode *Position;
    typedef Position BinTree;
    struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
    };
    
    void PreorderTraversal( BinTree BT ); /* 先序遍历,由裁判实现,细节不表 */
    void InorderTraversal( BinTree BT );  /* 中序遍历,由裁判实现,细节不表 */
    
    BinTree Insert( BinTree BST, ElementType X );
    BinTree Delete( BinTree BST, ElementType X );
    Position Find( BinTree BST, ElementType X );
    Position FindMin( BinTree BST );
    Position FindMax( BinTree BST );
    
    int main()
    {
    BinTree BST, MinP, MaxP, Tmp;
    ElementType X;
    int N, i;
    
    BST = NULL;
    scanf("%d", &N);
    for ( i=0; i<N; i++ ) {
    scanf("%d", &X);
    BST = Insert(BST, X);
    }
    printf("Preorder:"); PreorderTraversal(BST); printf("\n");
    MinP = FindMin(BST);
    MaxP = FindMax(BST);
    scanf("%d", &N);
    for( i=0; i<N; i++ ) {
    scanf("%d", &X);
    Tmp = Find(BST, X);
    if (Tmp == NULL) printf("%d is not found\n", X);
    else {
    printf("%d is found\n", Tmp->Data);
    if (Tmp==MinP) printf("%d is the smallest key\n", Tmp->Data);
    if (Tmp==MaxP) printf("%d is the largest key\n", Tmp->Data);
    }
    }
    scanf("%d", &N);
    for( i=0; i<N; i++ ) {
    scanf("%d", &X);
    BST = Delete(BST, X);
    }
    printf("Inorder:"); InorderTraversal(BST); printf("\n");
    
    return 0;
    }
    /* 你的代码将被嵌在这里 */

    输入样例:

    10
    5 8 6 2 4 1 0 10 9 7
    5
    6 3 10 0 5
    5
    5 7 0 10 3

    输出样例:

    Preorder: 5 2 1 0 4 8 6 7 10 9
    6 is found
    3 is not found
    10 is found
    10 is the largest key
    0 is found
    0 is the smallest key
    5 is found
    Not Found
    Inorder: 1 2 4 6 8 9

    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 if(X = BST->Data)  do nothing
    }
    return BST;
    }
    BinTree Delete( BinTree BST, ElementType X ){
    Position TMP;
    if( !BST ) printf("Not Found\n");
    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 ){  //如果BST左右孩子都有
    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;
    }
    Position Find( BinTree BST, ElementType X ){
    if( !BST )	return NULL;
    else if( X == BST->Data ) return BST;
    else if( X > BST->Data ) return Find( BST->Right, X );
    else if( X < BST->Data ) return Find( BST->Left, X );
    return NULL;
    }
    //递归查找最小元素
    Position FindMin( BinTree BST ){
    if( !BST ) return NULL;
    else if( !BST->Left ) return BST;
    else if( BST->Left ) FindMin( BST->Left );
    }
    //非递归查找最大元素
    Position FindMax( BinTree BST ){
    if( BST )
    while( BST->Right ) BST = BST->Right;
    return BST;
    }

    总结

    简单总结下这周的学习内容,继续二叉树,我觉得自己非常有做调包侠的前途!!!

    • 点赞
    • 收藏
    • 分享
    • 文章举报
    我是管小亮 博客专家 发布了226 篇原创文章 · 获赞 4668 · 访问量 75万+ 他的留言板 关注
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: 
    相关文章推荐