数据结构(复习)--------关于平衡二叉树(转载)

在上一个专题中,我们在谈论二叉查找树的效率的时候。不同结构的二叉查找树,查找效率有很大的不同(单支树结构的查找效率退化成了顺序查找)。如何解决这个问题呢?关键在于如何最大限度的减小树的深度。正是基于这个想法,平衡二叉树出现了。

 

平衡二叉树的定义 (AVL—— 发明者为Adel'son-Vel'skii 和 Landis)

 

平衡二叉查找树,又称 AVL树。 它除了具备二叉查找树的基本特征之外,还具有一个非常重要的特点:的左子树和右子树都是平衡二叉树,且左子树和右子树的深度之差的绝对值平衡因子 ) 不超过1。 也就是说AVL树每个节点的平衡因子只可能是-1、0和1(左子树高度减去右子树高度)。

 

那么如何是二叉查找树在添加数据的同时保持平衡呢?基本思想就是:当在二叉排序树中插入一个节点时,首先检查是否因插入而破坏了平衡,若 破坏,则找出其中的最小不平衡二叉树,在保持二叉排序树特性的情况下,调整最小不平衡子树中节点之间的关系,以达 到新的平衡。所谓最小不平衡子树 指离插入节点最近且以平衡因子的绝对值大于1的节点作为根的子树。

 

平衡二叉树的操作

 

1. 查找操作

       平衡二叉树的查找基本与二叉查找树相同。

 

2. 插入操作

       在平衡二叉树中插入结点与二叉查找树最大的不同在于要随时保证插入后整棵二叉树是平衡的。那么调整不平衡树的基本方法就是: 旋转 。 下面我们归纳一下平衡旋转的4中情况

1) 绕某元素左旋转  

                                 80                                    90  

                                 /  \             左旋               /    \

                               60 90          ---- ->         80     120

                                    /  \                               /  \       /

                                  85 120                    60  85 100

                                        /

                                      100     

                               a)  BST树                              b ) AVL树

     分析一下:在插入数据100之前,a图的B ST树只有80节点的平衡因子是-1(左高-右高),但整棵树还是平衡的。加入100之后,80节点的平衡因子就成为了-2,此时平衡被破坏。需要左旋转成b 图。

     当树中节点X的右孩子的右孩子上插入新元素,且平衡因子从-1变成-2后,就需要绕节点X进行左旋转。

 

2) 绕某元素右旋转  

                                100                                   85

                                 /  \               右旋              /    \

                              85  120         ------ ->     60    100  

                              /  \                                      \      /   \

                            60 90                                 80  90 120

                              \

                              80

                             a) B ST树                                b) AVL树

     当树中节点X的左孩子的左孩子上插入新元素,且平衡因子从1变成2后,就需要绕节点X进行右旋转。

 

3) 绕某元素的左子节点左旋转,接着再绕该元素自己右旋转。 此情况下就是左旋与右旋 的结合,具体操作时可以分 解成这两种操作,只是围绕点不一样而已。

                                                      

                            100                             100                                90

                             /  \             左旋            /  \              右旋           /    \

                          80  120       ------>      90  120        ------>     80   100  

                          / \                                  /                                    /  \      \

                       60 90                            80                              60  85  120

                            /                               / \

                          85                            60 85

      当树中节点X的左孩子的右孩子上插入新元素,且 平衡因子从1变成2后,就需要 先绕X的左子节点Y左旋转,接着再绕X右旋转


4) 绕某元素的右子节点右旋转,接着再绕该元素自己左旋转。 此情况下就是 右旋与左旋 的结合,具体操作时可以分解 成这两种操作,只是围绕点不一样而已 。

 

                               80                               80                                       85  

                               /   \             旋          /  \                             /  \     

                            60  100      ------>      60 85            ------->          80 100

                                   /  \                                 \                                   /     /   \       

                                85  120                        100                           60    90 120

                                   \                                   /  \

                                   90                           90  120

       当树中节点X的右孩子的左孩子上插入新元素,且 平衡因子从-1变成-2后,就需要 先绕X的右子节点Y右旋转,接着再绕X左旋转

 

 

平衡二叉树性能分析


