【数据结构】实验一:绪论

实验一  绪论

一、实验目的与要求

1)熟悉C/C++语言(或其他编程语言)的集成开发环境;

2)通过本实验加深对算法时间复杂度的理解;

3)结合具体的问题分析算法时间复杂度。

二、实验内容

设计程序实现统计一个班的学生成绩(学生的人数可以设置3000、5000、8000、10000等测试数据),要求自行设计至少两种排序算法,实现如下四个功能;记录每种算法的耗时,结合数据结构的知识对两种算法的时间复杂度进行比较说明。

(1) 输入每个学生的学号,并随机生成2门课程的成绩;

(2) 计算每个学生的平均成绩和总成绩;

(3) 按总成绩从高到低排名,并按名次输出每个学生情况,包括:

     学号,各科成绩,平均成绩,总成绩,排名

(4) 由键盘输入课程号,输出该课程成绩在90分(含90分)以上且总分在前3名的学生情况,要求能多次查询。

三、实验步骤

1)程序中可能遇到的头文件如下

#include<Windows.h>                 //windows头文件

#include<iostream>                  //引入一个流类库

#include<stdio.h>                   //标准输入输出头文件

#include<time.h>                    //导入时间库函数文件

2)提示代码

int array_Sort[ARRAY_MAXSIZE];      //声明待排序的数组

int array_Sort2[ARRAY_MAXSIZE];

for(int i=0;i<=ARRAY_MAXSIZE;i++){   //生成随机数组,大小为10000

......

    }

for(int j=0;j<ARRAY_MAXSIZE;j++){    //生成递减数组,大小均为10000 

......

    }

clock_t start,end;                  //声明开始和结束的时间计数器

start=clock();                      //排序开始时间计数器

end=clock();                        //排序结束时间计数器

cout<<(double)(end-start)<<" ms"<<endl;//排序的时间

3)请将调试成功的源代码粘贴在下面

 TEST:

#include<Windows.h>                 //windows头文件
#include<iostream>                  //引入一个流类库
#include<stdio.h>                   //标准输入输出头文件
#include<time.h>                    //导入时间库函数文件
#include<cstring>
#include<cstdlib>
using namespace std;class Student{int ** student;//二维数组:指针的指针 int x,y;//坐标 
public://构造Student(int temp=0){x=temp;y=5;student=new int *[x];//坐标x int i=0;for(i=0;i<x;i++){student[i]=new int [y];//坐标y }}//输出void Show(){int i=0;for(i=0;i<x;i++){cout<<"学号:"<<student[i][0]<<"科目一成绩:"<<student[i][1]<<"科目二成绩:"<<student[i][2]<<"平均成绩:"<<student[i][3]<<"总成绩:"<<student[i][4]<<"排名:"<<student[i][5]+1<<endl; //student[i][5]初始化为i,输出时候+1}} //随机生成void Data(){int i=0;for(i=0;i<x;i++){student[i][0]=i;//学号 student[i][1]=rand()%100;//科目一成绩 student[i][2]=rand()%100;//科目二成绩 student[i][3]=(student[i][1]+student[i][2])/2;//平均分 student[i][4]=student[i][1]+student[i][2];//总分}} //总分排序:冒泡 void Rank(){int *temp,i=0,j=0;clock_t start,end;//声明开始和结束的时间计数器start=clock();//排序开始时间计数器for(i=0;i<x-1;i++){//外层,n个元素n-1次 for(j=0;j<x-i-1;j++){//内层,n个元素n-i次 if(student[j][4]<student[j+1][4]){temp=student[j];student[j]=student[j+1];student[j+1]=temp;}}}end=clock();//排序结束时间计数器cout<<"冒泡排序法所用时间:"<<(double)(end-start)<<" ms"<<endl;//排序的时间for(i=0;i<x;i++){student[i][5]=i;//初始化排名 }}//总分排序:选择void rank(){int *temp,maxno,i=0,j=0;clock_t start,end;//声明开始和结束的时间计数器start=clock();//排序开始时间计数器for(i=0;i<x-1;i++){//x个数,循环x-1次 maxno=i;//假设第i个最小 for(j=i+1;j<x;j++){if(student[j][4]>student[maxno][4]){maxno=j;}}temp=student[i];student[i]=student[maxno];student[maxno]=temp;}end=clock();//排序结束时间计数器cout<<"选择排序法所用时间:"<<(double)(end-start)<<" ms"<<endl;//排序的时间for(i=0;i<x;i++){student[i][5]=i;//初始化排名 }}//第四问1.0 /*void Problem(int subject=0){Student.rank();int num=0;//统计总分前三名 int flag=0;//标记符合条件存在情况 for(num=0;num<3;num++){if(student[num][subject]>=90){//第i个人这门课符合条件cout<<"学号:"<<student[num][0]<<"科目一成绩:"<<student[num][1]<<"科目二成绩:"<<student[num][2]<<"平均成绩:"<<student[num][3]<<"总成绩:"<<student[num][4]<<"排名:"<<student[num][5]<<endl;flag=1; }} if(flag==0){cout<<"该课程成绩在90分(含90分)以上且总分在前3名的学生不存在" <<endl;}}*//*//析构~Student(){int i=0;for(i=0;i<x;i++){delete [] student[i];student[i]=NULL;//删除指针的指针 }delete [] student;student=NULL;//删除指针 }*///第四问2.0 void Problem(int subject=0){int num=0;//统计总分前三名的counter int flag=0;//标记符合条件存在情况 for(num=0;num<3;num++){if(student[num][subject]>=90){//第i个人这门课符合条件cout<<"学号:"<<student[num][0]<<"科目一成绩:"<<student[num][1]<<"科目二成绩:"<<student[num][2]<<"平均成绩:"<<student[num][3]<<"总成绩:"<<student[num][4]<<"排名:"<<student[num][5]+1<<endl;flag=1; }} if(flag==0){cout<<"该课程成绩在90分(含90分)以上且总分在前3名的学生不存在" <<endl;}}
};int main(){cout<<"请输入学生人数:";int myx;cin>>myx;Student test(myx);//调用构造test.Data();//调用随机生成test.Rank();//调用冒泡test.Show();cout<<"请输入查询次数:";int checktime;cin>>checktime;int time; for(time=1;time<=checktime;time++){cout<<"请输入查询科目(科目一输入1,科目二输入2):";int sub;cin>>sub;test.rank();//调用选择 test.Problem(sub);//输出问题四的结果 }return 0;
}

