应用竞赛树结构模拟实现外排序(C++实现)

2023-05-16

基本要求

(1)设计实现最小输者树结构 A D T ADT ADT A D T ADT ADT 中应包括初始化、返回赢者、重构等基本操作。
(2)设计实现外排序,外部排序中的生成最初归并串以及 K K K 路归并都用最小输者树结构实现;
(3)随机创建一个较长的文件;设置归并路数以及缓冲区的大小;获得外排序的访问磁盘的次数并进行分析,可采用小文件来模拟磁盘块。

问题分析

(1)设计并实现最小输者树
(2)应用最小输者树结构实现生成初始顺串
(3)应用最小输者树结构实现 K K K 路归并
(4)随机生成较长文件,设置归并路数以及缓冲区大小,对以上操作进行分析验证。

设计思路

(1)调整输者树
将新进入输者树的节点与其父节点进行比较,把败者所对应的索引存在父节点中,赢者再与上一层的父节点进行比较,直到比较到根结点,最后将败者存在 t r e e [ 1 ] tree[1] tree[1] 中,赢者存在 t r e e [ 0 ] tree[0] tree[0] 中。
(2)构建输者树(初始化)
将初始化输者树的过程转换为调整输者树的过程,假设外部结点为 l e a v e [ 0 , … , k ] leave[0,…,k] leave[0,,k],先指定 k k k m i n min min 即设置 l e a v e [ k ] leave[k] leave[k] 为比赛的胜者,然后将所有的内部结点置为 k k k,最后从 0 0 0 k − 1 k-1 k1,重构输者树,即可得到初始输者树。
(3)利用输者树生成初始顺串
假设输者树的结点个数为 k k k,从输入集合中输入前 k k k 个元素并初始化这些元素的顺串号均为 1 1 1,建立这 k k k 个选手的最小输者树,并重复以下过程,直至所有元素都输出到对应的顺串中。
(i) 将赢者 W W W 移入它顺串号所对应的顺串中;
(ii) 若输入集合中有下一个输入元素,则 N = N= N= 下一个输入元素,否则 N = ∞ N=∞ N=
(iii) 如果 N N N 的元素值 ≥ W ≥W W 的元素值,则 N N N 的顺串号 = W = W =W 的顺串号,否则 N N N 的顺串号 = W = W =W 的顺串号 + 1 +1 +1
(iiii) N N N 代替 W W W,重构输者树。
(4)利用输者树进行 K K K 路归并
从外部文件中读取 K ∗ B U F _ S I Z E K*BUF\_SIZE KBUF_SIZE 个元素,分别放入 K K K个输入缓冲区中,以每个缓冲区中的第一个元素构建输者树,每次将赢者移至输出缓冲区中,然后调整输者树。当输出缓冲区满时,将数据块写入外存,当输入缓冲区空时,再从外存中读入一个数据块,重复上述过程,直至读取到文件结束,即完成K路归并。

测试结果

以随机生成一个数据量为100000的文件进行测试为例:
在这里插入图片描述
利用内排序生成测试文件test.txt

#include <bits/stdc++.h>
using namespace std;
int main()
{
	freopen("input.txt","r",stdin);
	freopen("test.txt","w",stdout);
	int a[100010];
	int idx=0,n;
	while(cin>>n){
		a[idx++]=n;
	}
	sort(a,a+idx);
	for(int i=0;i<idx;i++){
		cout<<a[i]<<" ";
	}
}

比较temp34.txt与test.txt:
在这里插入图片描述
之后又测试了数据量分别为1000,10000,1000000的文件,结果均正确。

分析与探讨