平衡二叉树的性能优势:

      很显然,平衡二叉树的优势在于不会出现普通二叉查找树的最差情况。其查找的时间复杂度为O(logN)。

 

平衡二叉树的缺陷:

      (1) 很遗憾的是,为了保证高度平衡,动态插入和删除的代价也随之增加。因此,我们在下一专题中讲讲《红黑树》 这种更加高效的查找结构。

 

      (2) 所有二叉查找树结构的查找代价都与树高是紧密相关的,能否通过减少树高来进一步降低查找代价呢。我们可以通过多路查找树的结构来做到这一点,在后面专题中我们将通过《多路查找树/B-树/B+树 》来介绍。

 

      (3) 在大数据量查找环境下(比如说系统磁盘里的文件目录,数据库中的记录查询 等),所有的二叉查找树结构(BST、AVL、RBT)都不合适。如此大规模的数据量(几G数据),全部组织成平衡二叉树放在内存中是不可能做到的。那么 把这棵树放在磁盘中吧。问题就来了:假如构造的平衡二叉树深度有1W层。那么从根节点出发到叶子节点很可能就需要1W次的硬盘IO读写。大家都知道,硬盘的机械部件读写数据的速度远远赶不上纯电子媒体的内存。 查找效率在IO读写过程中将会付出巨大的代价。在大规模数据查询这样一个实际应用背景下,平衡二叉树的效率就很成问题了。对这一问题的解决:我们也会在《多路查找树/B-树/B+树 》 将详细分析。

 

      上面提到的红黑树和多路查找树都是属于深度有界查找树(depth-bounded tree —DBT)

 

来自于:http://hxraid.iteye.com/blog/609949

----------------------------------------------------------------------------------------------------------------------------------------------------------

  1. typedef int ElementType;  
  2.   
  3. #ifndef AVLTREE_H  
  4. #define AVLTREE_H  
  5.   
  6. struct TreeNode  
  7. {  
  8.     ElementType Element;  
  9.     int Height;  
  10.     struct TreeNode *Left;  
  11.     struct TreeNode *Right;  
  12. };  
  13.   
  14. typedef struct TreeNode *AvlTree;  
  15. typedef struct TreeNode *Position;  
  16.   
  17. AvlTree MakeEmpty(AvlTree T);  
  18. AvlTree Insert(ElementType X, AvlTree T);  
  19. Position Find(ElementType X ,AvlTree T);  
  20. Position FindMax(AvlTree T);  
  21. Position FindMin(AvlTree T);  
  22.   
  23. #endif  

avltree.c函数实现

