八大排序算法细讲

目录

排序

概念

运用

常见排序算法

插入排序

直接插入排序

思想:

步骤(排升序):

代码部分:

时间复杂度:

希尔排序

思路

步骤

gap的取法

代码部分:

时间复杂度:

选择排序

直接选择排序

排升序思路:

排升序步骤:

代码部分:

时间复杂度:

堆排序

代码部分:

交换排序

冒泡排序

代码部分:

快速排序(递归版本)

思路:

hoare版本

排升序步骤:

相遇问题:

代码部分:

挖坑法版本

排升序思路:

代码部分:

前后指针版本:

排升序思路:

代码部分:

时间复杂度:

快速排序(非递归版本)

思路:

注意:

​编辑

代码部分(找基准值部分用的是前后指针方法):

归并排序

思路:

排升序步骤:

代码部分:

时间复杂度:

非比较排序

计数排序

思路:

代码部分:

时间复杂度:

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


排序

概念

排序就是将一段记录,按照其中的某个或某些关键字大小,实现递增或递减的操作

运用

排序在我们的生活中运用也是极其广泛的,如:在购物软件中,根据不同条件来筛选商品;大学院校的排名……等等

常见排序算法

插入排序

直接插入排序

思想:

把待排序的记录按其关键码值的大小逐个插入到⼀个已经排好序的有序序列中,直到所有的记录插入完为止,得到⼀个新的有序序列

这种排序算法类似于玩扑克牌,就是依次将手中的牌进行排序

步骤(排升序):

1、先取出第二张牌与第一张进行比较,小的放前面,大的放后面

2、让后面的牌再进行上面那一步

这样看起来会比较抽象,举一个例子来实现就容易理解了

代码部分:
void InsertSort(int* arr, int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		int end = i;
		int temp = arr[end + 1];
		while (end >= 0)
		{
			if (arr[end] > temp)
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else
			{
				break;
			}
		}
		arr[end + 1] = temp;
	}
}

时间复杂度:

直接插入排序的时间复杂度为O(N^2),但在一般情况下是不会达到N^2的,只有在排序数组与要求排序方向相反时(也就是逆序),才会达到O(N^2)

这也就导致了一个问题,在面对逆序情况下,使用该排序算法,效率就会大大降低

面对这种情况,前人就在直接插入排序算法的基础上进行了改良,也就是接下来要讲的——希尔排序

希尔排序

根据上面的直接插入排序算法我们可以知道,在面对逆序数组时,算法复杂度太大了(O(N^2)),

所以前人就在该算法基础上进行了改良

思路

先选定一个整数,命名为gap,通常是gap=n/3+1,将带排序数组中元素根据gap值分为多组,也就是将相距gap值的元素分在同一组中,然后对每一组的元素进行排序,这是就完成一次排序,然后gap=gap/3+1,,再将数组根据gap值分为多组,进行插入排序,当gap=1时,就相当于进行直接插入排序算法。

步骤

步骤一(当gap>1):

1、将数组根据gap分为多组

2、将相距gap值的元素进行比较

注:步骤一也可以称为预排序,目的是为了:将数组转变为一个相对有序的情况,避免直接插入排序在面对逆序数组情况时时间复杂度变大

排升序时:小的元素在前面,大的元素在后面

排降序时:大的元素在前面,小的元素在后面

步骤二(当gap=1):

就相当于进行直接插入排序

举例可知

gap的取法

gap值的最初值取该数组的长度,当它进入while循环时,就先进行gap=gap/+1

然而,为什么是对gap/3,而不是除以其他值呢?

如果gap除以的值过小的话,比如:gap=gap/2,就会导致分的组太少,而每组内元素比较次数过多,while循环次数也会增多(因为gap值要不断除以2,直到gap=1时停止while循环)

如果gap除以的值过大的话,比如:gap=gap/8,就会导致分的组过多,而每组内元素比较次数较少,while循环次数少

所以gap除以的值要取适中的值,3则是较好的值

那为何还要加一呢?