为了进一步研究输者树应用在外排序中的优势,又进行了以下实验:
在这里插入图片描述
缓冲区大小均为1024的情况下输者树与快速排序生成的初始顺串个数对比:
在这里插入图片描述
外排序所需要的时间由内部排序所需要的时间、外存信息读写所需要的时间、内部归并所需要的时间三部分组成,其中减少外存信息的读写次数是提高外部排序效率的关键。而对于同一个文件来说,进行外排序所需读写外存的次数与归并趟数有关,为了减少归并趟数,可以从减少初始顺串的个数、增加归并的路数两个方面着手。

  • 生成初始顺串
    在缓冲区大小相同的条件下,利用输者树生成的初始顺串个数明显少于快速排序, 这是因为快速排序得到的顺串的编号与容量是固定的,而输者树根据相应的赢者规则,每次取出胜者后,对树重构,新加入的元素的顺串号由其元素值与胜者元素值的大小关系所决定,从而尽可能通过动态比较增加了每个初始顺串的容量,使得初始顺串个数减少。
  • K路归并
    假设归并路数为 k k k,外部文件中的数据个数为 n n n,如果只是简单地进行线性比较,取 k k k 路中的最小,那么时间复杂度为 O ( n ∗ k ) O(n*k) O(nk)。若采用输者树,初始化时,首先将内部节点初始化为 k k k, 时间复杂度为 O ( k ) O(k) O(k) n n n 次移入和替代赢者共需耗时 O ( n ∗ l o g k ) O(n*logk) O(nlogk),故总的时间复杂度为 O ( k + n l o g k ) O(k+nlogk) O(k+nlogk),从而提高了 k k k 路归并的性能。
  • 增加归并路数
    分析以上实验数据可得,在数据量和缓冲区大小一定时,适当地增加归并路数,会减少初始顺串的数量与访问外存的次数,从而加快外排序的速度;但是当归并路数k无限增大时,输入缓冲区的个数也会随之增多,在内存短缺的情况下,每个缓冲区的容量会相应的减少,从而会使得内外存交换数据的次数增加(加载顺串到输入缓冲区的次数增多),因此 k k k 值的设定要根据实际内存的大小而定,过多地增加 k k k 值,虽然会减少归并次数,但会使程序的运行效率降低。

代码实现

#include <iostream>
#include <cstdio>
#include <cstdlib> 
#include <algorithm>
#include <cstring>
#include <string>
#include <climits>
#include <fstream>
using namespace std;

int Count;		//待排序文件的数据个数 
int BUF_PAGES;  //缓冲区有多少个page 
int PAGE_SIZE; //page的大小 
int BUF_SIZE;//BUF_PAGES*PAGE_SIZE; //缓冲区大小
char* input_file;//输入文件名  

//缓冲区 
struct Page{
	int *arr; 
	int current; //当前顺串扫描的位置 
	Page(){
		current=0;
	}
	Page(int bufsize){
		arr=new int[bufsize+1];
		current=0;
	}
};

//选手 
struct player{
	int id;//编号 
	int element;//元素 
	//赢者规则 
	friend bool operator<(const player &s1,const player &s2){
		if(s1.id!=s2.id)
			return s1.id<s2.id;
			
		else
			return s1.element<s2.element;
	}
	//重载运算符 = 
	player& operator=(const player &s){
		id=s.id;
		element=s.element;
		return *this;
	} 
}; 

//输者树 
class LoserTree{
	public:
		LoserTree(){}
		~LoserTree(){}
		//初始化 
		void Initialize(int kk);
		//返回赢者 
		int Winner(){return tree[0];}
		//重构 
		void Adjust(int s);
		void Adjust(int *,player *,int ,int);
		//快排生成顺串 
		void Generate_1(); 
		//输者树生成顺串 
		void Generate_2(); 
		//K路归并 
		void K_Merge(int start,int k);
		//外排序
		void ExternSort(int k);  
		//读数据块
		int Read_Data_Block(FILE* file, int a[], int n);
		//写数据块
		void Write_Data_Block(FILE* file, int a[], int n); 
		//获取临时文件名称 
		char* Get_Filename(int index); 
	private: 
    	int *tree;	//内部结点 
		int *leave; //外部结点          
    	int k;      //选手个数  
		int file_count;	//临时文件数目	 	
};

//获取临时文件名称 
char* LoserTree::Get_Filename(int index){
    char *tempname=new char[100];
    sprintf(tempname,"temp%d.txt",index);
    return tempname;
}

//从外存中读数据块 
int LoserTree::Read_Data_Block(FILE* file, int a[], int n){
    int i=0;
    while(i<n&&(fscanf(file,"%d",&a[i]))!=EOF)
        i++;
    return i;
}

//往外存中写数据块 
void LoserTree::Write_Data_Block(FILE* file, int a[], int n){
    for(int i=0;i<n;i++)
        fprintf(file,"%d ",a[i]);
    fprintf(file,"%d",INT_MAX);
}