[cpp] view plaincopyprint?
  1. #include "fatal.h"  
  2. #include "avltree.h"  
  3.   
  4. AvlTree MakeEmpty(AvlTree T)  
  5. {  
  6.     if(T != NULL)  
  7.     {  
  8.         MakeEmpty(T->Left);  
  9.         MakeEmpty(T->Right);  
  10.         free(T);  
  11.     }  
  12.     return NULL;  
  13. }  
  14.   
  15. static int Height(Position P)  
  16. {  
  17.     if(P == NULL)  
  18.         return -1;  
  19.     else  
  20.         return P->Height;  
  21. }  
  22.   
  23. static int Max(int Lhs, int Rhs)  
  24. {  
  25.     return Lhs > Rhs ? Lhs : Rhs;  
  26. }  
  27.   
  28. static Position SingleRotateWithLeft(Position K2)  
  29. {  
  30.     Position K1;  
  31.   
  32.     K1 = K2->Left;  
  33.     K2->Left = K1->Right;  
  34.     K1->Right = K2;  
  35.   
  36.     K1->Height = Max(Height(K1->Left), Height(K1->Right)) + 1;  
  37.     K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;  
  38.   
  39.     return K1;  
  40. }  
  41.   
  42. static Position SingleRotateWithRight(Position K2)  
  43. {  
  44.     Position K1;  
  45.   
  46.     K1 = K2->Right;  
  47.     K2->Right = K1->Left;  
  48.     K1->Left = K2;  
  49.   
  50.     K1->Height = Max(Height(K1->Left), Height(K1->Right)) + 1;  
  51.     K2->Height = Max(Height(K2->Left), Height(K2->Right)) + 1;  
  52.   
  53.     return K1;  
  54. }  
  55.   
  56. static Position DoubleRotateWithLeft(Position K3)  
  57. {  
  58.     K3->Left = SingleRotateWithRight(K3->Left);  
  59.     return SingleRotateWithLeft(K3);  
  60. }  
  61.   
  62. static Position DoubleRotateWithRight(Position K3)  
  63. {  
  64.     K3->Right = SingleRotateWithLeft(K3->Right);  
  65.     return SingleRotateWithRight(K3);  
  66. }  
  67.   
  68. AvlTree Insert(ElementType X, AvlTree T)  
  69. {  
  70.     if(T == NULL)  
  71.     {  
  72.         T = (Position)malloc(sizeof(struct TreeNode));  
  73.         if(T == NULL)  
  74.             FatalError("Out of space");  
  75.         T->Element = X;  
  76.         T->Height = 0;  
  77.         T->Left = T->Right = NULL;  
  78.     }  
  79.     else if(X < T->Element)//左子树插入新节点  
  80.     {  
  81.         T->Left = Insert(X, T->Left);  
  82.         if(Height(T->Left) - Height(T->Right) == 2)//左子树插入节点所以高度是左子树高于右子树  
  83.         {  
  84.             if(X < T->Left->Element)//对α的左儿子的左子树进行一次插入,需要左旋  
  85.                 T = SingleRotateWithLeft(T);  
  86.             else //对α的左儿子的右子树进行一次插入,需要双旋  
  87.                 T = DoubleRotateWithLeft(T);  
  88.         }  
  89.     }  
  90.     else if(X > T->Element)//右子树插入新节点  
  91.     {  
  92.         T->Right = Insert(X, T->Right);  
  93.         if(Height(T->Right) - Height(T->Left) == 2)//因为是右子树插入新节点,所以高度是右子树高于左子树  
  94.         {  
  95.             if(X > T->Right->Element)//对α的右儿子的右子树进行一次插入,需要右旋  
  96.                 T = SingleRotateWithRight(T);  
  97.             else//对α的右儿子的左子树进行一次插入,需要双旋  
  98.                 T = DoubleRotateWithRight(T);  
  99.         }  
  100.     }  
  101.     T->Height = Max(Height(T->Left), Height(T->Right)) + 1;  
  102.     return T;  
  103. }  
  104.   
  105. Position Find(ElementType X, AvlTree T)  
  106. {  
  107.     if(T == NULL)  
  108.         return NULL;  
  109.     if(X < T->Element)  
  110.         return Find(X, T->Left);  
  111.     else if(X > T->Element)  
  112.         return Find(X, T->Right);  
  113.     else  
  114.         return T;  
  115. }  
  116.   
  117. Position FindMin(AvlTree T)  
  118. {  
  119.     if(T == NULL)  
  120.         return NULL;  
  121.     else if(T->Left == NULL)  
  122.         return T;  
  123.     else  
  124.         return FindMin(T->Left);   
  125. }  
  126.   
  127. Position FindMax(AvlTree T)  
  128. {  
  129.     if(T == NULL)  
  130.         return NULL;  
  131.     else if(T->Right == NULL)  
  132.         return T;  
  133.     else  
  134.         return FindMax(T->Right);  
  135. }  

testavl.c测试AVL树的实现

[cpp] view plaincopyprint?
  1. #include "avltree.h"  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4.   
  5. void InOrder(AvlTree T)  
  6. {  
  7.     if(T != NULL)  
  8.     {  
  9.         InOrder(T->Left);  
  10.         printf("%d ", T->Element);  
  11.         InOrder(T->Right);  
  12.     }  
  13. }  
  14.   
  15. void PreOrder(AvlTree T)  
  16. {  
  17.     if(T != NULL)  
  18.     {  
  19.         printf("%d ", T->Element);  
  20.         PreOrder(T->Left);  
  21.         PreOrder(T->Right);  
  22.     }  
  23. }  
  24.   
  25. int main(void)  
  26. {  
  27.     AvlTree T;  
  28.     Position P;  
  29.     int i;  
  30.   
  31.     T = MakeEmpty(NULL);  
  32.     for(i = 1; i <= 7; i++)  
  33.         T = Insert(i, T);  
  34.     for(i = 16; i >= 10; i--)  
  35.         T = Insert(i, T);  
  36.     T = Insert(8, T);  
  37.     T = Insert(9, T);  
  38.     printf("Root: %d\n", T->Element);  
  39.     printf("InOrder:  ");  
  40.     InOrder(T);  
  41.     printf("\nPreOrder: ");  
  42.     PreOrder(T);  
  43.     putchar('\n');  
  44.     system("Pause");  
  45.   
  46.     return 0;  
  47. }  

