数据结构排序篇上

排序的概念及其运用

排序的概念

排序 :所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性 :假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次
序保持不变,即在原序列中, r[i]=r[j] ,且 r[i] r[j] 之前,而在排序后的序列中, r[i] 仍在 r[j] 之前,则称这种排
序算法是稳定的;否则称为不稳定的。
内部排序 :数据元素全部放在内存中的排序。
外部排序 :数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

排序的运用 

 

 常见的排序

 插入排序:直接插入排序

先写直接插入排序。

直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列
实际中我们玩扑克牌时,就用了插入排序的思想

一下子写排序是不可取的,排序这个部分,先写单趟,后写整体。

就比如说,我有0~end个数据的下标,我想把该数组外的end+1下标的值插入到现有数据。end在哪里我不清楚,这里只是假设,这里单趟的核心思想就是把一个数往前面的有序区间插入。这里的0~end肯定是有序的。注意注意,这里的end是什么我们并不知道。

这里已经有一个有序区间了。然后我把后一个值往前面插入。

2比5小,所以5得往后挪动,但是一挪动就会覆盖2,所以得先把2存起来。将2保存在一个变量中。比5小挪动,end减减,比3小挪动,end减减,比1大,就放到1的后面。假如要插入的不是2了,而是0,那我还是比1小,1往后挪动,我end减减,然后把0插入在end的后面,所以结束条件为end=-1;

总结:无论哪一种情况,都是放在end的后面。

//单趟插入排序
void InsertSort(int* a, int n)
{
	int end=0;
	int tmp = a[end + 1];
	while (end >= 0)
	{
		if (tmp < a[end])
		{
			a[end + 1] = a[end];
			--end;
		}
		else
		{
			break;
		}
	}
	//这里切记end要加1,否则会出问题,因为我们之前移动后,立马end减去1了。
	a[end + 1] = tmp;
}

上图是完成了一趟了

这个循环有两个出去的条件,一个是你比end对应的值大于或者等于就break跳出,还有end小于0就结束,就是所有的值都比你目标值大,就一直挪动,挪到end等于-1,就将目标值插入到end的后面。这就是一趟走的整体思路。

完成了一趟的数据后,我们就开始写次数来完善程序。

这里我们把end给为0,就想当然把0当成有序,然后继续来走。

所以给的end的其实位置就是0.所以在循环里,这里就给i。

end为0时,即第一个数据有序,end后的数据开始插入,以此类推。

end的结束位置在数组最后位置的前一个。即有n个数据,那么最后一个数据的下标为n-1,再往前就是n-2;

因为这里要经常打印数组,所以这里就写一个相应的函数。

void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}

分析时间复杂度

写代码时,要对其的思路逻辑清楚一点,否则会出现问题。

一定要学会单趟套整体。

这个直接插入排序的时间复杂度为多少?千万不要说两层循环n的平方。简单排序看层数是没问题的。但是排序这里看循环层数来判断n的平方是不对的。判断时间复杂度要看思想。

这个直接插入排序,逆序的时候,时间复杂度是最坏的。就是第一个数有序,第二个数插入一次,第三个数两次,就是等差数列。就是得全部挪动一遍。所以也就是1~n-1,也就是n的平方。

呃呃呃,虽然这个程序是n的平方,但是切记看思想来判断。

这是最坏情况,我们再看一下最好情况,即顺序。就是0(n),就是遍历了一遍。或者说接近有序,这个最好情况再顺序有序或者接近有序时成立。

为什么最好是0(n)呢?就是我给你一个数组,你是不知道他是是否有序的。你不知道他是否有序。没有排序可以做到0(1),最快的排序就是接近0(n)的。当然在一些比较局限的场景里可以做到0(n)。常见的排序n*log(n)就是最好的了。

交换排序:冒泡排序

体现素养的小细节:

写个冒泡,呜呜,遇到友人了。

BubbleSort.(命名要规范,否则面试出大问题)。

规范:代码里面不要有拼音,除非没有对应的单词。这个关乎面试官对你的代码素养。

冒泡排序 是一种交换思想,如果前一个大于后一个就交换,这样以来,一轮之后,最大的值就到最后了。然后再前一个根后一个交换,把次大的值换到倒数第二个位置了。

我们还按照先写单趟,再写整体。

这里先写一个交换函数,因为之后可以复用。

//单趟冒泡排序
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void BubbleSort(int* a, int n)
{
	for (int i = 1; i < n; i++)
	{
		if (a[i - 1] > a[i])
		{
			Swap(&a[i - 1], &a[i]);
		}
	}
}

代码比的是细节。要控制住细节。如果你觉得细节控制的不是太好,那一定是画图画少了。