加一的目的是为防止gap整除的值为0,这样可以防止gap=0时,直接退出循环,没有排序完全

代码部分:
void ShellSort(int* arr, int n)
{
	int gap = n;
	while (gap > 1)//gap不能等于1,如果为一进入循环,在gap/3+1中就会一直为1,就会死循环
	{
		
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; ++i)
		{
			int end = i;
			int temp = arr[end + gap];
			while (end >= 0)
			{
				if (arr[end] > temp)
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = temp;
		}
	}
	
}

时间复杂度:

希尔排序算法的时间复杂度不好计算,大概为O(N^1.3)

选择排序

直接选择排序

排升序思路:

每一次循环,先从待排数组中找出最大和最小值,将最小值与待排数组的起始位置交换,最大值与待排数组的最后一个元素交换,直到所有待排数组元素排完

排升序步骤:

1、设立起始位置和最后一元素下标位置:begin、end,然后找到最大值和最小值下标

2、将最小值和起始元素交换、最大值和末尾元素交换

3、交换后,begin++、end--,然后进行[begin,end]区间元素的排序,按照上面两步

4、直到begin>end时结束排序

注:当begin与maxi、end与mini重叠时,会造成重复交换,所以就需要将maini和mini进行交换

代码部分:

void SelectSort(int* arr, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int mini , maxi;
		mini = maxi = begin;
		for (int i = begin + 1; i <= end; ++i)
		{
			if (arr[i] > arr[maxi])
			{
				maxi = i;
			}
			if (arr[i] < arr[mini])
			{
				mini = i;
			}
		}
		if (begin == maxi)
		{
			maxi = mini;
		}
		Swap(&arr[begin], &arr[mini]);
		Swap(&arr[end], &arr[maxi]);

		begin++;
		end--;
	}
}

时间复杂度:

直接选择排序的时间复杂度很好理解,为O(N^2),因为它的效率不是很好,所以实际上很少会用到

堆排序

堆排序的讲解,在前面的文章已经讲解过了,就不在这里过多说明,有兴趣的朋友可以移步

二叉树:堆的建立和应用_二叉树的应用,两种创建方式-CSDN博客