测试:首先插入1到7,然后插入16到10,最后插入8和9。AVL树的应该为下图所示


测试结果如下图所示

---------------------------------------------------------------------------------------------------------------------------------------------------------

来于:http://blog.csdn.net/zitong_ccnu/article/details/11097663

--------------------------------------------------------------------

//关于平衡二叉树的实现 BBST(Blance binary search tree)
#include <cstdio>
#include <cstdlib>
//#define _OJ_
typedef struct tree
{
    int data;
    int height;
    struct tree *lchild;
    struct tree *rchild;
} tree, *Bitree;

int
Height(Bitree T)
{
    if(T == NULL)    return -1;
    else  return T->height;
}

int
Max(int h1, int h2)
{
    return h1 > h2 ? h1 : h2;
}

Bitree
Left(Bitree T)
{
    Bitree T1;
    T1 = T->rchild;
    T->rchild = T1->lchild;
    T1->lchild = T;

    T->height  = Max(Height(T->lchild), Height(T->rchild)) + 1;
    printf("T == %d\n", T->height);

    T1->height = Max(Height(T1->lchild), Height(T1->rchild)) + 1;
    printf("T1 == %d\n", T1->height);
    return T1;
}

Bitree
Right(Bitree T)
{
    Bitree T1;
    T1 = T->lchild;
    T->lchild = T1->rchild;
    T1->rchild = T;
 
    T->height  = Max(Height(T->lchild), Height(T->rchild)) + 1;
    printf("T == %d\n", T->height);
    T1->height = Max(Height(T1->lchild), Height(T1->rchild)) + 1;
    printf("T1 == %d\n", T1->height);
    return T1;
}

Bitree
Left_Right(Bitree T)
//左孩子的右孩子插入元素
{
    T = Left(T);
    return Right(T);
}

Bitree
Right_Left(Bitree T)
//右孩子的左孩子插入元素
{
    T = Right(T);
    return Left(T);
}


Bitree
Insert(Bitree T, int x)
{
    if(T == NULL) {
    T = (Bitree) malloc (sizeof(tree));
    T->data = x;         T->height = 0;
    T->lchild = T->rchild = NULL;
    }

    else if(x < T->data) {
    T->lchild = Insert(T->lchild, x);
    if(Height(T->lchild) - Height(T->rchild) == 2) {
    if(x < T->lchild->data)
        T = Right(T);                      //在左边左儿子插入元素ll此时右旋
    if(x > T->lchild->data)
        T = Left_Right(T);                //在左边右儿子的插入元素lr此时左右旋
    }
  }

    else if(x > T->data) {
    T->rchild = Insert(T->rchild, x);
    if(Height(T->rchild) - Height(T->lchild) == 2) {
        printf("\n%d %d\n", Height(T->rchild), Height(T->lchild));
        printf("ok\n");
    if(x > T->rchild->data)
        T = Left(T);                       //在右边右儿子插入元素rr此时左旋
    if(x < T->lchild->data)
        T = Right_Left(T);                //在右边左儿子插入元素rl此时右左旋
     }
  }

    T->height = Max(Height(T->lchild), Height(T->rchild)) + 1;
    return T;
}

void
preoder(Bitree T)
{
    if(T) {
        printf("data == %d\n", T->data);
        preoder(T->lchild);
        printf("\n");
        preoder(T->rchild);
    }
}


int main(int argc, char const *argv[]) {
#ifndef _OJ_ //ONLINE JUDGE
       freopen("input.txt", "r", stdin);
       //freopen("output.txt", "w", stdout);
#endif
    
    int a[100];
    int n;
    Bitree T = NULL;
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);    printf("%d ", a[i]);
        T = Insert(T, a[i]);
    }
    preoder(T);
    // printf("%d\n", Height(T));
    // printf("%d\n", T->data);



    
    return 0;
}

 