这里for循环条件也可以给i为0,这样接得写i<n-1了,这样得控制尾部的结束条件了。当然,怎么写都是可以的。

我们这样写的就是一前一后进行交换。

到这里第一次记冒好了,第一次就确定了最大值,所以第二趟就冒到n-1就行了。当<1时,冒泡就结束。所以一共冒泡n-1次就行。

void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n - 1; j++)
	{
		for (int i = 1; i < n; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
			}
		}
	}
}

 这里第一层次数循环是到n-2结束,第二层for循环进行每一次需要的趟数到小于n-(n-2)结束,即小于2就结束,也就是到1,我们分析就是到1就继续,正好0和1那里比较了,然后就结束,思路是这样的。

到这里,冒泡就写好了,但是其实还是可以优化的。

冒泡空间有可优化的空间,就是顺序可能或者基本有序,就不冒一趟没有发现数据交换,就不用再继续走了,这里给个标志。

void BubbleSort(int* a, int n)
{
	for (int j = 0; j < n - 1; j++)
	{
		int exchange = 0;

		for (int i = 1; i < n; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				exchange = 1;
			}
		}

		if (exchange == 0)
			break;
	}
}

冒泡排序的时间复杂度是n的平方。这个时候的最坏的情况不是说逆序了,逆序只是其中一种情况,不一定是逆序,很多情况都是n的平方。最好的顺序就是接近有序从而达到0(n)。

它和插入排序看起来没什么区别,但其实不一样。

冒泡排序的特性总结:
1. 冒泡排序是一种非常容易理解的排序
2. 时间复杂度: O(N^2)
3. 空间复杂度: O(1)
4. 稳定性:稳定

 对比直接插入排序和冒泡排序

// 测试排序的性能对比
void TestOP()
{
	srand(time(0));
	//开100000个空间
	const int N = 100000;
	int* a1 = (int*)malloc(sizeof(int) * N);
	int* a2 = (int*)malloc(sizeof(int) * N);
	int* a3 = (int*)malloc(sizeof(int) * N);
	int* a4 = (int*)malloc(sizeof(int) * N);
	int* a5 = (int*)malloc(sizeof(int) * N);
	int* a6 = (int*)malloc(sizeof(int) * N);
	//每个数组放一样的数
	for (int i = 0; i < N; ++i)
	{
		a1[i] = rand();
		a2[i] = a1[i];
		a3[i] = a1[i];
		a4[i] = a1[i];
		a5[i] = a1[i];
		a6[i] = a1[i];
	}
	//计算时间
	int begin1 = clock();
	InsertSort(a1, N);
	int end1 = clock();
	int begin2 = clock();
	BubbleSort(a2, N);
	int end2 = clock();
	/*int begin3 = clock();
	SelectSort(a3, N);
	int end3 = clock();
	int begin4 = clock();
	HeapSort(a4, N);
	int end4 = clock();
	int begin5 = clock();
	QuickSort(a5, 0, N - 1);
	int end5 = clock();
	int begin6 = clock();
	MergeSort(a6, N);
	int end6 = clock();*/
	printf("InsertSort:%d\n", end1 - begin1);
	printf("BubbleSort:%d\n", end2 - begin2);
	/*printf("SelectSort:%d\n", end3 - begin3);
	printf("HeapSort:%d\n", end4 - begin4);
	printf("QuickSort:%d\n", end5 - begin5);
	printf("MergeSort:%d\n", end6 - begin6);*/
	free(a1);
	free(a2);
	/*free(a3);
	free(a4);
	free(a5);
	free(a6);*/
}
int main()
{
	/*int a[] = { 5,4,3,2,1 };
	BubbleSort(a, sizeof(a) / sizeof(a[0]));
	PrintArray(a, sizeof(a) / sizeof(a[0]));*/
	TestOP();

	return 0;
}

malloc个多个数组,产生一个随机值。然后将数组1赋值给别的数组,就是说这6个数组的值都是一样的。 

这里begin减去end就是排序所消耗的时间。

clock是电脑运行启动到调用这个函数是所消耗的毫秒数,所以两个clock之差就是中间的排序消耗掉的时间。

这里进行测试时,debug可能优化没有全开,测性能用release。

下图是realease的。

跑十万个值进行的比较。

所以明显的感觉到这两个不一样。不能单看时间复杂度来看这里的问题。

时间复杂度用来算他是属于哪一个量级的。这两个属于同一个档次的排序。同一个学校,是统一档次,但出来的不同同学有不同。

所以不能单一时间复杂度来评估。

选择排序:堆排序

