插入排序,选择排序,交换排序,归并排序和非比较排序(C语言版)

news2024/12/23 11:24:46

前言

        所谓排序,就是将一组数据按照递增或者递减的方式进行排列,让这组数据变得有序起来。排序在生活中运用的是十分广泛的,各行各业都用到了排序,比如我们在网购的时候就是按照某种排序的方式来选择东西的。所以去了解排序的实现也就是很重要的了。

目录

1.排序的概念

2.常见的排序算法

3.常见的排序算法的实现

        3.1插入排序

                3.1.1直接插入排序 

                3.1.2希尔排序 

        3.2选择排序

                3.2.1堆排序

                3.2.2直接选择排序  

        3.3交换排序

                3.3.1冒泡排序

                3.3.2快速排序 

        3.4归并排序

                3.4.1归并排序 

                3.4.2归并排序应用-外排序

        3.5非比较排序 

4.排序算法的复杂度及稳定性的分析  


1.排序的概念

        排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小按照一定的规律变成递增或者递减的序列。

        稳定性: 假定待排序的记录序列中,存在多个具有相同关键字的记录,经过排序后这些记录的相对次序没有发生变化,即在原序列中r[i] = r[j],且r[i]在r[j]之前,而在排序后r[i]任在r[j]之前,则称这种排序算法是稳定的,否则就是不稳定的。

        内排序:数据元素全部放在内存中的排序。

        外排序:数据元素太多不能同时放在内存中,根据排序过程中的要求能在内外存之间移动数据的排序。

2.常见的排序算法

         

3.常见的排序算法的实现

        3.1插入排序

        基本思想:把待排序的记录按其关键码值逐个插入到一个已经排好序的有序序列中,直到所有的序列插完为止,得到一个新的有序序列。

        实际上我们在玩扑克排的时候,就用到了插入排序的思想。

         

                3.1.1直接插入排序 

        当插入第i个元素的时候前面的array[0],array[1],…,array[i-1]已经排好序,此时用arryy[i]的排序码与array[i -1],array[i-2],array[i-3],...的排序码顺序比较找到插入的位置即将array[i]插入,原来位置上的元素顺序后移。

        比较过程,如果是排升序,先与当前值比较,如果比当前值小就和当前值的前一个元素比较,如果比当前值的前一个元素大,就插入到当前值的前一个元素的后面,如果比当前值的前一个元素小,继续去前面进行比较,知道找到合适的位置进行插入,如果是最小的,那么就要插入到数组的开头。如图:

void InsertSort(int* a, int n)//升序排序
{
	assert(a);
	for (int i = 0; i < n - 1; ++i)
	{
		int end = i;
		int tmp = a[end + 1];//保存数据,后面移动的时候数据会被覆盖
		while (end >= 0)
		{
			if (a[end] > tmp)
			{
				a[end + 1] = a[end];//将数据向后移动空出位置
				--end;//迭代继续向前比较
			}
			else
			{
				break;//插入到
			}
		}
		a[end + 1] = tmp;
	}
}

        直接插入排序的特性总结:

        1.时间复杂度为O(N*2)。

        2.排序的序列越接近有序,时间复杂度越低。

        3.稳定性:稳定。

        4.空间复杂度O(1),它是一种稳定的排序。

        实现代码:

                3.1.2希尔排序 

        希尔排序又称缩小增量排序法。希尔排序的基本思想是:先选定一个整数,把待排序的文件中所记录分成一个个组,所有距离为gap的记录在一个组内,并对每一组内的记录进行排序。然后,重复上述分组和排序的工作。当gap = 1时,所以记录统一排好序。

        说白了,希尔排序从直接插入排序找突破口,虽然直接插入排的时间复杂度很高,但是直接插入排序在有序或者接近有序的情况下,效率会是很好的,那么怎么样让它接近有序呢?这就要采用预排序了。通过预排序让数组接近有序,最后一次在进行直接插入排序,就会很快,通过这样的方式 希尔排序对直接插入排序进行了很好的优化。

        希尔排序分为两步:

        1.对数组进行预排序

        将数组按照间隔gap分为很多组,先对间隔为gap的组进行排序,使得间隔为gap的是有序的,然后缩小间隔gap。在重复上述过程。 

        2.直接插入排序

        当gap等于1时,就相当于是直接插入排序啦,听起来是不是很简单啊,hhhh。

 

        如图:

        