转载于:https://www.cnblogs.com/airfand/p/5082410.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256167.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

天猫双11凭什么达到1682亿?这些支撑技术或许可以告诉你

历年「双 11」都会掀起一股买买买的购物热潮 阿里巴巴将这个原本普通的日子赋予了非凡的意义 今年&#xff0c;天猫以 1682 亿的成交额再破记录 而在这一系列疯狂“秒杀”动作的背后 有一个叫云化架构的技术体系支撑着十几亿人的消费狂欢 12 月 8 日 ArchSummit 阿里技术专场 来…

keil5中文乱码的解决

keil5 复制出来的中文显示乱码&#xff0c;该如何解决&#xff1f; 点击Edit - Configuration &#xff0c;进入编辑器设置&#xff1a; 点击ok &#xff0c;就可以了转载于:https://www.cnblogs.com/alan666/p/8312100.html

【图像处理】——Python实现几何变换(自定义+opencv库)

理论知识:参考https://blog.csdn.net/on2way/article/details/40460675 Python调用opencv函数参考:https://blog.csdn.net/on2way/article/details/46801063 一、引自《数字图像处理》的基础知识汇总 这个很重要!!!这里需要注意的是反向映射和前向映射的区别,反…

spark2.0.1 安装配置

1. 官网下载 wget http://d3kbcqa49mib13.cloudfront.net/spark-2.0.1-bin-hadoop2.7.tgz 2. 解压 tar -zxvf spark-2.0.1-bin-hadoop2.7.tgz ln -s spark-2.0.1-bin-hadoop2.7 spark2 3. 环境变量 vi /etc/profile #Spark 2.0.1export SPARK_HOME/usr/local/spark2export PATH…

python实战===如何优雅的打飞机

这是一个打飞机的游戏&#xff0c;结构如下&#xff1a; 其中images中包含的素材为 命名为alien.png 命名为ship.png 游戏效果运行是这样的&#xff1a; 敌军&#xff0c;也就是体型稍微大点的&#xff0c;在上方左右移动&#xff0c;并且有规律向下移动。我军目标&#xff0c;…

【图像处理】——Python实现灰度特征提取

目录 1、灰度特征 2、Python代码 1、灰度特征 2、Python代码 import cv2 import numpy as npdef gray_features(img):hist = cv2.calcHist([img],[0],None,[256],[0,255])#得到全局直方图统计数据

前端lvs访问多台nginx代理服务时出现404错误的处理

前端lvs访问多台nginx代理服务时出现404错误的处理 环境描述&#xff1a;app --> lvs --> nginx --> server app访问页面购买流量页面(nginx服务器)代理到后端和服务器交互(多台server)刚开始访问没有问题&#xff0c;流量变大为了避免出现问题&#xff0c;nginx配置了…

iptables四个表与五个链间的处理关系

转载自&#xff1a;http://www.linuxidc.com/Linux/2012-08/67505.htm netfilter/iptables IP 信息包过滤系统是一种功能强大的工具&#xff0c;可用于添加、编辑和除去规则&#xff0c;这些规则是在做信息包过滤决定时&#xff0c;防火墙所遵循和组成的规则。 这些规则存储在专…

C++总结笔记(八)—— 菱形继承

文章目录一、基本概念二、程序举例1. 虚继承2. 内在逻辑一、基本概念 菱形继承是指存在两个子类继承自同一个基类&#xff0c;同时有子类继承这两个子类。 二、程序举例 1. 虚继承 使用虚继承可以解决菱形继承资源浪费的问题&#xff0c;因为有两个子类继承基类&#xff0c…

InnoDB引擎与MyIASM的一点总结

InnoDB引擎&#xff1a; 提供了对数据库ACID事务的支持&#xff0c;并且实现了SQL标准的四种隔离级别 提供了行级锁和外键约束。 它的设计的目标是处理大容量数据库系统&#xff0c;用于缓冲数据和索引。 不支持FULLTEXT类型的数据&#xff0c;没有保存表的行数&#xff0c;当s…

C++总结笔记(九)—— 多态