//初始化 
void LoserTree::Initialize(int kk){
	k=kk;
	leave[k]=INT_MIN;
	for(int i=0;i<k;i++)
		tree[i]=k;
	for(int i=0;i<k;i++)
		Adjust(i);
}

//重构输者树 
void LoserTree::Adjust(int s){
	//父节点 
	int t=(s+k)>>1;
	//向上调整 
	while(t>0){
		if(leave[s]>leave[tree[t]]){ 
			s^=tree[t];
			tree[t]^=s;
			s^=tree[t];
		}
		t>>=1;
	}
	tree[0]=s;
}

//利用快速排序生成顺串 
void LoserTree::Generate_1(){
    FILE* fin=fopen(input_file,"rt");
    int n=0;
	file_count=0;
	//内部缓冲区 
    int* array=new int[BUF_SIZE/2];
    while ((n=Read_Data_Block(fin, array, BUF_SIZE/2))>0){
        sort(array, array+BUF_SIZE/2);
        char* filename=Get_Filename(file_count++);
        FILE* tempfile=fopen(filename,"w");
        free(filename);
        Write_Data_Block(tempfile,array,n);
        fclose(tempfile);
    }
    delete[] array;
    fclose(fin);
	cout<<file_count<<endl;
}

//重构输者树 
void LoserTree::Adjust(int *tree,player *leave,int s,int k){
	int t=(s+k)>>1;
	while(t>0){
		if(leave[tree[t]]<leave[s]){
			s^=tree[t];
			tree[t]^=s;
			s^=tree[t];
		}
		t>>=1;
	}
	tree[0]=s;	
}

//输者树生成顺串 
void LoserTree::Generate_2(){
	file_count=0;
	int K=BUF_SIZE/2;
	int Tree[K];
	player Leave[K+1];
	int OutputNum=Count/BUF_SIZE+10;
	//文件输出流 
	ofstream out[OutputNum]; 
	for(int i=0;i<OutputNum;i++){
		char* tmp=Get_Filename(i);
		out[i].open(tmp,ios::app);
	}
	//文件输入流 
	ifstream in;
	in.open(input_file);
	if(!in.is_open()){
		cout<<"错误:当前目录下该文件不存在!"<<endl;
		exit(0);
	}
	for(int i=0;i<K;i++){
		in>>Leave[i].element;
		Leave[i].id=0;		
	}  
	//初始化输者树 
	Leave[K].element=INT_MIN;
	Leave[K].id=-1;
	for(int i=0;i<K;i++)
		Tree[i]=K;
	for(int i=0;i<K;i++)
		Adjust(Tree,Leave,i,K);
	int maxid=0;
	//输者树排序 
	while (Leave[Tree[0]].element!=INT_MAX){
		int p=Tree[0];
		file_count=max(file_count,Leave[p].id);
		out[Leave[p].id]<<Leave[p].element<<" ";
		//读到文件尾 
		if(in.eof()){
			Leave[p].element=INT_MAX;
			Leave[p].id=INT_MAX;
			in.close();
		} 
		//读入新元素并确定顺串号 
		else{
			int element;
			in>>element;
			if(element<Leave[p].element){
				Leave[p].id++;
			}
			Leave[p].element=element;
		}
		//重构输者树 
		Adjust(Tree,Leave,p,K);
    }
	file_count++;		
	//添加 ∞作为终止符 
    for(int i=0;i<file_count;i++){
		out[i]<<INT_MAX;
		out[i].close();    	
	}		
}