堆排序 (Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是
通过堆来进行选择数据。 需要注意的是排升序要建大堆,排降序建小堆。

 

 

直接选择排序的特性总结:
1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度: O(N*logN)
3. 空间复杂度: O(1)
4. 稳定性:不稳定

 

void HeapSort(int* a, int n)
{
	//a数组直接建堆 0(N)
	for (int i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}

	//O(N*logN)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		printf("%d ", a[end]);
		--end;
	}
	printf("%d", a[0]);
}
int main()
{
	int a[] = { 5,4,3,2,1 };
	HeapSort(a, sizeof(a) / sizeof(a[0]));
	//PrintArray(a, sizeof(a) / sizeof(a[0]));
	//TestOP();

	return 0;
}

 

排序和排序直接真的有差距啊。

插入和冒泡属于同一类,但效率差很多的重要的点在,插入具有很强的适应性。

冒泡不再冒的条件是很苛刻的,就是不能有任何一个交换,没有一个条件交换,就是已经有序了,这个条件是很难达成的。

插入的适应性在哪里呢?只要由一个靠后的数据比前面数据都小,那就挪动n次。但是这是非常极端的,一般来说这个数据可能在偏中间一点的位置,即只挪动了一半的数据就达到了目的。

 

这个堆冒泡是常态,但对于插入排序来说,他只要每个数据都要挪满时才会出现这种情况。但是对插入排序来说,他的中间或许可能会局部有序,他不需要;一直挪。随机的场景更多的是局部有序。

时间复杂度不在同一个量级就没有可比性,在同一个量级的也有差异。冒泡在随机数是都是比满。

插入排序:希尔排序

 

希尔觉得插入排序非常的不错,如果有序接近有序,插入有序就非常nb了。它要改革直接插入排序。如果能把数据接近有序,那就很快乐。

所以他分为两个步骤:

预排序 目标:接近有序;

他觉得你挪动的太慢了。它想让挪动的快一些。也就是分组插入排序。目标:大的更快换到后面的位置,小的数更快换到前面的位置。

就是以gap为间距来一一分组。

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

 

希尔排序的特性总结:
1. 希尔排序是对直接插入排序的优化。
2. gap > 1 时都是预排序,目的是让数组更接近于有序。当 gap == 1 时,数组已经接近有序的了,这样就 会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
3. 希尔排序的时间复杂度不好计算,因为 gap 的取值方法很多,导致很难去计算,因此在好些树中给出的 希尔排序的时间复杂度都不固定

 《数据结构(C语言版)--- 严蔚敏

 《数据结构-用面相对象方法与C++描述》--- 殷人昆

稳定性:不稳定

 

预排序和原数组相比: 

 

他有序了一点,但不是很多。

我们先写单趟。

我们接下来以下图这个数组为例开始排

 

//单次希尔排序
void ShellSort(int* a, int n)
{
	int gap = 3;
	int end=0;
	int tmp = a[end + gap];
	while (end >= 0)
	{
		if (tmp < a[end])
		{
			a[end + gap] = a[end];
			end -= gap;
		}
		else
		{
			break;
		}
	}
	a[end + gap] = tmp;
}

比完5和2了,然后比5和3时,不是上述代码,写的,得先在上图再套一层才能写,这里先继续写。

这里跟插入排序很像,无非就是将加1换成了加gap。

刚才完成的只是把一个数往前插入,如果我们要排一组数据,那么该如何排。

 for(int i=0;i<n;i+=gap)

 上图这里再套一层循环。但是这里有问题,如果i等于在5的位置时(即进行了交换之后),再加上gap来进入循环,这个时候就越界了。

所以外层循环应该写为上图:

这个时候就帮助我们帮红色这一组就排完了,但是我们想排整体,该如何呢?间距为gap,就有gap组。gap是几就有几组。所以再次套一层循环。

//一个gap进行的希尔排序
void ShellSort(int* a, int n)
{
	int gap = 3;
	for (int i = 0; i < n-gap; i += gap)
	{
		int end=i;
		int tmp = a[end + gap];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + gap] = a[end];
				end -= gap;
			}
			else
			{
				break;
			}
		}
		a[end + gap] = tmp;
	}
}

所以外层循环应该写为上图:

这个时候就帮助我们帮红色这一组就排完了,但是我们想排整体,该如何呢?间距为gap,就有gap组。gap是几就有几组。所以再次套一层循环。