文章目录一、多态是什么&#xff1f;二、使用步骤2.1. 静态多态2.1.1 函数重载2.1.2 模板2.2.动态多态2.2.1 示例2.2.2 原理分析总结一、多态是什么&#xff1f; 多态是面向对象的语言中都必须掌握的特性&#xff0c;其概念简单讲就是对同一种特性的方法有不同的实现功能&…

组件局域网中的无集线器、Windows XP、Windows 7、Windows 8的对等网

为什么要用对等网&#xff1f; 答&#xff1a;对等网采用分散管理的方式&#xff0c;网络中的每台计算机既作为客户机又可作为服务器来工作&#xff0c;每个用户都管理自己机器上的资源。 组建局域网中无集线器的对等网 组建局域网中Windows XP的对等网 组建局域网中Windows 7的…

阿里巴巴将赴NIPS 2017 3大事业部联袂展示AI全技能

被誉为国际顶级的机器学习和神经网络学术会议NIPS 2017将于12月4日-9日在美国加州长滩市举行。在本届会议上&#xff0c;阿里巴巴除有两篇论文入选Workshop并进行Oral和Poster形式报告外&#xff0c;3大技术事业部将连续3天&#xff08;5日-7日&#xff09;在阿里展区举行多场技…

360安全卫士加速球误关闭某个应用软件

近期因为工作原因须要使用金山快盘。但因为之前电脑上安装了360安全卫士&#xff0c;在使用加速球功能的时候&#xff0c;会出现&#xff0c;误关闭金山快盘的操作&#xff0c;怎么避免呢&#xff1f; 1、打开360主界面。找到安全防护中心&#xff0c;例如以下图&#xff1a; 2…

20145238-荆玉茗 《信息安全系统设计基础》第7周学习总结

20145238 《信息安全系统设计基础》第7周学习总结 教材学习内容总结 存储器系统 : 存储器系统是一个具有不同容量、成本和访问时间的存储设备的层次结构。 1、RAM随机访问存储器 分类&#xff1a;SRAM&#xff08;静态&#xff09;、DRAM&#xff08;动态&#xff09;特点&…

关于两个jar包中存在包名和类名都完全相同的jar包冲突问题

2019独角兽企业重金招聘Python工程师标准>>> 最近弄webservice&#xff0c;我使用的jdk自带的wsimport工具来生成客户端代码&#xff0c;发现生成的代码具有编译错误&#xff0c;错误描述如下&#xff1a; The method getPort(QName, Class<T>) in the type S…

const和define 区别

1&#xff1a; 编译器处理不同 define宏是在预处理阶段展开&#xff0c;const常量是编译运行阶段使用。 2&#xff1a;类型和安全检查不同 const常量有数据类型&#xff0c;而宏常量没有数据类型&#xff0c;仅仅是展开。编译器可以对前者进行类型安全检查&#xff0c;而对后者…

【项目实战】——Python打包正装换底色代码为exe文件(可在其他无Python环境下运行)

目录 1.安装pyinstaller 2.生成.exe文件 方法1&#xff1a; 方法2&#xff1a; 方法3&#xff1a; &#xff08;1&#xff09;使用命令行窗口进入项目的根目录 &#xff08;2&#xff09;在改目录下执行pyi-makespec main.py&#xff08;main.py是你的主入口文件&#x…

安装完最小化 RHEL/CentOS 7 后需要做的 30 件事情(三)码农网

12. 安装 Apache Tomcat Tomcat 是由 Apache 设计的用来运行 Java HTTP web 服务器的 servlet 容器。按照下面的方法安装 tomcat&#xff0c;但需要指出的是安装 tomcat 之前必须先安装 Java。 # yum install tomcat 安装 Apache Tomcat 安装完 tomcat 之后&#xff0c;启动 to…

QT5.14.2基于PCL1.11.1显示点云(基于Windows VS2019开发环境)

文章目录一、安装1.1 PCL安装1.2 QT安装1.3 VTK编译二、程序配置1. 基于mscv创建QT的程序2. 配置QT工程文件和依赖项3. 编写点云显示的小程序总结一、安装 1.1 PCL安装 PCL1.11.1库的安装网上教程很多&#xff0c;推荐一个很好的教程&#xff1a; Win10 系统下 VisualStudio2…