//K路合并 
void LoserTree::K_Merge(int start,int k){
	int count=file_count-start;
	if(count<=1)
		return;
	int runs=count/k;
	int cur=file_count; 
	if(count%k!=0)
		runs++;
	int cnt=runs;
	int j=start;
	int K=k;
	//执行runs次k路归并 
	while(cnt--){
		k=min(K,cur-j);
		ifstream in[k];
		//读取当前要归并的临时文件 
		for (int i=0;i<k;i++){
			char* tmp=Get_Filename(j++);
			in[i].open(tmp);
		}		
		//输入缓冲区 
		Page Buffer[k];
		for(int i=0;i<k;i++){
			Buffer[i]=Page(BUF_SIZE);
		}
		//从外存读入缓冲区 
		for(int i=0;i<k;i++){
			int num=0;
		    while(num<PAGE_SIZE&&!in[i].eof()){
				in[i]>>Buffer[i].arr[num];
				num++;
			}
			Buffer[i].current=0;
		}
		//读取外部节点 
		for(int i=0;i<k;i++){
			leave[i]=Buffer[i].arr[0];
			Buffer[i].current++;
		}
		//初始化输者树 
		Initialize(k);
		int p;
		//输出缓冲区 
		int res[PAGE_SIZE];
		int idx=0;
		char* outputfile=Get_Filename(file_count);
		ofstream out(outputfile);	
		//输者树排序	
		while (leave[tree[0]] != INT_MAX){
			p=tree[0];  //p为当前最小关键字所在的顺串 
			res[idx++]=leave[p];
			//输出缓冲区已满,将数据块写入外存 
			if(idx==PAGE_SIZE){
				for(idx=0;idx<PAGE_SIZE;idx++){
					out<<res[idx]<<" ";
				} 
				idx=0;
			}
			//输入缓冲区已空,从外存读入数据块 
			if(Buffer[p].current>=PAGE_SIZE){
				int num=0;
			    while (num<PAGE_SIZE&&!in[p].eof()){
					in[p]>>Buffer[p].arr[num];
					num++;
				}
				Buffer[p].current=0;
				leave[p]=Buffer[p].arr[Buffer[p].current];
				Buffer[p].current++;				
			}
			//继续读取缓冲区 
			else{
				leave[p]=Buffer[p].arr[Buffer[p].current];
				Buffer[p].current++;
			}
			//重构输者树 
			Adjust(p);
        }
        //输出缓冲区剩余内容写入外存 
		for(int oidx=0;oidx<idx;oidx++){
			out<<res[oidx]<<" ";
		}
		//终止符 
		out<<INT_MAX;
		//关闭文件流 
		for (int i=0;i<k;i++){
			in[i].close();
		}
		out.close();
		file_count++;
	}
	//进行下一轮归并 
	K_Merge(j,K);
}

//外排序 
void LoserTree::ExternSort(int K){
		double time=0;  
		double counts=0;  
		LARGE_INTEGER nFreq;  
		LARGE_INTEGER nBeginTime;  
		LARGE_INTEGER nEndTime;  
		QueryPerformanceFrequency(&nFreq);  
		QueryPerformanceCounter(&nBeginTime);//开始计时 
		//生成初始顺串 
        Generate_2();	
        k=K;
        tree = new int[k];
        leave = new int[k+1];
		//K路归并		
		K_Merge(0,K);
		cout<<endl; 
		cout<<"外排序成功!"<<endl;
		cout<<"结果存于temp"<<file_count-1<<".txt"<<endl;
		QueryPerformanceCounter(&nEndTime);//停止计时  
		time=(double)(nEndTime.QuadPart-nBeginTime.QuadPart)/(double)nFreq.QuadPart;//计算程序执行时间单位为s  
		cout<<"运行时间:"<<time*1000<<"ms"<<endl;
		//释放内存空间 
        delete[] tree;
        delete[] leave;	
        
}