4)运行结果分析

1.数组大小ARRAY_MAXSIZE为10000如下(截图运行结果):

 

 2.数组大小ARRAY_MAXSIZE为8000如下(截图运行结果):

 

 

 3.数组大小ARRAY_MAXSIZE为5000如下(截图运行结果):

 

 

 4.数组大小ARRAY_MAXSIZE为3000如下(截图运行结果):

 

 

两种算法时间性能分析表:

方法

最好情况

最坏情况

平均情况

冒泡排序

10000人:277ms

8000人:165ms

5000人:53ms

3000人:17ms

10000人:281ms

8000人:170ms

5000人:57ms

3000人:17ms

10000人:279ms

8000人:167.5ms

5000人:55ms

3000人:17ms

简单选择排序

10000人:150ms

8000人:87ms

5000人:26ms

3000人:9ms

10000人:150ms

8000人:96ms

5000人:26ms

3000人:10ms

10000人:150ms

8000人:91.5ms

5000人:26ms

3000人:9.5ms

请针对上表进行分析与说明

分析:

在人为设置总人数为10000人、8000人、5000人、3000人的四个案例中,冒泡排序法的运算时间均大于简单选择排序法的运算时间,且总体来看冒泡排序法的运算时间是简单选择排序法的运算时间的1.5倍~2倍。

说明:

为了分析上述表格的结果,我们设元素个数为length,对上述表格的两种排序算法作如下的简要理解:

冒泡排序法运算法则为——从第一个值开始,依次轮询,相邻的两个数依次比较,如果大于(正序排序)或者小于(倒序排序)则交换位置,即每一次轮询都会把最大的一个数冒泡到最后,轮询次数为length-1,每次轮询的长度都会减1。

简单选择排序法运算法则为——从第一个值开始,依次轮询,每次轮询把当前值替换为最大值,轮询次数为length-1,每次轮询的长度都会减1。