//希尔排序
void ShellSort(int* a, int n)
{
	assert(a);//确保指针不为空
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;//保证最后一次排序的间隔是1,进过计算gap按照三分之一减少是最优的
		for (int i = 0; i < n - gap; ++i)//排升序
		{
			int end = i;
			int tmp = a[end + gap];//防止数据被覆盖
			while (end >= 0)
			{
				if (a[end] > tmp)
				{
					a[end + gap] = a[end];//移动数组,继续在前面比较
					end = end - gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;//将数据插入到数组中
		}
		Print(a, 10);
		printf("  gap = %d\n", gap);
		printf("\n");
	}
	
}

        希尔排序的特性总结

        1.希尔排序是对直接插入排序的优化。

        2. 当gap大于1的时候都是预排序,目的是让数组更接近有序。当gap == 1时,数组已经接近有序了,这样就可以很快的排出来了。这样的话整体而言可以达到优化的效果。我们实现后可以进行性能测试的对比。

        3.希尔排序的时间复杂度不好计算,因为gap的取值有很多方法,导致很难去计算,因此在很多书里面希尔排序的时间复杂度都不固定。

 

        因为这里的gap是按照Knuth的方法取值的,所以暂时按照来计算。

         

        3.2选择排序

        基本思想:每次从待排序的数据中选出最小(或者最大的元素),存放到序列的起始位置,直到待排序的数组排序完为止。 

                3.2.1堆排序

        详见:堆排序 

                3.2.2直接选择排序  

         排升序:在元素集合array[i]-array[n-1],选择关键码子最大(最小)的数据元素。

        若它不是这组元素中的最后一个 (第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换。

        在剩余的array[i]--array[n -2](array[i+1] --array[n-1])集合中重复上述步骤,直到集合剩下一个元素。

void SelectSort(int* a, int n)
{
	assert(a);//确保a存在
	//排升序
	int left = 0;
	int right = n - 1;
	while (left < right)
	{
		int maxDex = right;
		int minDex = left;
		//遍历剩余的数组每次找出最大的和最小的将最大的换到n-1的位置,将最小的放到j位置
		for (int i = left; i <= right; ++i)
		{
			if (a[maxDex] < a[i] )
			{
				maxDex = i;//记录最大值的下标
			}
			if (a[minDex] > a[i]  )
			{
				minDex = i;//记录最小值的下标
			}
		}
		Swap(&a[minDex], &a[left]);
		if (left == maxDex)//说明最大值的下标在最左边,上一步的交换让最大值已经不是最左边,而是下标minDex
			maxDex = minDex;
		Swap(&a[maxDex], &a[right]);
		left++;
		right--;
	}
}

         它的时间复杂度是O(n*n)。

void SelectSort(int* a, int n)
{
	assert(a);//确保a存在
	//排升序
	int left = 0;
	int right = n - 1;
	while (left < right)
	{
		int maxDex = right;
		int minDex = left;
		//遍历剩余的数组每次找出最大的和最小的将最大的换到n-1的位置,将最小的放到j位置
		for (int i = left; i <= right; ++i)
		{
			if (a[maxDex] < a[i] )
			{
				maxDex = i;//记录最大值的下标
			}
			if (a[minDex] > a[i]  )
			{
				minDex = i;//记录最小值的下标
			}
		}
		Swap(&a[minDex], &a[left]);
		if (left == maxDex)//说明最大值的下标在最左边,上一步的交换让最大值已经不是最左边,而是下标minDex
			maxDex = minDex;
		Swap(&a[maxDex], &a[right]);
		left++;
		right--;
	}
}

        3.3交换排序

                3.3.1冒泡排序

        详见 冒泡排序

                3.3.2快速排序 

        详见快速排序 

        快速排序除了递归的实现方法外,还有非递归的实现方法,那么,如何通过非递归来实现快排的呢? 让我们一起来试试吧,我们都知道递归的方法实现快排是通过函数调用栈帧来实现的,其实非递归也是通过模拟函数调用栈帧的过程,通过数据结构的栈来模拟实现的。

        虽然数据结构的栈和操作系统的栈不是一会事情,但是它们的性质是相同的(后进先出),如何通过栈来模拟实现呢?

        代码: 

// 快速排序 非递归实现
void QuickSortNonR(int* a, int begin, int end)
{
	//创建并初始化栈
	Stack st;
	StackInit(&st);
	//将区间[left,right]入栈
	StackPush(&st, end);
	StackPush(&st, begin);
	//通过栈来模拟快排递归时的调用
	//数据结构实现的栈和操作系统的栈的特性是一样的
	while (!StackEmpty(&st))
	{
		int left = StackTop(&st);
		StackPop(&st);
		int right = StackTop(&st);
		StackPop(&st);//如栈的时候先右后左,出栈的时候先左后右
		int midi = PartSort1(a, left, right);//对子区间进行快速排序的单趟排序
		
		//将左右子区间都入栈
		if (midi + 1 < right)//右边区间至少存在一个数
		{
			StackPush(&st, right);
			StackPush(&st, midi + 1);
		}
		if (left < midi - 1)//左边区间至少存在一个数
		{
			StackPush(&st, midi - 1);
			StackPush(&st, left);
		}
	}
	StackDestory(&st);
}

        3.4归并排序

                3.4.1归并排序 

                 归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个典型应用,将已经有序的子序列合并,得到完全有序的的序列;即先使每个子序列都有序,在合并子序列使得整个区间有序,若将两个有序表合并成一个有序表,称为二路归并,归并排序的核心步骤:

代码:

//单趟归并排序
void _MergeSortSignal(int *a, int begin1, int end1, int begin2, int end2, int *tmp)//闭区间
{
	int begin = begin1;//保存数组起始的位置方便拷贝
	tmp = (int*)malloc(sizeof(int) * (10 + 1));
	int i = begin1;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	//将剩下的一个数组尾插到tmp
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	for (int j = begin ; j <= end2; ++j)
	{
		a[j] = tmp[j];
	}

	free(tmp);

 }
// 归并排序递归实现
void _MergeSort(int* a, int left, int right, int * tmp)
{
	if (left >= right)//区间只剩下一个数
	{
		return;
	}
	int midi = (left + right) / 2;
    _MergeSort(a, left, midi, tmp);
	_MergeSort(a, midi + 1, right, tmp);
    //合并有序的小区间
	_MergeSortSignal(a, left, midi, midi + 1, right, tmp);

}
void MergeSort(int* a, int n)
{
	//int* tmp = (int*)malloc( sizeof(int) * n);
	_MergeSort(a, 0, n - 1,NULL);//闭区间[left,right]
	//free(tmp);
}

 

        归并排序的非递归法: 

        如果采用栈来模拟会将问题变得复杂,通过上面的图,我们不难发现归并排序是将要排序的区间不断缩小的过程直到要排序的区间变得有序,那么怎么样是一定有序的呢,我们不难发现,如果区间只有一个数的时候一定是有序的,所以我们采取这个思路,刚开始让相邻的连个数进行归并,此时间隔gap为一,下一次,相邻的两个数已经有序了,那么此时要将区间长度为2的相邻的两个子区间归并为一个有序的区间,此时gap = 2,依次类推增大gap就行了,什么时候结束呢,直到gap大于等于数组的长度时,数组肯定是有序的。这时候在进行归并已经没有意义了。

        注意:划分子区间进行合并的时候,有可能第二个区间的长度小于第一个区间的长度,或者第二个区间不存在,因此需要注意,对第二个区间的边界进行修正或者只有第一个子区间时,这次就不需要归并排序了。

//将两个有序小区间合并为一个
void _MergeSortSignal(int *a, int begin1, int end1, int begin2, int end2, int *tmp)//闭区间
{
	int begin = begin1;//保存数组起始的位置方便拷贝
	tmp = (int*)malloc(sizeof(int) * (10 + 1));
	int i = begin1;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
	//将剩下的一个数组尾插到tmp
	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	for (int j = begin ; j <= end2; ++j)
	{
		a[j] = tmp[j];
	}

	free(tmp);

 }
// 归并排序非递归实现
void MergeSortNonR(int* a, int n)
{
	//实现思路:这里如果借助栈来模拟会将问题变得复杂起来,所以可以采取循环的方式
	//直接归并,第一次是相邻的两个数归并,这时候gap为1,第二次gap为而就是区间[i,i+gap-1] 和区间[i+gap,i+2*gap -1]进行插入排序,依次类推
	//直到gap不小于数组的长度就结束
	int gap = 1;
	while (gap < n)
	{
		//单趟归并排序
		for (int i = 0; i < n;++i)
		{
			//采用闭区间
			//[i,i+gap-1] 和[i+gap,i+2*gap]
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;

			//调用将两个数组合并成一个数组的函数
			if (begin2 >= n)
			{
				break;//说明要排序第二组不存在,只有第一组,本次不需要再排
			}
			if (end2 >= n)
			{
				//需要修正第二组的边界
				end2 = n - 1;
			}
			_MergeSortSignal(a, begin1, end1, begin2, end2, NULL);
		}
		gap *= 2;
	}
}

 

                3.4.2归并排序应用-外排序

           归并排序和其他几种排序不太一样,其它几种排序适合在内存中进行排序,而归并排序不仅可以在内存中进行排序,当数据很多时,多到内存中放不下,只能存放到文件中此时其它的排序都不怎么好用,但是归并排序却可以对数据进行排序并且是在文件中进行,所以归并排序也是外排序。

        现在模拟一种场景,假设,有海量的数据,这些数据无法一次加载到内存中,现在请你编写一个程序对这些数据进行排序,并将结果保存在文件中。

        思路是:

        1.首先我们需要将这些数据划分成很多份,并且划分出来的每一份都可以一次性加载到内存中并且进行排序。

        2.将划分好的数据一次存放到子文件中,并且使用快排将这些数据变得有序。

        3.此时已经满足归并排序的先决条件,每个子序列都是有序的,此时我们只需要每次读取两个文件中的数据将它们比较并且合并到一个新的文件中,如法炮制直到最后将所有的有序子区间合并成一个文件,此时这个文件中的数据都是有序的。

        

代码:

//将两个文件中的有序数据合并到一个文件中并且保持有序
void _MergeFile(const char* file1, const char* file2, const char* mfile)
{
	FILE* fout1 = fopen(file1, "r");
	if (fout1 == NULL)
	{
		printf("fout1打开文件失败\n");
		exit(-1);
	}
	FILE* fout2 = fopen(file2, "r");
	if (fout2 == NULL)
	{
		printf("fout2打开文件失败\n");
		exit(-1);
	}
	FILE* fin = fopen(mfile, "w");
	if(fin == NULL)
	{
		printf("fin打开文件失败\n");
		exit(-1);
	}
	int num1, num2;
	int ret1 = fscanf(fout1, "%d\n", &num1);
	int ret2 = fscanf(fout2, "%d\n", &num2);
	//在文件中读数据进行归并排序
	while (ret1 != EOF && ret2 != EOF)
	{
		if (num1 < num2)
		{
			fprintf(fin, "%d\n", num1);
			//再去fout1所指的文件中读取数据
			ret1 = fscanf(fout1, "%d\n", &num1);
		}
		else
		{
			fprintf(fin, "%d\n", num2);
			//再去fout2所指的文件中读取数据
			ret2 = fscanf(fout2, "%d\n", &num2);
		}
	}
	while (ret1 != EOF)
	{
		fprintf(fin, "%d\n", num1);
		
		ret1 = fscanf(fout1, "%d\n", &num1);
	}
	while (ret2 != EOF)
	{
		fprintf(fin, "%d\n", num2);
		
		ret2 = fscanf(fout2, "%d\n", &num2);
	}
	fclose(fout1);
	fclose(fout2);
	fclose(fin);
}
void MergeSortFile(const char* file)//文件归并排序
{
	//打开文件
	FILE* fout = fopen(file, "r");
	if (fout == NULL)
	{
		printf("打开文件失败\n");
		exit(-1);
	}
	int n = 10;
	int a[10] = { 0 };
	char subr[1024] ;
	/*memset(subr, 0, 1024);
	memset(a, 0, sizeof(int) * n);*/

	int num = 0;
	int i = 0;
	int fileI = 1;
	while (fscanf(fout, "%d\n",&num )!=EOF)
	{
		if (i < n - 1)
		{
			a[i++] = num;
		} 
		else
		{
			a[i] = num;
			QuickSort(a, 0, n - 1);//对内存中的数据进行排序
			sprintf(subr, "%d", fileI++);
			FILE* fin = fopen(subr, "w");
			if (fin == NULL)
			{
				printf("打开文件失败\n");
				exit(-1);
			}
			//写数据到文件中
			for (int j = 0; j < n; ++j)
			{
				fprintf(fin, "%d\n", a[j]);
			}
			//关闭文件
			i = 0;//置零对下一组数据进行操作
			/*memset(subr, 0, 1024);
			memset(a, 0, sizeof(int) * n);*/
			fclose(fin);
		}
		
	}

	//外排序
	//利用互相归并到文件中,实现整体有序

	char file1[100] = "1";
	char file2[100];
	char mfile[100] = "12";
	for (int i = 2; i <= n; ++i)
	{
		sprintf(file2, "%d", i);
		//读取FIle和file2,进行归并排序出mfile
		_MergeFile(file1, file2, mfile);

		strcpy(file1,mfile);
		sprintf(mfile, "%s%d", mfile, i + 1);
	}
	fclose(fout);
	return NULL;
}

 

        3.5非比较排序 

        非比较排序顾名思义就是不用对元素进行比较就可以进行排序了,这里介绍的是计数排序, 

计数排序又叫鸽巢原理,是对哈希直接定值法的变形应用。操作步骤:

        1.统计相同元素出现的次数

        2.根据统计结果将序列回收到原来的序列中

 

代码:

// 计数排序
void CountSort(int* a, int n)
{
	//先遍历数组,找出最大值和最小值用来确定范围
	int max = a[0];
	int min = a[0];
	for (int i = 0; i < n; ++i)
	{
		if (max < a[i])
		{
			max = a[i];
		}
		if (min > a[i])
		{
			min = a[i];
		}
	}
	//然后根据最大值和最小值的范围开辟空间
	int range = max - min + 1;
	int* CountArray = (int*)calloc(sizeof(int), range);
	//统计原数组中每个数出现的次数
	for (int i = 0; i < n; ++i)
	{
		CountArray[ a[i] - min ] ++ ;//利用相对位置来计算数据出现的个数
	}
	/*Print(CountArray, 9);
	printf("\n");*/

	//将临时数组中的数,覆盖到原数组中
	int j = 0;
	for (int i = 0; i < range; ++i)
	{
		while (CountArray[ i ]--)
		{
			a[j++ ] = i + min;//将每个数据从临时数组中拿出来加上相对数据min,然后对数组进行覆盖
		}
	}
	//释放临时开辟的空间
	free(CountArray);
}

 

        计数排序的特性总结:

  1.计数排序在数据范围集中时,效率很高,但是适用范围和场景有限。

  2.时间复杂度O(max(N ,范围))

  3.空间复杂度O(范围)

   

4.排序算法的复杂度及稳定性的分析  

         

        什么是稳定性呢,通俗的来说就是相同元素在进过排序后它们在数组中的相对位置不变,那么稳定或者不稳定有什么影响呢?在一些特殊的场景下是有影响的,比如,在一场考试中,要给前三名颁奖,如何确定前三名呢?比如前五名的成绩分别是:99 98 97 97 97,这些的情况下,是无法直接确定前三名的,因为第三,四,五名的成绩是相同的,那么这时候还有另一条规定就是这场比赛中成绩相同时,用时短 的在前面。那么这样的话,通过稳定的排序就可以确定前三名且对大家都是公平的,但是如果是不稳定的排序,这个结果是不公平的。 

        选择排序是不稳定的,如果在一组序列中出现多个相同的最大值,选择哪一个就是问题,或者是下图这种情况: 

        堆排序也是不稳定的,在建堆或者选数的时候要进行向下调整,向下调整的时候可能会改变相同元素的相对顺序,如图: 

         快速排序也是不稳定的,因为在选某个基准进比较时,可能相对顺序就会发生改变。        

        希尔排序也是不稳定的,因为在预排序时,相同的数可能被分到不同的组,所以它们的相对次序就没有办法保证了。计数排序因为是统计原来数组中每个元素出现的次数,所以相同元素的相对位置是没有办法保证的。 

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

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

相关文章

vue 使用qrcode生成二维码并可下载保存

安装qrcode npm install qrcode --save代码 <template><div style"display: flex; flex-direction: column; align-items: center; justify-content center;"><div>查看溯源码&#xff0c;<a id"saveLink" style"text-decorati…

Ae 效果:CC Glue Gun

生成/CC Glue Gun Generate/CC Glue Gun CC Glue Gun&#xff08;CC 胶水枪&#xff09;可以用于生成仿佛由胶水枪绘制的线条或图案&#xff0c;它模拟了胶水枪绘制在不同表面上的纹理和反光效果。 CC Glue Gun 效果实质上是通过设置画笔笔触的位置来构成画笔描边路径&#xff…

ModaHub魔搭社区专访百度智能云李莅:向量数据库市场会不会更卷?

ModaHub魔搭社区:在当今的信息化时代,数据库技术已经渗透到了我们生活的各个角落。传统的关系型数据库在市场上的竞争已经非常激烈,据统计,市面上有数百种不同类型的数据库产品在竞争。那么,在未来,随着人工智能和大数据技术的发展,向量数据库市场会否也会陷入同样的激烈…

js中如何判断一个变量的数据类型?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐typeof 运算符⭐instanceof 运算符⭐Object.prototype.toString 方法⭐Array.isArray 方法⭐自定义类型检查⭐null 和 undefined 检查⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订…

ClickHouse进阶(七):Clickhouse数据查询-1

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术,IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &#x1f4cc;订阅…

RK3568-i2c-适配8010rtc时钟芯片

硬件连接 从硬件原理图中可以看出&#xff0c;rtc时钟芯片挂载在i2c3总线上&#xff0c;设备地址需要查看芯片数据手册。编写设备树 &i2c3 {status "okay";rx8010: rx801032 {compatible "epson,rx8010";reg <0x32>;}; };使能驱动 /kernel/…

NPM 常用命令(三)

目录 1、npm compltion 1.1 描述 2、npm config 2.1 常用命令 2.2 描述 set get list delete edit fix 2.3 配置 json global editor location long 3、npm dedupe 3.1 描述 3.2 配置 4、npm deprecate 4.1 命令使用 4.2 描述 4.3 配置 registry ot…

【huggingface】数据集及模型下载并保存至本地

目录 数据集ChnSentiCorppeoples_daily_ner 模型bert-base-chinesehfl/rbt3t5-baseopus-mt-zh-enChinese_Chat_T5_Base 环境&#xff1a;没有代理&#xff0c;无法访问部分国外网络 数据集 正常情况下通过load_dataset加载数据集&#xff1b;save_to_disk保存至本地&#xff1b…

佳作导读 | 《C++ Core Guidelines》

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 佳作导读 | 《C Core Guidelines》 《C Core Guidelines》由Bjarne Stroustrup和Herb Sutter等共同编写关于使用C编程语言的指南&#xff1b;旨在提供关于如何使用C进…

Linux常用命令——csplit命令

在线Linux命令查询工具 csplit 将一个大文件分割成小的碎片文件 补充说明 csplit命令用于将一个大文件分割成小的碎片&#xff0c;并且将分割后的每个碎片保存成一个文件。碎片文件的命名类似“xx00”&#xff0c;“xx01”。csplit命令是split的一个变体&#xff0c;split只…

如何在Win10系统上安装WSL(适用于 Linux 的 Windows 子系统)

诸神缄默不语-个人CSDN博文目录 本文介绍的方法不是唯一的安装方案&#xff0c;但在我的系统上可用。 文章目录 1. 视频版2. 文字版和代码3. 本文撰写过程中使用到的其他网络参考资料 1. 视频版 B站版&#xff1a;在Windows上安装Linux (WSL, 适用于 Linux 的 Windows 子系统…

【Rust 日报】2023-09-03 sudo-rs:sudo 和 su 的内存安全实现

sudo-rs&#xff1a;sudo 和 su 的内存安全实现 sudo-rs 项目通过以下方式改进了原始 sudo 的安全性&#xff1a; 使用内存安全语言&#xff08;Rust&#xff09;&#xff0c;因为估计原始 sudo 中三分之一的安全漏洞都与内存管理问题有关。省略不常用的功能&#xff0c;以减少…

记2个library cache lock故障case

第一个case 客户说晚上10点的时候做业务很卡&#xff0c;遂取对应时段awr 非常明显的library cache lock事件。这个事件是元数据锁&#xff0c;一旦泛滥对数据库的影响范围很大。 因此&#xff0c;他的泛滥第一时间应该想到会有大量持有元数据的动作。对sql进行检查 这个自动…

精益制造、质量管控,盛虹百世慧共同启动MOM(制造运营管理)

百世慧科技依托在电池智能制造行业中的丰富经验&#xff0c;与盛虹动能达成合作&#xff0c;为其提供MOM制造运营管理平台&#xff0c;并以此为起点&#xff0c;全面提升盛虹动能的制造管理水平与运营体系。 行业困境 中国动力电池已然发展为全球最大的电池产业&#xff0c;但…

【网络安全带你练爬虫-100练】第20练:数据处理-并写入到指定文档位置

目录 一、目标1&#xff1a;解码去标签 二、目标2&#xff1a;提取标签内内容 三、目标3&#xff1a;处理后的数据插入原位置 四、目标4&#xff1a;将指定的内容插入指定的位置 五、目标5&#xff1a;设置上下文字体格式 六、目标6&#xff1a;向多个不同位置插入不同的…

算法笔记:平衡二叉树

1 介绍 平衡二叉树&#xff08;AVL树&#xff09;是一种特殊的二叉搜索树&#xff08;BST&#xff09;&#xff0c;它自动确保树保持低高度&#xff0c;以便实现各种基本操作&#xff08;如添加、删除和查找&#xff09;的高效性能。 ——>时间都维持在了O(logN)它是一棵空…

网络安全—0基础入门学习手册

前言 一、什么是网络安全 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都有攻与防…

windows下配置pcl-python

1.前提概要 python版本的pcl基本上只有3.6的能用&#xff0c;本人3.7/3.8均进行了尝试。 因为很多博主提到的Gtk已经下载不了了&#xff0c;实在是维护人员太懒了。如果你看到这里&#xff0c;可以试试下面这个链接&#xff0c;说不定又能用了呢。 Gtk下载&#xff1a;http:…

vmware网卡(网络适配器)桥接、NAT、仅主机3种模式解析

Bridged&#xff08;桥接模式&#xff09;、NAT&#xff08;网络地址转换模式&#xff09;、Host-Only&#xff08;仅主机模式&#xff09; Windows系统安装好vmware后&#xff0c;在网络连接中会生成VMnet1和VMnet8两个虚拟网卡。 VMnet1作用于仅主机模式&#xff0c;VMnet8作…

Java作业3

1.下面代码的运行结果是&#xff08;C&#xff09; public static void main(String[] args){String s;System.out.println("s"s);}A.代码编程成功&#xff0c;并输出”s” B.代码编译成功&#xff0c;并输出”snull” C.由于String s没有初始化&#xff0c;代码不…