//主程序 
int main()
{
	//创建输者树 
	LoserTree a;
	//指定输入文件
	cout<<"请输入要进行外排序的文件名称:";
	string Input_File;
	cin>>Input_File;
	input_file=(char*)Input_File.c_str();
	//指定待排序的文件大小
	cout<<"请输入待排序文件的大小(数据个数):";
	cin>>Count;
	cout<<"请输入缓冲区大小(上限1,000,000):";
	cin>>BUF_SIZE;
	if(BUF_SIZE<0||BUF_SIZE>1000000){
		cout<<"错误:输入缓冲区不合法!"<<endl;
		exit(0);
	}
	//指定归并路数 
	cout<<"请输入归并路数:";
	int ways;
	cin>>ways;
	BUF_PAGES=ways+1;
	PAGE_SIZE=BUF_SIZE/BUF_PAGES;
	cout<<endl;
	//执行外排序 
	a.ExternSort(ways);
	return 0;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

应用竞赛树结构模拟实现外排序(C++实现) 的相关文章

  • [week15] B - ZJM与生日礼物(选做)—— 字典树

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 ZJM 收到了 Q老师 送来的生日礼物 xff0c 但是被 Q老师 加密了 只有 ZJM 能够回答对 Q老师 的问题 xff0c Q老师 才会把密码告诉 ZJM
  • [week15] C - ZJM与纸条(选做)—— KMP算法

    文章目录 题意InputOutput输入样例输出样例提示 分析总结代码 题意 ZJM 的女朋友是一个书法家 xff0c 喜欢写一些好看的英文书法 有一天 ZJM 拿到了她写的纸条 xff0c 纸条上的字暗示了 ZJM 的女朋友 想给 ZJM
  • 51按键外部中断控制流水灯

    实验二 外部按键输入 一 实验目的 1 了解单片机检测口方法 2 了解单片机外部中断原理 3 了解按键输入原理 二 实验内容 1 完成按键扫描控制流水灯 2 完成按键外部中断控制流水灯 三 实验原理 四 实验电路与程序 1 软件实验一 xf
  • 树莓派4B构建debian镜像UEFI启动

    树莓派4B构建debian镜像UEFI启动 前言 今天按照大佬的博客树莓派俱乐部官方 Debian 系统镜像 支持UEFI跑了遍 完整的UEFI镜像构建过程 包括镜像分区 挂载 xff0c 根文件系统的制作 xff0c 内核的移植 xff0
  • Linux修改主机名问题

    记一次修改主机名不成功原因 场景 虽然使用hostname命令可以修改主机名 xff0c 但如果重启主机之后主机名还会变为之前的 xff0c 所以需要把修改的主机名称写到配置文件中 假设修改后的主机名为 new hostname 1 修改配
  • mybatisPlus分页插件报错,sql后面拼接多了一个limit。

    原本 用的mybatisPlus版本为3 1 0 xff0c 后来升级到3 4 2了 xff0c 使用分页的时候报错 解决 xff1a mybatisPlus 3 1 0 所用到的分页插件为 而mybatisPlus 3 4 2版本pagi
  • Deep Knowledge Tracing (深度知识追踪)

    boss又让我看这块的内容了 xff0c 刚开学 xff0c 还不太适应实验室的学习生活 xff0c 假期闲散惯了操 目录 1 概述2 表示3 1 DKT的优势3 2 DKT的不足4 模型5 序列的输入和输出输入输出 6 优化及应用7 三个
  • C程序代码

    一 C语言概述有算法 1 输出一行信息 span class token macro property span class token directive hash span span class token directive keyw
  • 【C语言-10】.求10 个整数中最大值。 (数组定义法和函数调用法)

    数组定义法 首先定义一个一维数组存放输入的数字 xff0c 然后将键盘输入的数字依次存入一维数组 xff1b 假定数组中某一元素为最大值 xff0c 将其与其他元素逐一比较 xff0c 得到最大的数为max值 xff1b 最后得到的max为
  • 【工程实践】解决 nvcc: command not found

    1 nvcc nvcc 是The main wrapper for the NVIDIA CUDA Compiler suite Used to compile and link both host and gpu code NVIDIA
  • hdu 5119(dp题)

    题目链接 xff1a http acm hdu edu cn showproblem php pid 61 5119 题目 xff1a Matt has N friends They are playing a game together
  • word(doc/docx)转markdown:使用Typora的插件

    打开你的Typora xff0c 选择文件 gt 导入 第一次导入会让你下载 pandoc 插件 下载链接如下 xff1a https github com jgm pandoc releases download 2 14 1 pando
  • 案例描述:update中,MySQL inner join 和 left join的区别,小结果集驱动大结果集

    场景描述 以一个场景为例 xff1a 单据A xff1a 下游子表 xff08 数据量级小 xff09 单据B xff1a 下游主表 xff08 数据量级小 xff09 单据C xff1a 中游子表 xff08 数据量级小 xff09 单据
  • Hadoop生态圈(一)- Hadoop详解

    目录 前言1 Hadoop概述1 1 Hadoop是什么1 2 Hadoop发展简史1 2 Hadoop三大发行版本1 3 Hadoop优势1 4 Hadoop的组成1 4 1 Hadoop1 x 2 x 3 x区别1 4 2 HDFS架构
  • arduino硬件总结

    文章目录 arduino硬件总结串口通讯I2CSPI中断函数基本了解实现测速 ADC读取光敏传感器的值 pwm舵机控制 arduino硬件总结 arduino 支持中断 xff0c ADC PWM xff0c I2C xff0c spi x
  • 文件上传 - Apache SSI远程命令执行

    文章目录 一 漏洞原理二 漏洞场景 挖掘思路三 触发条件四 漏洞复现4 1 启动环境4 2 访问环境4 3 复现过程 五 防御措施 一 漏洞原理 在测试任意文件上传漏洞的时候 xff0c 目标服务端可能不允许上传php jsp asp后缀的
  • Linux:chmod -R 777 *含义

    Linux xff1a chmod R 777 首先 xff0c chmod命令是linux上用于改变权限的命令 xff0c R 是递归遍历子目录 xff0c 因为你要操作的文件使用的 通配符 777 xff0c 第一个7代表文件所属者的权
  • STM32HAL库学习笔记七——I2C通信

    HAL库快速部署I2C 本文主要介绍如何使用STM32CubeMX快速部署I2C通信 xff0c 并与EEPROM进行数据收发 文章目录 HAL库快速部署I2CI2C简介EEPROM简介HAL库部署IIC通信实现多字节写入一 CubeMX配
  • python报错Statements must be separated by newlines or semicolons解决方法

    今天做练习时遇到这样的报错 xff1a Statements must be separated by newlines or semicolons 翻译一下就是 xff1a 语句必须用换行符或分号分隔 首先按报错提示 xff0c 我把cl
  • python自然语言处理之spacy详解

    spaCy简介 spaCy号称工业级Python自然语言处理 xff08 NLP xff09 软件包 xff0c 可以对自然语言文本做词性分析 命名实体识别 依赖关系刻画 xff0c 以及词嵌入向量的计算和可视化等 spaCy模块有4个非常

随机推荐

  • anaconda创建env报错 ResolvePackageNotFound

    具体错误 如图 xff1a 按照其他博主 xff08 方法详情 xff09 提供的方法操作了还是有部分报错 xff1a 解决策略 继续上面解决剩下的部分报错 xff0c 打开 yaml文件 xff0c 记事本打开就行 将报错列出的几个包移到
  • LDA主题建模过程及参数详解

    平台及工具 语言 xff1a python 平台 xff1a anaconda 43 jupyter notebook 语料库 xff1a 近三百篇英文文献的摘要 主要代码 首先 xff0c pandas处理csv数据 span class
  • 已经成功安装了但是jupyter notebook仍然找不到模块

    问题描述 工具 语言 jupyter notebook 43 anaconda python 有时会遇到这样的情况 xff0c 命名已经install了模块 xff0c notebook还是报找不到模块错误 再装已经提示satisfied
  • pyecharts 地图绘制

    环境描述 win11 jupyter notebook 目标效果 世界地图 43 按数据进行分级着色 xff1b 最终效果图如下 xff1a pyecharts 绘制地图时注意点 可以实现目标地图绘制效果的python库很多 xff0c 这
  • 指定wb用户在指定日期范围内的wb内容抓取

    一 操作步骤 只记录过程 xff0c 不讲述原理 1 获取用户ID和cookie 用户ID在进入个人主页时导航栏中就会有显示 xff0c 例如下面这样 xff1a cookie获取 xff08 有的代码无需cookie也能运行 xff09
  • 中介变量、调节变量与协变量

    在平时看论文过程中偶会接触到这几个概念 xff0c 然而都没想过弄明白 xff0c 每次总觉得只要看明白个大概反正自己又不用这种方法 作为科研人 xff0c 还是应该保持谦逊 xff0c 保持学习 一 中介变量 1 概念 中介变量 xff0
  • linux环境搭建

    文章目录 linux环境搭建基础工具环境docker镜像docker 的基本操作git amp amp sshbash脚本 python 环境 linux环境搭建 基础工具环境 docker镜像 Docker CE 镜像源站 docker如
  • 【Linux】状态机

    Linux 状态机 首先感谢阅读 xff0c 作者是在工作中学习与积累 xff0c 每一个笔记都是心得和积累 xff0c 希望可以和大家一起交流学习 学习咱们先定好计划 xff0c 需要了解的都一样 xff0c 有 xff1a xff08
  • MyBatisPlus源码

    MyBatisPlus源码 文章目录 MyBatisPlus源码1 通用Mapper 96 BaseMapper 96 2 顶级Mapper 96 Mapper 96 3 通用Service 96 IService 96 4 通用Servi
  • bomb二进制炸弹拆除实验(MIPS)

    上学期计算机系统基础课程的一个实验 xff0c 在这里再简略整理一下 xff1a 实验要求 xff1a 仅给定一个MIPS二进制可执行文件bomb xff0c 要求运用GDB调试工具 xff0c 通过分析反汇编代码来输入正确的参数以拆除炸弹
  • 图与网络可视化实战(matlab实现)

    本篇以2020年数学建模美赛D题的足球传球网络可视化为例 xff0c 分三大步骤来简单讲解一下matlab在图与网络可视化方面的应用 xff1a Step1 构图 xff1a 首先根据输入数据构造邻接矩阵 xff0c 然后调用matlab中
  • Week8 - 程序设计思维与实践 - HRZ的序列(第二次CSP模拟T1)

    T1 HRZ的序列 该比赛已结束 xff0c 您无法在比赛模式下递交该题目 您可以点击 在题库中打开 以普通模式查看和递交本题 题目描述 相较于咕咕东 xff0c 瑞神是个起早贪黑的好孩子 xff0c 今天早上瑞神起得很早 xff0c 刷B
  • Week8 - 程序设计思维与实践 - HRZ学英语(第二次CSP模拟T2)

    T2 HRZ学英语 该比赛已结束 xff0c 您无法在比赛模式下递交该题目 您可以点击 在题库中打开 以普通模式查看和递交本题 题目描述 瑞神今年大三了 xff0c 他在寒假学会了英文的26个字母 xff0c 所以他很兴奋 xff01 于是
  • Week14 - 程序设计思维与实践 - 矩阵快速幂(+优化DP)

    题目连接 A Q老师与石头剪刀布 xff08 必做 xff09 题意 每一个大人曾经都是一个小孩 xff0c Q老师 也一样 为了回忆童年 xff0c Q老师 和 Monika 玩起了石头剪刀布的游戏 xff0c 游戏一共 n 轮 无所不知
  • Week14 - 程序设计思维与实践 - HDU3700 - Cat(限时模拟)

    Problem Description There is a cat cat likes to sleep If he sleeps he sleeps continuously no less than A hours For some
  • SDU《程序设计思维与实践》课程个人感想

    这门课到此也就宣告结束了呀 xff0c 回想过去居家学习的 16 周真的是既辛酸又充实 由于是非竞赛生 xff0c 之前没怎么接触过算法刷题这一方面 xff0c 唯一学的点算法也是来自上学期的数据结构 xff0c 回想刚开始上这门课的时候
  • 跳表的实现、分析以及可视化(Qt C++、Graphviz)

    演示程序截图 实现功能 跳表初始化跳表的查找操作跳表的插入操作跳表的删除操作 xff08 指定关键字的元素 关键字最小的元素 关键字最大的元素 xff09 跳表可视化 程序结构设计 初始化模块 xff1a void Initializati
  • 1、stm32F103入门学习--开发环境搭建(一)

    stm32简介 这款是网上销量比较多的板子 xff0c 我找板子主要还是看价格 xff0c 20元左右 xff0c 不需要太贵 xff0c 只是做个核心入门 xff0c 不要太多的外设 xff0c 特别是对初学者 xff0c 因为从来没见过
  • 森林与二叉树之间的转换以及可视化演示(C++实现)

    演示程序截图 基本要求 构造并实现森林的ADT和二叉树ADT xff0c 森林ADT中应包括初始化 插入元素 删除元素 xff0c 插入边 xff0c 删除边 xff0c 转换成二叉树 xff0c 显示森林及对应的二叉树等基本操作 xff0
  • 应用竞赛树结构模拟实现外排序(C++实现)

    基本要求 xff08 1 xff09 设计实现最小输者树结构 A D T ADT A D T xff0c A D