//完整的希尔排序
void ShellSort(int* a, int n)
{
	int gap = 3;
	for (int j = 0; j < gap; j++)
	{
		for (int i = 0; i < n - gap; i += gap)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

总结一下:希尔排序分为预排序他的目的是分组插入排序

预排序的目标是:大的更快换到后面的位置,小的数更快换到前面的位置。

到这里,其实上图完整的希尔排序也可以简化为2层。

void ShellSort(int* a, int n)
{
	int gap = 3;
	/*for (int j = 0; j < gap; j++)
	{
		for (int i = 0; i < n - gap; i += gap)
		{*/
	for (int i = 0; i < n - gap; i++)
	{
		int end = i;
		int tmp = a[end + gap];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + gap] = a[end];
				end -= gap;
			}
			else
			{
				break;
			}
		}
		a[end + gap] = tmp;
	}
	/*	}
	}*/
}

希尔排序是初始的是什么呢,是一组排完排另一组。是排完红色,再排绿色,再排紫色。

一组一组排。

但是按照上图来说,先比较换了2和5,然后不一整组一整组比较,而是最外层的i++。这个方法是gap组数据,交替完成分组插入排序。

gap大于1就是预排,等于1就是快速排序。gap越大,数据跳的越快,大的更快到前面为止,小的更快到后面,但是越不接近有序。

gap越小,数据跳的越慢,但是越接近有序,gap==1就是插入后就是有序。

 

继续深入;

这里还有人怎么给呢?到这里就已经变为怎么给gap了。

 这样就能控制gap了,我第一次间距给上50,gap大不接近有序,没关系啊,我gap在缩小,我除以2最后一趟一定是1.

 

这里希尔排序每一组都在接近有序。

呜呜呜呜,开始这个排序让你爱答不理,最后让我高攀不起。呜呜呜呜!

 

有人觉得除3更好,但是除3不能保证最后余数为1.
代码能力是练出来的。需要消化的数据才是有含量的。

若有收获,就点个赞吧

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

震惊!借助Coze白嫖GPT4-128k解决方案

震惊!某大佬借助Coze白嫖GPT4-128k解决方案 前言 此文章介绍如何免费使用GPT-4高级模型并拓展API功能 最近的 Coze 在国内开放了&#xff0c;可以免费使用大模型。但是和国外的有点区别&#xff0c;国外版本使用的chatgpt4&#xff0c;国内版本使用的是语雀大模型。 Coze是一…

功能测试_订购单检查_判定表

画判定表的步骤&#xff1a; 列出条件 列出动作

964: 数细胞

样例&#xff1a; 解法&#xff1a; 1.遍历矩阵 2.判断矩阵[i][j]&#xff0c;若是未标记细胞则遍历相邻所有未标记细胞并标记&#xff0c;且计数 实现&#xff1a;遍历相邻所有未标记细胞 以DFS实现&#xff1a; function dfs(当前状态) {if (终止条件) {}vis[标记当前状…

设计模式——外观(门面)模式10

外观模式&#xff1a;能为系统框架或其他复杂业务流程封装提供一个简单的接口。 例如抽奖过程中 设计模式&#xff0c;一定要敲代码理解 调用1&#xff08;抽奖系统&#xff09; /*** author ggbond* date 2024年04月08日 10:34*/ public class Lottery {public String getId…

x86处理器工作原理

对于电脑&#xff0c;大家可能司空见惯。但有没有想过它的处理器是如何工作的呢&#xff1f;下面和大家一起学习它的工作原理。 一. 最早的处理器 1.1 技术的发展 1947年&#xff0c;美国贝尔实验室的肖克利和同事们一起发明了晶体管。 1958年&#xff0c;美国人杰克基尔比发…

SpringBoot 集成H2数据库,启动执行sql, 中文乱码

目录 H2数据库介绍 SpringBoot版本&#xff1a;SpringBoot 2.1.12.RELEASE 快速集成H2&#xff0c;maven依赖 快速集成H2&#xff0c;数据源及关键参数配置 spring.datasource.schema参数&#xff08;建表SQL脚本&#xff09; spring.datasource.data参数&#xff08;更新、…

napi系列学习高阶篇——通过IDE集成C/C++三方库并开发napi接口

简介 应用在调用系统固件集成的C/C三方库时&#xff0c;可能会由于系统固件集成端与IDE的NDK中libc版本不一致导致调用失败&#xff0c;而且系统固件集成的C/C三方库对于应用的调式也很不友好&#xff0c;需要多方编译调试&#xff0c;很不方便。因此本文将通过在IDE上适配ope…

16、普通数组-除自身以外的数组乘积

思路 通过辅助数组的方式 第一个从左向右的辅助数组乘积第二次从右向左的辅助数组乘积对于0<i<N-1 他的数组乘积就是左边的数组乘积*右边数组乘积然后再分类讨论i0 就是右边1-N-1的数组乘积iN-1就是左边从N-2到0的数组乘积 代码如下&#xff1a; class Solution {pub…