通过对比我们容易发现,两种排序算法的时间复杂度都为O(n²),但二者的排序理念和结果大不相同,对此作以下两点分析与说明:

首先,从程序设计的思路来看,冒泡排序法通过相邻两个元素的逐一对比,从而进行大小排序,而简单选择排序法是以当前元素为基准,将其和后面的元素之一对比,在一定程度上会使得相同值的元素比较过程中两个元素的相对前后顺序位置受到影响。因而冒泡排序法相比于简单选择排序法而言在算法的思路理解和具体的编程过程上更为简单且容易理解,在实际运算的过程中更为稳定。

其次,从运算时间的长短来看,在内循环中,冒泡排序法每次都要交换元素的顺序,而简单选择排序法则只需要记录元素的下标,在一轮的比较只需要换一次位置。因而冒泡排序法的效率比简单选择排序法的效率低。上述表格的四种案例冒泡排序法的运算时间是简单选择排序法的运算时间的1.5倍~2倍的具体运算结果也证实了这条结论。

综上所述,在所需计算量较小或者是对运算时间无具体要求的情况下,我们可以优先选择冒泡排序法进行实践;在所需计算量较大或者是要求运算时间尽可能小的情况下,我们可以优先选择简单选择排序法进行实践。


其他参考代码:

#include<Windows.h>                 //windows头文件
#include<iostream>                  //引入一个流类库
#include<stdio.h>                   //标准输入输出头文件
#include<time.h>                    //导入时间库函数文件
#include<iomanip>
#include<cstdlib>#define ARRAY_MAXSIZE 5000         //定义学生的人数
#define STR_LENGTH 5
#define CLASS 2                     //课程数量using namespace std;class Student{
private:string id;char classnum[CLASS];int scores[4];int rank;
public:Student();//学生信息的初始化void init1(int num);//产生随机数排序void init2(int num);//产生递减数列排序void setrank(int ran);int getrank();int getscore1();int getscore2();string getinfo();//显示学生的信息//运算符重载           friend bool operator<(const Student& s1,const Student& s2);//比较总成绩friend bool operator>(const Student& s1,const Student& s2);
};
Student::Student(){id="2021";classnum[0]='D';classnum[1]='S';for(int i=0;i<4;i++){scores[i]=0;}rank=0;
}
void Student::init1(int num){//随机//id初始化string temp=to_string(num);//id初始化id+=string(STR_LENGTH - temp.length(), '0');//前面补零id+=temp;//成绩初始化for(int i=0;i<CLASS;i++){scores[i]=rand()%101;}scores[2]=(scores[0]+scores[1])/2;scores[3]=scores[0]+scores[1];
}
void Student::init2(int num){//递减//id初始化string temp=to_string(num);//id初始化id+=string(STR_LENGTH - temp.length(), '0');//前面补零id+=temp;//成绩初始化scores[0]=100-0.01*num;scores[1]=100-0.01*num;scores[2]=(scores[0]+scores[1])/2;scores[3]=scores[0]+scores[1];
}void Student::setrank(int ran){rank=ran;
}int Student::getrank(){return rank;
}int Student::getscore1(){return scores[0];
}int Student::getscore2(){return scores[1];
}string Student::getinfo(){string info;string temp[4];for(int i=0;i<4;i++){temp[i]=to_string(scores[i]);}string str0=string(3 - temp[0].length(), ' ')+temp[0];string str1=string(3 - temp[1].length(), ' ')+temp[1];string str2=string(3 - temp[2].length(), ' ')+temp[2];string str3=string(3 - temp[3].length(), ' ')+temp[3];info="学号:"+id+"科目D成绩:"+str0+"科目S成绩:"+str1+"平均成绩:"+str2+"总成绩:"+str3+"排名"+to_string(rank);return info;
}bool operator<(const Student& s1,const Student& s2){return s1.scores[3]<s2.scores[3];
}
bool operator>(const Student& s1,const Student& s2){return s1.scores[3]>s2.scores[3];
} void bubble_sort(Student arr[]){       //冒泡排序//计算排序的时间clock_t start,end;               //声明开始和结束的时间计数器start=clock();      //排序开始时间计数器                   int i, j;for (i = 0; i < ARRAY_MAXSIZE - 1; i++){for (j = 0; j < ARRAY_MAXSIZE - 1 - i; j++){if (arr[j] < arr[j + 1]){Student temp;temp=arr[j];arr[j]=arr[j+1];arr[j+1]=temp;}        }}end=clock();                        //排序结束时间计数器cout<<"当前排序方法为冒泡排序"<<endl;cout<<"*************************"<<endl;cout<<"排序时间为:"<<setfill(' ')<<setw(10)<<(double)(end-start)<<" ms"<<endl;
}void insertion_sort(Student arr[]){     //插入排序//计算排序的时间clock_t start,end;                  //声明开始和结束的时间计数器start=clock();                      //排序开始时间计数器                       for(int i=1;i<ARRAY_MAXSIZE;i++){Student key=arr[i];int j=i-1;while((j>=0) && (key<arr[j])){arr[j+1]=arr[j];j--;}arr[j+1]=key;}end=clock();                        //排序结束时间计数器cout<<"当前排序方法为插入排序"<<endl;cout<<"*************************"<<endl;cout<<"排序时间为:"<<setfill(' ')<<setw(10)<<(double)(end-start)<<" ms"<<endl;
}void selection_sort(Student arr[]){     //选择排序//计算排序的时间clock_t start,end;                  //声明开始和结束的时间计数器start=clock();                      //排序开始时间计数器     for (int i = 0; i < ARRAY_MAXSIZE - 1; i++) {int min = i;for (int j = i + 1; j < ARRAY_MAXSIZE; j++)if (arr[j] > arr[min])min = j;Student temp;temp=arr[i];arr[i]=arr[min];arr[min]=temp;}end=clock();                        //排序结束时间计数器cout<<"当前排序方法为插入排序"<<endl;cout<<"*************************"<<endl;cout<<"排序时间为:"<<setfill(' ')<<setw(10)<<(double)(end-start)<<" ms"<<endl;
}int main(){Student arrOfStu[ARRAY_MAXSIZE];while(1){//初始界面的展示cout<<"当前学生人数为:"<<setfill(' ')<<setw(15)<<ARRAY_MAXSIZE<<"人"<<endl;cout<<"********************************"<<endl;cout<<"1.进行学生学号成绩随机初始化****"<<endl<<endl;cout<<"2.进行学生学号成绩递减初始化****"<<endl<<endl;cout<<"3.进行学生成绩的排序        ****"<<endl<<endl;cout<<"4.按成绩从高到低输出学生情况****"<<endl<<endl;cout<<"5.输入课程号输出优秀学生    ****"<<endl<<endl;//输出该课程成绩在90分(含90分)以上且总分在前3名的学生情况,要求能多次查询cout<<"********************************"<<endl;int cho;cin>>cho;switch(cho){case 0:cout<<"欢迎下次使用"<<endl;//system("pause");return 0;break;case 1:srand((unsigned)time(NULL));for(int i=0;i<ARRAY_MAXSIZE;i++){arrOfStu[i].init1(i);}cout<<"随机初始化完成"<<endl;system("pause");system("cls");break;case 2:for(int i=0;i<ARRAY_MAXSIZE;i++){arrOfStu[i].init2(i);}cout<<"递减初始化完成"<<endl;system("pause");system("cls");break;case 3://排序的不同方法//bubble_sort(arrOfStu);//insertion_sort(arrOfStu);selection_sort(arrOfStu);for(int i=0;i<ARRAY_MAXSIZE;i++){arrOfStu[i].setrank(i+1);}system("pause");system("cls");break;case 4:if(arrOfStu[0].getrank()!=0){for(int i=0;i<ARRAY_MAXSIZE;i++){cout<<arrOfStu[i].getinfo()<<endl;}system("pause");system("cls");break;}else{cout<<"成绩未排名请排名后再操作"<<endl;system("pause");system("cls");break;}case 5:while(1){char c;cout<<"请输入课程号\n输入E结束"<<endl;cin>>c;if(c=='D'){if(arrOfStu[0].getrank()!=0){for(int i=0;i<3;i++){if(arrOfStu[i].getscore1()>=90){cout<<arrOfStu[i].getinfo()<<endl;}}}else{cout<<"成绩未排名请排名后再操作"<<endl;system("pause");system("cls");break;}}else{if(c=='S'){if(arrOfStu[0].getrank()!=0){for(int i=0;i<3;i++){if(arrOfStu[i].getscore2()>=90){cout<<arrOfStu[i].getinfo()<<endl;}}}else{cout<<"成绩未排名请排名后再操作"<<endl;system("pause");system("cls");break;}}else{if(c=='E'){break;}else{cout<<"输入错误请再次输入"<<endl<<endl;}}}}system("pause");system("cls");break;default:cout<<"输入错误,请再次输入"<<endl;system("pause");system("cls");break;}}return 0;
}

 

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

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

相关文章

深入学习 redis - Stream、Geospatial、HyperLogLog、Bitmap、Bitfields 类型扩展

目录 前言 Stream geospatial HyperLogLog Bitmaps Bitfields 前言 redis 中最关键的五个数据类型 String、List、Hash、Set、Zset 应用最广泛&#xff0c;同时 redis 也推出了额外的 5 个数据类型&#xff0c;他们分别是针对特殊场景才进行的应用的. Ps&#xff1a;这几种…

odoo16-domain

odoo16-domain 参考:https://blog.csdn.net/u013250491/article/details/86699928 domain的使用注意以下几点: 是在py文件中使用还是在xml中使用,py文件是在后端使用可以利用orm, 而xml是在前端渲染,使用的是js,没有办法使用orm如果在xml中使用,domain的格式建议为[[]], 二维…

Paragon NTFS2023最新版Mac读写NTFS磁盘工具

Paragon NTFS for Mac是Mac平台上一款非常优秀的读写工具&#xff0c;可以在Mac OS X中完全读写、修改、访问NTFS硬盘、U盘等外接设备的文件。这款软件最大的亮点简书可以让我们读写 NTFS 分区&#xff0c;因为在Mac OS X 系统上&#xff0c;默认状态下我们只能读取NTFS 分区&a…

速成版-带您一天学完python自动化测试(selenium)

Selenium是一套web网站的程序自动化操作解决方案。我们通过编写自动化程序&#xff0c;使得自动完成浏览器界面的相关操作&#xff0c;除了能够自动化的完成相关操作&#xff0c;还能从web页面获取相关信息&#xff0c;然后通过程序进行分析处理&#xff0c;本质上就是提升从网…

25.5 matlab里面的10中优化方法介绍——牛顿法(matlab程序)

1.简述 1 牛顿法简介 牛顿迭代法&#xff08;Newton’s method&#xff09;又称为牛顿-拉夫逊&#xff08;拉弗森&#xff09;方法&#xff08;Newton-Raphson method&#xff09;&#xff0c;它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。 多数方程不存…

【spring】spring bean的生命周期

spring bean的生命周期 文章目录 spring bean的生命周期简介一、bean的创建阶段二、bean的初始化阶段三、bean的销毁阶段四、spring bean的生命周期总述 简介 本文测试并且介绍了spring中bean的生命周期&#xff0c;如果只想知道结果可以跳到最后一部分直接查看。 一、bean的…

图像滤波器

图像噪声 • 图像噪声是图像在获取或是传输过程中受到随机信号干扰&#xff0c;妨碍人们对图像理解及分析处理 的信号。 • 图像噪声的产生来自图像获取中的环境条件和传感元器件自身的质量&#xff0c;图像在传输过程中产 生图像噪声的主要因素是所用的传输信道受到了噪声…

【技术架构】技术架构的演进

文章目录 前言1.名词解释(常见概念)1.1 应用&#xff08;Application&#xff09; / 系统&#xff08;System&#xff09;1.2 模块&#xff08;Module&#xff09; / 组件&#xff08;Component&#xff09;1.3 分布式&#xff08;Distributed&#xff09;1.4 集群&#xff08;…

机器学习 day30(正则化参数λ对模型的影响)

λ对Jcv和Jtrain的影响 假设该模型为四阶多项式当λ很大时&#xff0c;在最小化J的过程中&#xff0c;w会很小且接近0&#xff0c;此时模型f(x)近似于一个常数&#xff0c;所以此时模型欠拟合&#xff0c;Jtrain和Jcv都很大当λ很小时&#xff0c;表示模型几乎没有正则化&…

5.2.tensorRT基础(2)-使用onnx解析器来读取onnx文件(源码编译)

目录 前言1. ONNX解析器2. libnvonnxparser.so3. 源代码编译4. 补充知识总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 t…

Rocky Linux 8.4在Tesla P100服务器里的部署及显卡cudnn安装-极度精简

安装Rocky linux教程 https://developer.aliyun.com/article/1074889 注意事项 Tesla P100服务器&#xff0c;按Delete进入bios,设置Daul模式&#xff0c;第一选项选UEFI hard disk(用驱动盘选这个)&#xff0c;usb的就选UEFI usb 安装rocky linux时&#xff0c;这两项默认&…

css中flex后文本溢出的问题

原因&#xff1a; 为了给flex item提供一个合理的默认最小尺寸&#xff0c;flex将flex item的min-width 和 min-height属性设置为了auto flex item的默认设置为&#xff1a; min-width&#xff1a; auto 水平flex布局 min-height&#xff1a;auto 垂直flex布局 解决办法&…

【ICCV2023】Scale-Aware Modulation Meet Transformer

Scale-Aware Modulation Meet Transformer, ICCV2023 论文&#xff1a;https://arxiv.org/abs/2307.08579 代码&#xff1a;https://github.com/AFeng-x/SMT 解读&#xff1a;ICCV2023 &#xff5c; 当尺度感知调制遇上Transformer&#xff0c;会碰撞出怎样的火花&#xff1…

【Nodejs】Node.js简介

1.前言 Node 的重要性已经不言而喻&#xff0c;很多互联网公司都已经有大量的高性能系统运行在 Node 之上。Node 凭借其单线程、异步等举措实现了极高的性能基准。此外&#xff0c;目前最为流行的 Web 开发模式是前后端分离的形式&#xff0c;即前端开发者与后端开发者在自己喜…

Gitlab 合并分支与请求合并

合并分支 方式一&#xff1a;图形界面 使用 GitGUI&#xff0c;右键菜单“GitExt Browse” - 菜单“命令” - 合并分支 方式二&#xff1a;命令行 在项目根目录下打开控制台&#xff0c;注意是本地 dev 与远程 master 的合并 // 1.查看本地分支&#xff0c;确认当前分支是否…

2、HAproxy调度算法

HAProxy的调度算法可以大致分为以下几大类&#xff1a; 静态算法&#xff1a;这类算法的调度策略在配置时就已经确定&#xff0c;并且不会随着负载的变化而改变。常见的静态算法有&#xff1a; Round Robin(轮询) Least Connections(最少连接数) Static-Weight(静态权重) Sourc…

QSlider 样式 Qt15.15.2 圆形滑块

在看文档的时候测试了一下demo&#xff0c;然后发现了一个有意思的东西&#xff0c;自定义滑块为带边框的圆形。 在设置的时候边框总是和预期的有点误差&#xff0c;后来发现了这样一个计算方式可以画一个比较标准的圆。&#xff08;ABCDEF在下方代码块内&#xff09; 滑块的…

Kubernetes 之CNI 网络插件大对比

介绍 网络架构是Kubernetes中较为复杂、让很多用户头疼的方面之一。Kubernetes网络模型本身对某些特定的网络功能有一定要求&#xff0c;但在实现方面也具有一定的灵活性。因此&#xff0c;业界已有不少不同的网络方案&#xff0c;来满足特定的环境和要求。 CNI意为容器网络接…

【iOS】—— 持久化

文章目录 数据持久化的目的iOS中数据持久化方案数据持久化方式分类内存缓存磁盘缓存 沙盒机制获取应用程序的沙盒路径沙盒目录的获取方式 持久化数据存储方式XML属性列表Preferences偏好设置&#xff08;UserDefaults&#xff09;数据库存储什么是序列化和反序列化&#xff0c;…

Hadoop概念学习(无spring集成)

Hadoop 分布式的文件存储系统 三个核心组件 但是现在已经发展到很多组件的s 或者这个图 官网地址: https://hadoop.apache.org 历史 hadoop历史可以看这个: https://zhuanlan.zhihu.com/p/54994736 优点 高可靠性&#xff1a; Hadoop 底层维护多个数据副本&#xff0c;所…