代码部分:
void AdJustDown(int* arr, int parent, int n)//向下调整
{
	int child = parent * 2 + 1;
	while (child < n)
	{
		//这里左右孩子的比较,c>c+1,交换建小堆;c<c+1,交换建大堆
		//建大堆,先找大孩子;建小堆,先找小孩子
		if (child + 1 < n && arr[child] < arr[child + 1])
		{
			child++;
		}
		//>建大堆
		//<建小堆
		if (arr[child] > arr[parent])
		{
			Swap(&arr[child], &arr[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
void HeapSort(int* arr, int n)//向下调整算法建堆:时间复杂度O(n)
{
	//排升序建大堆
	//排降序建小堆
	//先建堆
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdJustDown(arr, i, n);
	}
	//再排序
	int end = n - 1;
	while (end > 0)
	{
		Swap(&arr[0], &arr[end]);//交换堆顶和尾结点
		AdJustDown(arr, 0, end);
		end--;
	}

}

交换排序

冒泡排序

冒泡排序大家应该都不陌生,是我们C语言学习的第一个排序算法,它的时间复杂度为O(N^2),

关于它的思路步骤我就不过多说明了,它在实际当中也基本不会用到,它是起着一种教学作用的排序算法

代码部分:
void BubbleSort(int* arr, int n)
{
	int i = 0;
	for (i = 0; i < n - 1; ++i)
	{
		int j = 0;
		int flag = 1;
		for (j = 0; j < n - 1 - i; ++j)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
				flag = 0;
			}
		}
		if (flag == 1)//当提前完成排序后,就直接退出循环
		{
			break;
		}
	}
}

快速排序(递归版本)

快速排序可以说是排序算法中最重要的排序算法,在实际学习和工作中运用得最多,接下来我们来好好学习快速排序算法

思路:

任取待排数组中某一个元素作为基准值(key),然后将基准值放到正确位置上,按照基准值将数组分割成两个序列,左子序列中所有元素小于基准值,右子序列中所有元素大于基准值(这里排升序),然后再对左右子序列重复该过程,直到所有元素都排列再在相对应位置上为止

hoare版本

排升序步骤:

1、找基准值:

起始令首元素为基准值(key),设right和left,right为末尾元素下标,left为首元素下标,

让left从左往右找比基准值大的值,right从右往左找比基准值大的值,

找到以后将left与right指向的值进行交换,这个交换的前提是right>=left;

而当right小于left时right所指向的值就与key进行交换,这时key就回到了正确的位置

2、二分

根据key所在位置,对数组进行二分,将数组分为左右两个子序列,然后再对左右两个子序列进行上述操作

相遇问题:

1、相遇点值小于基准值

由此可知,当相遇点小于基准值时,left依旧减减

2、相遇点值大于基准值

由此可知,当相遇点大于基准值时,right依旧加加

3、当相遇点值等于基准值

这种情况看似两种都可以,但是当选择了right依旧减减时,就会导致面对下面这种情况时,时间复杂度大大提高 

这种情况便是相遇点值与基准值相同的情况,在这种情况下,该排序算法的时间复杂度就会大大提高,无法进行高效的分割排序

其实这也是这种hoare版本快速排序在面对待排数组中重复元素过多情况下的弊端

代码部分:
int Hoare_QuickSort(int* arr, int left, int right)
{
	int keyi = left;
	left++;
	while (left <= right)
	{
		//rigth从右往左找比基准值小的值
		while (left<=right && arr[right]>arr[keyi])//这里的arr[rigth]>arr[keyi]只能取大于号,不能加上等于号,
												   //加上的话在面对数组全相等或有序数组时,时间复杂度会变大
		{
			right--;
		}
		//left从左往右找比基准值大的值
		while (left<=right && arr[left]<arr[keyi])//这里的情况和rigth是一样的
		{
			left++;
		}
		if (left <= right)//当left还未大于rigth时,就进行交换
		{
			Swap(&arr[left], &arr[right]);
		}
	}
	Swap(&arr[right], &arr[keyi]);
	keyi = right;
	return keyi;
}

void QuickSort(int* arr, int left, int right)//排升序
{
	if (left >= right)
	{
		return;
	}
	//找基准值
	int keyi = Hoare_QuickSort(arr, left, right);

	//二分
	//[left,keyi-1] keyi [keyi+1,right]
	QuickSort(arr, left, keyi - 1);
	QuickSort(arr, keyi + 1, right);

}

挖坑法版本

排升序思路:

设立左右指针:left、right,先将基准值视为第一个坑:hole,

right从右往左找比基准值小的数,找到以后就放入到hole的位置,然后righ处就为新的坑;

left从左往右找比基准值大的数,找到以后就放入到hole的位置,然后left处就为新的坑;

当right==left时,就将保存的基准值放入到两者相遇处

就这样便完成了第一次基准值的寻找

找到以后就和hoare版本一样进行二分

注:

这种方法起始的left只能指向首元素;

和hoare版本不同的是,当right从右往左找比基准值小的值时,当遇到比基准值大的或者等于的值时,继续往左找;left也是一样的

代码部分:
int Hole_QuickSort(int* arr, int left, int right)
{
	int hole = left;
	int key = arr[hole];
	while (left < right)
	{
		while (left<right && arr[right]>=key)
		{
			right--;
		}
		//找到比基准值小的值
		arr[hole] = arr[right];
		hole = right;
		while (left<right && arr[left]<=key)
		{
			left++;
		}
		//找到比基准值大的值
		arr[hole] = arr[left];
		hole = left;
	}
	//right和left相遇
	arr[hole] = key;
	return hole;
}

void QuickSort(int* arr, int left, int right)//排升序
{
	if (left >= right)
	{
		return;
	}
	//找基准值
	int keyi = Hole_QuickSort(arr, left, right);

	//二分
	//[left,keyi-1] keyi [keyi+1,right]
	QuickSort(arr, left, keyi - 1);
	QuickSort(arr, keyi + 1, right);

}

前后指针版本:

排升序思路:

设立两个变量:pcur(用于探路,来找比基准值小的值),prev(在pcur的后面)

1、当找到比基准值小的值时,++prev,prev所指向的元素和pcur所指向的元素交换,然后++pcur

2、当pcur所指向的元素没有比基准值小时,++pcur

当pcur越界(pcur>right)时,就将基准值与prev所指向的元素交换,就这样就实现了将比基准值小的元素放在基准值左边,大的放在右边

注:

有时候prev++后的值正好等于pcur,这个时候就不需要发生交换

代码部分:
int lomuto_QuickSort(int* arr, int left, int right)
{
	int prev = left, pcur = prev + 1;
	int keyi = left;
	while (pcur <= right)
	{
		if (arr[pcur] < arr[keyi]&&++prev != pcur)
		{
			Swap(&arr[prev], &arr[pcur]);
		}
		pcur++;
	}
	Swap(&arr[prev], &arr[keyi]);
	keyi = prev;
	return keyi;
}


void QuickSort(int* arr, int left, int right)//排升序
{
	if (left >= right)
	{
		return;
	}
	//找基准值
	int keyi = lomuto_QuickSort(arr, left, right);

	//二分
	//[left,keyi-1] keyi [keyi+1,right]
	QuickSort(arr, left, keyi - 1);
	QuickSort(arr, keyi + 1, right);

}

时间复杂度:

快速排序算法的时间复杂度为O(NlogN),在特殊情况下:待排数组中重复元素很多的时候,会到造成时间复杂度上升为O(N^2logN),这一点要记住,这与如何解决这一情况,在后面的文章中会着重讲解

快速排序(非递归版本)

我们讲解了递归版本的快速排序,那也会有非递归版本的快速排序

在非递归版本的快速排序和递归版本的快速排序有什么区别呢?

非递归版本的快速排序算法需要借助数据结构:栈来实现

思路:

我们首先需要建立一个栈,然后:

1、将数组的left和right下标入栈

2、进入一个循环(结束条件:栈为空),将从栈中出来的两个元素命名为begin和end

3、然后对[begin,end]这个区间来找基准值,找基准值的方法在上面已经说了三种方法,随便用那个都行

4、找完以后,根据基准值进行二分为左右两个子序列,再将左右两个子序列的首尾下标入栈,再重复上面的操作

注意:

1、当begin大于或等于keyi-1或者end小于或等于keyi+1时不进行入栈操作,也就是只有在begin<keyi-1或end>keyi+1的情况下才允许入栈操作

2、每次找完基准值后还要确定一次待排区间中下标是否都入栈了,首尾下标要再入一次栈,入栈条件也要满足上面的条件

3、建立了栈,在排完序后就需要进行销毁

如果对栈还有所不解的朋友,可以移步至【数据结构初阶】栈和队列的建立_实现线性表、栈和队列(要求顺序和链式两种实现)-CSDN博客

其实非递归版快速排序就是利用栈这一数据结构来模拟实现正常快速排序中的递归过程

代码部分(找基准值部分用的是前后指针方法):

void QuickSortNonR(int* arr, int left, int right)//非递归版本
{
	ST st;
	StackInit(&st);
	StackPush(&st, right);
	StackPush(&st, left);
	while (!StackEmpty(&st))
	{
		int begin = StackTop(&st);
		StackPop(&st);
		int end = StackTop(&st);
		StackPop(&st);
		
		int keyi = lomuto_QuickSort(arr, begin, end);
		if (end > keyi + 1)
		{
			StackPush(&st, end);
			StackPush(&st, keyi+1);
		}
		if (begin < keyi - 1)
		{
			StackPush(&st, keyi - 1);
			StackPush(&st, begin);
		}
	}

	StackDestroy(&st);

}

归并排序

思路:

将待排序数组不断进行二分,直到划分为一个个有序的子序列,然后再将这些子序列两两合并,成一个有序数组

也就是先二分再合并

排升序步骤:

1、二分:

对数组取中间值(mid),进行二分,要保证数组最左边下标left要小于最右边下标right(left<right)

mid = left+(right-left)/2

根据mid分为左右两个子序列([left,mid-1],[mid+1,right])

直到left大于或等于right时停止二分

2、合并:

将相邻有序数组两两合并为一个有序数组,并将这个有序数组存储在一个临时数组(temp)中

要注意的是:每次放入临时数组结束后,两个数组中可能会有元素没有放入到临时数组中,所以循环结束后要对两个数组进行检查,再进行一次放入临时数组

3、将临时数组中元素放回原先数组中

代码部分:
void _MergeSort(int* arr, int left, int right, int* temp)
{
	//二分
	if (left >= right)
	{
		return;
	}
	int mid = left + (right - left) / 2;
	_MergeSort(arr, left, mid,temp);
	_MergeSort(arr, mid+1, right,temp);
	//合并
	int begin1 = left, end1 = mid;
	int begin2 = mid+1, end2 = right;
	int i = begin1;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (arr[begin1] < arr[begin2])
		{
			temp[i++] = arr[begin1++];
		}
		else
		{
			temp[i++] = arr[begin2++];
		}
	}
	//两个区间可能还有元素没有入temp
	while (begin1 <= end1)
	{
		temp[i++] = arr[begin1++];
	}
	while (begin2 <= end2)
	{
		temp[i++] = arr[begin2++];
	}

	//将temp中元素放回原数组中
	for (int i = left; i <= right; ++i)
	{
		arr[i] = temp[i];
	}
}

void MergeSort(int* arr, int n)
{
	int* temp = (int*)malloc(sizeof(int) * n);
	_MergeSort(arr, 0, n - 1, temp);
	free(temp);
}

时间复杂度:

归并排序算法时间复杂度为O(NlogN),它二分的次数为logN次,合并次数为N次

非比较排序

计数排序

思路:

1、

先找出数组中的最大、最小值,

用最大值和最小值来求出待排数组中元素的出现次数数组大小

用一次数组来存储元素出现次数:count,它的大小为range = max-min+1

2、

遍历数组,求出待排数组中各个元素出现的次数

将每个元素和最小值相减可以得出它在countg数组中的下标,则该对应下标存储的值就加一

3、

根据count数组向原数组中放入元素

arr[index] = i + min

注:

当min和max跨度很大时就会造成空间的浪费,那就不适合这种算法

代码部分:
void CountSort(int* arr, int n)
{
	//先找最大值和最小值
	int max = arr[0], min = arr[0];
	for (int i = 1; i < n; ++i)
	{
		if (arr[i] > max)
		{
			max = arr[i];
		}
		if (arr[i] < min)
		{
			min = arr[i];
		}
	}
	int range = max - min + 1;
	int* count = (int*)malloc(sizeof(int) * range);
	if (count == NULL)
	{
		perror("malloc,fail!");
	}
	//初始化数组
	memset(count, 0, sizeof(int*) * range);
	//统计次数
	for (int i = 0; i < n; ++i)
	{
		count[arr[i] - min]++;
	}
	//将count中出现的次数还原到原数组中
	int index = 0;
	for (int i = 0; i < range; ++i)
	{
		while (count[i]--)
		{
			arr[index++] = i + min;
		}

	}
}

时间复杂度:

计数排序在数据范围集中时,效率很高,但是适用范围及场景有限
它的时间复杂度为O(N+range)

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

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录
的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,⽽在排序后的序列中,r[i]仍在r[j]
之前,则称这种排序算法是稳定的;否则称为不稳定的。
排序方法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序O(N^2)O(N)O(N^2)O(1)稳定
直接选择排序O(N^2)O(N^2)O(N^2)O(1)不稳定
直接插入排序O(N^2)O(N)O(N^2)O(1)稳定
希尔排序O(NlogN)~O(N^2)O(1.3)O(N^2)O(1)不稳定
堆排序O(NlogN)O(NlogN)O(NlogN)O(1)

不稳定

归并排序O(NlogN)O(NlogN)O(NlogN)O(N)稳定
快速排序O(NlogN)O(NlogN)O(N^2)O(logn)~O(N)不稳定

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

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

相关文章

python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法

回溯算法 「所有可能的结果」&#xff0c;而不是「结果的个数」&#xff0c;一般情况下&#xff0c;我们就知道需要暴力搜索所有的可行解了&#xff0c;可以用「回溯法」。 回溯算法关键在于:不合适就退回上一步。在回溯算法中&#xff0c;递归用于深入到所有可能的分支&…

【远程控制】安装虚拟显示器

todesk远程发现没显示器的机器有问题 电脑如果不外接一个显示器那么会默认为1024 768 分辨率需要安装虚拟显示器参考 竟然是一个隐私屏幕的解决方案。 虚拟显示器 Parsec-vdd 项目地址 Parsec-vdd 最大的优点是&#xff1a;支持 4K 高刷、可添加多个虚拟屏、 H-Cursor&#…

搭建集成开发环境PyCharm

1.下载安装Python&#xff08;建议下载并安装3.9.x&#xff09; https://www.python.org/downloads/windows/ 要注意勾选“Add Python 3.9 to PATH”复选框&#xff0c;表示将Python的路径增加到环境变量中 2.安装集成开发环境Pycharm http://www.jetbrains.com/pycharm/…

20250206在ubuntu20.04下使用unzip解压缩带中文名的文件

unzip -O GBK yourfile.zip unzip -O CP936 xxx.zip unar xxx.zip 20250206在ubuntu20.04下使用unzip解压缩带中文名的文件 2025/2/6 20:03 缘起&#xff1a;有些ZIP文件&#xff0c;里面有中文文件名。在WINDOWS系统中解压缩正常。 但是在Ubuntu20.04下可以解压缩&#xff0c;…

OSPF基础(1):工作过程、状态机、更新

OSPF基础 1、技术背景&#xff08;与RIP密不可分&#xff0c;因为RIP中存在的问题&#xff09; RIP中存在最大跳数为15的限制&#xff0c;不能适应大规模组网周期性发送全部路由信息&#xff0c;占用大量的带宽资源以路由收敛速度慢以跳数作为度量值存在路由环路可能性每隔30秒…

python学opencv|读取图像(五十三)原理探索:使用cv.matchTemplate()函数实现最佳图像匹配

【1】引言 前序学习进程中&#xff0c;已经探索了使用cv.matchTemplate()函数实现最佳图像匹配的技巧&#xff0c;并且成功对两个目标进行了匹配。 相关文章链接为&#xff1a;python学opencv|读取图像&#xff08;五十二&#xff09;使用cv.matchTemplate()函数实现最佳图像…

C#面试常考随笔12:游戏开发中常用的设计模式【C#面试题(中级篇)补充】

C#面试题&#xff08;中级篇&#xff09;&#xff0c;详细讲解&#xff0c;帮助你深刻理解&#xff0c;拒绝背话术&#xff01;-CSDN博客 简单工厂模式 优点&#xff1a; 根据条件有工厂类直接创建具体的产品 客户端无需知道具体的对象名字&#xff0c;可以通过配置文件创建…

动手学图神经网络(9):利用图神经网络进行节点分类 WeightsBiases

利用图神经网络进行节点分类Weights&Biases 引言 在本篇博客中,将深入探讨如何使用图神经网络(GNNs)来完成节点分类任务。以 Cora 数据集为例,该数据集是一个引用网络,节点代表文档,推断每个文档的类别。同时,使用 Weights & Biases(W&B)来跟踪实验过程和…

React 低代码项目:项目创建

Date: January 29, 2025 项目创建 思路&#xff1a; 使用 Create-React-App 创建 React 项目使用 Vite 创建 React 项目使用 eslint prettier husty 等&#xff0c;制定编码规则 创建项目 注&#xff1a;在这之前&#xff0c;推荐 node 版本&#xff1a;node/18.20.6 &#…

网络工程师 (21)网络的性能

一、速率&#xff08;数据率或比特率&#xff09; 定义&#xff1a;数据在数字信道上传送的速率&#xff0c;通常以比特每秒&#xff08;bps&#xff09;为单位。常见的速率单位还有千比特每秒&#xff08;kbit/s&#xff09;、兆比特每秒&#xff08;Mbit/s&#xff09;和吉比…

VMware Win10下载安装教程(超详细)

《网络安全自学教程》 从MSDN下载系统镜像&#xff0c;使用 VMware Workstation 17 Pro 安装 Windows 10 consumer家庭版 和 VMware Tools。 Win10下载安装 1、下载镜像2、创建虚拟机3、安装操作系统4、配置系统5、安装VMware Tools 1、下载镜像 到MSDN https://msdn.itellyou…

开源智慧园区管理系统对比其他十种管理软件的优势与应用前景分析

内容概要 在当今数字化快速发展的时代&#xff0c;园区管理软件的选择显得尤为重要。而开源智慧园区管理系统凭借其独特的优势&#xff0c;逐渐成为用户的新宠。与传统管理软件相比&#xff0c;它不仅灵活性高&#xff0c;而且具有更强的可定制性&#xff0c;让各类园区&#…

Chapter 4-1. Troubleshooting Congestion in Fibre Channel Fabrics

This chapter covers the following topics: 本章包括以下内容: Congestion troubleshooting methodology and workflow. Hints and tips for troubleshooting congestion. Cisco MDS NX-OS commands for troubleshooting congestion. Case studies demonstrating troubleshoo…

无界构建微前端?NO!NO!NO!多系统融合思路!

文章目录 微前端理解1、微前端概念2、微前端特性3、微前端方案a、iframeb、qiankun --> 使用比较复杂 --> 自己写对vite的插件c、micro-app --> 京东开发 --> 对vite支持更拉跨d、EMP 方案--> 必须使用 webpack5 --> 很多人感觉不是微前端 --> 去中心化方…

4G核心网的演变与创新:从传统到虚拟化的跨越

4G核心网 随着移动通信技术的不断发展&#xff0c;4G核心网已经经历了从传统的硬件密集型架构到现代化、虚拟化网络架构的重大转型。这一演变不仅提升了网络的灵活性和可扩展性&#xff0c;也为未来的5G、物联网&#xff08;LOT&#xff09;和边缘计算等技术的发展奠定了基础。…

PL/SQL Developer如何连接Oracle数据库(汉化)

博主主页:【南鸢1.0】 本文专栏&#xff1a; database 目录 简介 准备工作 一、下载PLSQL Developer 二、解压 三、安装PLSQL Developer 1、找到plsqldev1402x64.msi 2、接受协议【Next】 3、安装路径 4、选择安装方式 5、点击Install等待安装 6、首次打开 7、输入…

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之修改密码和个人资料

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【Spring篇】【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f383;1.修改密码 -持久…

OpenAI 实战进阶教程 - 第四节: 结合 Web 服务:构建 Flask API 网关

目标 学习将 OpenAI 接入 Web 应用&#xff0c;构建交互式 API 网关理解 Flask 框架的基本用法实现 GPT 模型的 API 集成并返回结果 内容与实操 一、环境准备 安装必要依赖&#xff1a; 打开终端或命令行&#xff0c;执行以下命令安装 Flask 和 OpenAI SDK&#xff1a; pip i…

oracle 基础语法复习记录

Oracle SQL基础 因工作需要sql能力&#xff0c;需要重新把sql这块知识重新盘活&#xff0c;特此记录学习过程。 希望有新的发现。加油&#xff01;20250205 学习范围 学习SQL基础语法 掌握SELECT、INSERT、UPDATE、DELETE等基本操作。 熟悉WHERE、GROUP BY、ORDER BY、HAVIN…

【Day32 LeetCode】动态规划DP Ⅴ 完全背包

一、动态规划DP Ⅴ 完全背包 1、完全背包理论 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品都有无限个&#xff08;也就是可以放入背包多次&#xff09;&#xff0c;求解将哪些物品装入背包里物品价值总和…