【MATLAB】GA_ELM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 1 基本定义 GA_ELM&#xff08;Genetic Algorithm and Extreme Learning Machine&#xff09;是一种结合了遗传算法和极限学习机的神经网络时序预测算法。它的核心思想是通过使用遗传算法来优化极限学习机的权重和偏差&…

OpenCV C++学习笔记

1.图像的读取与显示 1.1 加载并显示一张图片 #include<opencv2/opencv.hpp> #include<iostream>using namespace cv; using namespace std; int main(int argc,char** argv){Mat srcimread("sonar.jpg");//读取图像if(src.empty()){printf("Could…

吴恩达深度学习 (week3,4)

文章目录 一、神经网络概述二、神经网络的表示三、神经网络的输出四、多个例子的向量化五、向量化实现的解释六、深度学习激活函数七、激活函数导数八、神经网络的梯度下降法九、深度学习随机初始化十、上述学习总结1、第一题2、第二题3、第三题4、第四题5、第五题6、第六题7、…

磁悬浮鼓风机市场规模不断增长 我国行业发展面临挑战

磁悬浮鼓风机市场规模不断增长 我国行业发展面临挑战 磁悬浮鼓风机又称磁悬浮高速离心鼓风机&#xff0c;指基于磁悬浮技术制成的气体输送设备。磁悬浮鼓风机综合性能优良&#xff0c;属于高效节能磁悬浮动力装备&#xff0c;在众多领域需求旺盛。未来随着国家节能环保政策逐渐…

将Visio绘图导出PDF文件,使其自适应大小,并去掉导入Latex的边框显示

问题描述 将Visio绘图导成pdf文件&#xff0c;首先在Visio绘图如下&#xff1a; 如果直接导出或者另存为pdf文件&#xff0c;则会发现pdf文件是整个页面大小&#xff0c;而不是图片大小。而且在导入latex等排版工具现实时&#xff0c;会显示边框。 问题解决 1.调整Visio中的页…

科软24炸穿了,25还能冲吗?

25考研&#xff0c;科软必然保持大热 不是吧兄弟&#xff0c;明眼人都能看出来&#xff0c;科软以后不会出现大冷的局面了&#xff0c;除非考计算机的人减少&#xff0c;因为科软简直是叠满了buff&#xff0c;首先科软的专业课是22408&#xff0c;考的是数学二&#xff0c;这就…

ssm048电子竞技管理平台的设计与实现+jsp

电子竞技管理平台设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本电子竞技管理平台就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…

jsoncpp 编译和使用

原文链接&#xff1a; jsoncpp的编译和使用 jsoncpp 编译出库文件 1.从github仓库下载 2.下载 cmake 工具 3.生成VS项目 4.编译得到需要的库文件 jsoncpp 的使用 查看原文

JavaEE初阶Day 7:多线程(5)

目录 Day 7&#xff1a;多线程&#xff08;5&#xff09;1. 死锁2. 死锁场景3. 场景二&#xff1a;两个线程&#xff0c;两把锁4. 场景三&#xff1a;N个线程&#xff0c;M把锁5. 避免死锁问题6. 内存可见性问题 Day 7&#xff1a;多线程&#xff08;5&#xff09; 回顾synchr…

【C++】类和对象②(类的默认成员函数:构造函数 | 析构函数)

&#x1f525;个人主页&#xff1a;Forcible Bug Maker &#x1f525;专栏&#xff1a;C 目录 前言 类的6个默认成员函数 构造函数 概念 构造函数的特性及用法 析构函数 概念 析构函数的特性及用法 结语 前言 本篇主要内容&#xff1a;类的6个默认成员函数中的构造函…

ifconfig用法 、默认掩码

文章目录 概述2. ifconfig(尽量别用&#xff0c;已废弃)2.1 配置地址2.1.1 默认掩码 2.2 查看功能2.2.1 ifconfig 查看不含禁用的网卡2.2.2 ifconfig -a 查看含禁用的网卡2.2.3 ip a 2.3 启用、禁用网卡2.3.1 ifconfig eth1 up、 ifconfig eth1 down2.3.2 ifdown eth0、ifip et…

C++string类(个人笔记)

string类 1.认识string的接口以及熟练使用常用接口1.1string类对象的常见构造1.2string类对象的容量操作1.3string类对象的访问及遍历操作1.4string类对象的修改操作 2.vs 和g下string结构的说明3.string类运用的笔试题4.string类的模拟实现 1.认识string的接口以及熟练使用常用…