【数据结构】排序算法——Lessen1

news2024/11/26 9:14:04

Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
💥💥个人主页:奋斗的小羊
💥💥所属专栏:C语言

🚀本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。


目录

  • 前言
  • 一、常见排序算法
    • 1、插入排序
      • 1.1直接插入排序
      • 1.2希尔排序
    • 2、选择排序
      • 2.1直接选择排序
      • 2.2堆排序
    • 3、交换排序
      • 3.1冒泡排序
      • 3.2快速排序
        • 3.2.1 hoare版本
        • 3.2.2 挖坑法
        • 3.2.3 前后指针法

前言

所谓排序,就是将一组数据按照某种顺序进行排列的过程。
排序在很多应用中都非常重要,比如数据分析、搜索算法、数据库管理等。
本篇文章将详细介绍常见的排序算法。


一、常见排序算法

1、插入排序

1.1直接插入排序

插入排序是一种简单直观的排序算法,它的基本思想是将待排序的元素分为已排序和未排序两部分,然后逐步将未排序的元素插入到已排序的部分中,直到所有元素都被排序。

动图演示:

请添加图片描述

插入排序是比较容易理解的,代码实现也比较简单,唯一需要注意的是下标的取值范围,因为我们是从下标为1的元素开始向前比较的,所以下标最大的取值应该为n-2,这样保证我们刚好取到下标为n-1的最后一个元素。

代码示例:

//插入排序(升序)
void InsertSort(int* arr, int n)
{
	//先单次,再整体
	for (int i = 0; i < n - 1; i++)
	{
		//假设[0,end]有序,将end+1位置的元素插入
		int end = i;
		int tmp = arr[end + 1];
		while (end >= 0)
		{
			if (tmp < arr[end])
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else
			{
				break;
			}
		}
		arr[end + 1] = tmp;
	}
}

插入排序时间复杂度是O(N^2),总体来说效率也是不高的,但在某些场景中还是有发挥空间。


1.2希尔排序

希尔排序是一种插入排序的改进版本,以增量gap(通常是gap = n/3 + 1)来划分元素,使得远离的元素能够交换,从而加快整体排序的速度。它的基本思想是将待排序的序列分成若干个子序列(也称为“增量”),对每个子序列进行直接插入排序,然后逐步减少增量(gap = gap / 3 + 1),最终进行一次普通的插入排序,从而实现整体排序。

  • 当gap > 1时都是预排序,目的是让数组更接近于有序
  • gap = gap / 3 + 1;后面+1是为了保证最后一次gap的值为1

当gap=1时,相当于直接插入排序,希尔排序是直接插入排序算法上改进而来的,综合来说它的效率肯定是要高于直接插入排序的。

在这里插入图片描述

代码示例:
(1)

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

(2)

//希尔排序
void ShellSort(int* arr, int n)
{
	//多组并着走
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = arr[end + gap];
			while (end >= 0)
			{
				if (tmp < arr[end])
				{
					arr[end + gap] = arr[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			arr[end + gap] = tmp;
		}
	}
}

这两种方式都是可以的,虽然循环层数不一样,但是时间复杂度是一样的。
希尔排序的时间复杂度比较特别,理想情况下希尔排序的时间复杂度为:O(N^1.3)。希尔排序和堆排序是一个量级的。

根据希尔排序的特点,可以总结出下面的折线图:
在这里插入图片描述

因此,希尔排序在最初和最后的排序次数都为n,即前一阶段排序次数逐渐上升,当到达某一顶点时,排序次数逐渐下降到n,而该顶点非常难计算。

因为gap的取值很多,导致希尔排序的时间复杂度不好计算,我们只需记住当n在某个特定返回内,时间复杂度约为O(N^1.3)


2、选择排序

2.1直接选择排序

选择排序的基本思想是每一次从待排序的数组中选出最小(或最大)的一个数,存在起始位置,知道全部数据排完。为了提高效率,我们每次从待排序数组中同时找到最小和最大的两个数,分别将它们放到起始、末尾位置。

动图演示:

请添加图片描述

代码示例:

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

直接选择排序的时间复杂度是O(N^2),效率很低,甚至还比不过冒泡排序,因此在实际中基本不使用,主要用于教学。


2.2堆排序

堆排序在之前的文章中有详解介绍,这里就不再赘述。

void HeapSort(int* arr, int n)
{
	//升序,建大堆
	//降序,建小堆
	
	//向下调整建堆
	//O(N)
	for (int i = (n-1-1) / 2; i >= 0; i--)
	{
		AdjustDown(arr, i, n);
	}
	
	//O(N*logN)
	int end = n - 1;
	while (end > 0)
	{
		Swap(&arr[0], &arr[end]);
		AdjustDown(arr, 0, end);
		end--;
	}
}

3、交换排序

3.1冒泡排序

冒泡排序是一种简单的排序算法,其基本原理是通过重复遍历待排序的元素,比较相邻的两个元素,如果顺序错误则交换它们,直到没有需要交换的元素为止。

当某一趟并未发生交换说明此时数组已经有序,可以提前退出循环,我们可以设定一个标志来判断某一趟是否未发生交换。

动图演示:

请添加图片描述

代码示例:

//冒泡排序
void BubbleSort(int* arr, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int flag = 1;
		for (int j = i; j < n - j - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				flag = 0;
				Swap(&arr[j], &arr[j + 1]);
			}
		}
		if (1 == flag)
		{
			break;
		}
	}
}

冒泡排序的时间复杂度是O(N^2),效率是比较低的,在实际应用中很少用到,主要用于教学。


3.2快速排序

快速排序是一种二叉树结构的交换排序法,其基本思想是:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两个子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列有序。

快排主框架:

void _QuickSort(int* arr, int left, int right)
{
	//递归结束条件
	if (left >= right)
	{
		return;
	}
	//_QuickSort用于按照基准值将区间[left, right)中的元素进行划分
	QuickSort(arr, left, keyi - 1);
	QuickSort(arr, keyi + 1, right);
}

将区间中的元素进行划分的_QuickSort方法主要有以下几种实现方法。


3.2.1 hoare版本

| 算法思路: (默认排升序)

  • 创建左右指针,确定基准值
  • 从右向左找出比基准值小的数据,从左向右找出比基准值大的数据,左右指针数据交换,进入下次循环
  • 如果在最左边找基准值,则右边先走,反之则左边先走

动图演示:

请添加图片描述

我们可以将最左边的数作为基准值,先从右向左找小于基准值的数记住当前位置end,然后从左向右找大于基准值的数记住当前位置begin,交换两个数的位置;重复上述操作直到beginend指向同一位置,此时这个位置的值一定小于基准值,最后再将这个位置的值与基准值交换位置,此时作为基准值的数已经排到了它相应的位置。

代码示例:

//快速排序
void QuickSort(int* arr, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	int keyi = left;
	int begin = left;
	int end = right;
	while (begin < end)
	{
		//右边找小
		while (begin < end && arr[end] >= arr[keyi])
		{
			end--;
		}
		//左边找大
		while (begin < end && arr[begin] <= arr[keyi])
		{
			begin++;
		}
		Swap(&arr[begin], &arr[end]);
	}
	Swap(&arr[begin], &arr[keyi]);
	keyi = begin;
	QuickSort(arr, left, keyi - 1);
	QuickSort(arr, keyi + 1, right);
}

但是此时的快排代码还有一些缺陷,当待排集合已经接近有序时,快排的效率是很低的,如果数据量比较大还会因为函数递归太深而导致栈溢出。
因为我们将最左边的数当做基准值时,如果这个数恰好是最小或比较小的数,此时从右向左的数基本都比这个基准值大,所以会有很多次的递归调用。

| 优化一:
解决这个问题的办法就是我们找基准值时尽量找数据中不大不小的数,可以粗略的从数据头、数据中、数据尾三个位置的值中选中间值作为基准值,这样就可以很大的降低递归太深而导致栈溢出的风险。

//三数取中
int GetMidi(int* arr, int left, int right)
{
	int midi = (left + right) / 2;
	if (arr[left] < arr[right])
	{
		if (arr[right] < arr[midi ])
		{
			return right;
		}
		else if (arr[left] < arr[midi ])//arr[left]<arr[right] &&
		                               //arr[midi ]<arr[right]
		{
			return midi ;
		}
		else
		{
			return left;
		}
	}
	else
	{
		if (arr[right] > arr[midi ])
		{
			return right;
		}
		else if (arr[left] > arr[midi ])
		{
			return midi ;
		}
		else
		{
			return left;
		}
	}
}

拿到理想的基准值后,为了保证我们之前写的按最左边数作为基准值,可以将这个基准值和最左边的数交换位置。

//快速排序
void QuickSort(int* arr, int left, int right)
{
	if (left >= right)
	{
		return;
	}

	int midi = GetMidi(arr, left, right);
	Swap(&arr[left], &arr[midi ]);

	int keyi = left;
	int begin = left;
	int end = right;
	while (begin < end)
	{
		//右边找小
		while (begin < end && arr[end] >= arr[keyi])
		{
			end--;
		}
		//左边找大
		while (begin < end && arr[begin] <= arr[keyi])
		{
			begin++;
		}
		Swap(&arr[begin], &arr[end]);
	}
	Swap(&arr[begin], &arr[keyi]);
	keyi = begin;
	QuickSort(arr, left, keyi - 1);
	QuickSort(arr, keyi + 1, right);
}

| 优化二:
我们知道快速排序是二叉树结构的排序算法,当二叉树的层数较高时,此时分割的区间数据量比较小,而递归次数又占总体的大部分,可以考虑小区间优化,不再递归分割排序,减少递归的次数。
当数据量比较小时,排序算法的效率基本一致,我们优先考虑简单且较为高效的插入排序

//快速排序
void QuickSort(int* arr, int left, int right)
{
	if (left >= right)
	{
		return;
	}

	//小区间优化,不再递归分割排序,减少递归次数
	if ((right - left) + 1 < 10)
	{
		InsertSort(arr + left, (right - left) + 1);
	}
	else
	{
		//三数取中
		int midi = GetMidi(arr, left, right);
		Swap(&arr[left], &arr[midi ]);

		int keyi = left;
		int begin = left;
		int end = right;
		while (begin < end)
		{
			//右边找小
			while (begin < end && arr[end] >= arr[keyi])
			{
				end--;
			}
			//左边找大
			while (begin < end && arr[begin] <= arr[keyi])
			{
				begin++;
			}
			Swap(&arr[begin], &arr[end]);
		}
		Swap(&arr[begin], &arr[keyi]);
		keyi = begin;
		QuickSort(arr, left, keyi - 1);
		QuickSort(arr, keyi + 1, right);
	}
}

有了这两个优化,快排的效率就能得到很大的提升。


3.2.2 挖坑法

| 算法思路: (默认排升序)

首先将最左边的数据作为基准值拿出来,则原位置形成一个空位,创建左右指针,从右向左找出比基准值小的数据,找到后立即放入左边坑中,当前位置变为新的“坑”,重复上述操作直到左右指针相遇,最后再将基准值放入左右指针共同指向的“坑”中。

动图演示:

请添加图片描述
代码示例:

//挖坑法
void QuickSort(int* arr, int left, int right)
{
	//递归结束条件
	if (left >= right)
	{
		return;
	}

	//区间优化,减少递归次数
	if (right - left + 1 < 10)
	{
		InsertSort(arr + left, right - left + 1);
	}
	else
	{
		//三数取中
		int midi = GetMidi(arr, left, right);
		Swap(&arr[left], &arr[midi]);

		int keyi = left;
		int tmp = arr[keyi];
		int begin = left;
		int end = right;
		while (begin < end)
		{
			while (begin < end && arr[end] >= tmp)
			{
				end--;
			}
			arr[keyi] = arr[end];
			while (begin < end && arr[begin] <= tmp)
			{
				begin++;
			}
			if (begin == end)
			{
				arr[begin] = tmp;
				break;
			}
			arr[end] = arr[begin];
			keyi = begin;
		}
		keyi = begin;
		QuickSort(arr, left, keyi - 1);
		QuickSort(arr, keyi + 1, right);
	}
}

挖坑法虽然没有效率的提升,但是相对于hoare版本还是有一些优势:

  • 挖坑法不用分析为什么左边取基准值而右边先走的问题,因为当左边取基准值时左边就自然而然的形成了一个“坑”
  • 也不用分析为什么相遇位置一定比基准值小(或大)的问题,因为它相遇的位置是坑,自然而然的基准值就应该放在坑里

3.2.3 前后指针法

| 算法思路:
创建前后指针,两个指针从左向右分别找遇到的第一个小于和大于基准值的数进行交换,将所有大于基准值的数全都推到最后,使得小的都排在基准值的左边,大的都排在基准值的右边。

动图演示:
请添加图片描述
代码实现:

//前后指针法
int QuickSort3(int* arr, int left, int right)
{
	//三数取中
	int midi = GetMidi(arr, left, right);
	Swap(&arr[left], &arr[midi]);

	int keyi = left;
	int prev = left;
	int cur = prev + 1;
	while (cur <= right)
	{
		//先判断大小,再++prev,保证了当不满足大小时prev不再++
		if (arr[cur] < arr[keyi] && ++prev != cur)
		{
			Swap(&arr[prev], &arr[cur]);
		}
		cur++;
	}
	Swap(&arr[keyi], &arr[prev]);
	return prev;
}

这三种快排算法,前后指针法代码是最为清晰明了的,但三种算法时间复杂度是一样的。

| 三种快排算法汇总:

//三数取中
int GetMidi(int* arr, int left, int right)
{
	int midi = (left + right) / 2;
	if (arr[left] < arr[right])
	{
		if (arr[right] < arr[midi])
		{
			return right;
		}
		else if (arr[left] < arr[midi])
		{
			return midi;
		}
		else
		{
			return left;
		}
	}
	else
	{
		if (arr[right] > arr[midi])
		{
			return right;
		}
		else if (arr[left] > arr[midi])
		{
			return left;
		}
		else
		{
			return midi;
		}
	}
}

//hoare法
int QuickSort1(int* arr, int left, int right)
{
	//三数取中
	int midi = GetMidi(arr, left, right);
	Swap(&arr[left], &arr[midi]);

	int keyi = left;
	int begin = left + 1;
	int end = right;
	while (begin < end)
	{
		//左边作基值,右边先走
		while (begin < end && arr[end] >= arr[keyi])
		{
			end--;
		}
		while (begin < end && arr[begin] <= arr[keyi])
		{
			begin++;
		}
		Swap(&arr[begin], &arr[end]);
	}
	Swap(&arr[begin], &arr[keyi]);
	return begin;
}

//挖坑法
int QuickSort2(int* arr, int left, int right)
{
	//三数取中
	int midi = GetMidi(arr, left, right);
	Swap(&arr[left], &arr[midi]);

	int keyi = left;
	int tmp = arr[keyi];
	int begin = left + 1;
	int end = right;
	while (begin < end)
	{
		while (begin < end && arr[end] >= tmp)
		{
			end--;
		}
		arr[keyi] = arr[end];
		while (begin < end && arr[begin] <= tmp)
		{
			begin++;
		}
		if (begin == end)
		{
			arr[begin] = tmp;
			break;
		}
		arr[end] = arr[begin];
		keyi = begin;
	}
	return begin;
}

//前后指针法
int QuickSort3(int* arr, int left, int right)
{
	//三数取中
	int midi = GetMidi(arr, left, right);
	Swap(&arr[left], &arr[midi]);

	int keyi = left;
	int prev = left;
	int cur = prev + 1;
	while (cur <= right)
	{
		//先判断大小,再++prev,保证了当不满足大小时prev不再++
		if (arr[cur] < arr[keyi] && ++prev != cur)
		{
			Swap(&arr[prev], &arr[cur]);
		}
		cur++;
	}
	Swap(&arr[keyi], &arr[prev]);
	return prev;
}

void QuickSort(int* arr, int left, int right)
{
	//递归结束条件
	if (left >= right)
	{
		return;
	}

	//区间优化,减少递归次数
	if (right - left + 1 < 10)
	{
		InsertSort(arr + left, right - left + 1);
	}
	else
	{
		int keyi = QuickSort3(arr, left, right);
		QuickSort(arr, left, keyi - 1);
		QuickSort(arr, keyi + 1, right);
	}
}

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

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

相关文章

音乐播放器的优雅之选,黑金ONIX Overture XM5,更悦耳的音质体验

如今想要随时沉浸式的体验高品质的数字音乐资源&#xff0c;一款简单好用的音乐播放器必不可少&#xff0c;多年来在音乐爱好者的心中的经典品牌屈指可数&#xff0c;英国品牌ONIX算是一个&#xff0c;其Horizon系列以优雅的设计以及出众的品质&#xff0c;收获了很多忠实粉丝。…

OpenAI发布迷你AI模型GPT-4o mini

本心、输入输出、结果 文章目录 OpenAI发布迷你AI模型GPT-4o mini前言OpenAI发布迷你AI模型GPT-4o mini英伟达联合发布 Mistral-NeMo AI 模型:120 亿参数、上下文窗口 12.8 万个 tokenOpenAI发布迷你AI模型GPT-4o mini 编辑 | 简简单单 Online zuozuo 地址 | https://blog.csd…

【ADRC笔记】LESO-Wb

公式推导(bilibili) 一阶ESO 二阶ESO 二阶自抗扰控制器基本原理 选取状态变量 观测器收敛性推导 wo 观测器带宽

C语言·函数(超详细系列·全面总结)

前言&#xff1a;Hello大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;为了更好地形成一个学习c语言的体系&#xff0c;最近将会更新关于c语言语法基础的知识&#xff0c;今天更新一下函数的知识点&#xff0c;我们一起来看看吧&#xff01; 目录 一、函数是什么 &a…

HTTPServer改进思路1

Nginx源码思考项目改进 架构模式 事件驱动架构(EDA&#xff09;用于处理大量并发连接和IO操作 优点&#xff1a;高效处理大量并发请求&#xff0c;减少线程切换和阻塞调用技术实现&#xff1a;直接使用EPOLL&#xff0c;参考Node.js的http服务器 网络通信 协议&#xff1a;HTT…

day6 io线程

获取终端输入的字符

记录 cocos 开发问题 ,微信 wx.xxx函数 报找不到名称“wx”

今天写微信排行榜遇到 问题分享一下。 目前&#xff0c;微信、百度 和 抖音 小游戏这些平台为了保护其社交关系链数据&#xff0c;增加了 开放数据域 的概念&#xff0c;这是一个单独的游戏执行环境。开放数据域中的资源、引擎、程序&#xff0c;都和主游戏&#xff08;主域&a…

【2】Spring Cloud 工程搭建

&#x1f3a5; 个人主页&#xff1a;Dikz12&#x1f525;个人专栏&#xff1a;Spring Cloud实战&#x1f4d5;格言&#xff1a;吾愚多不敏&#xff0c;而愿加学欢迎大家&#x1f44d;点赞✍评论⭐收藏 目录 1.声明项目依赖和项目构建插件 2.完善子项目订单服务 2.1完善启动…

[Spring] Spring配置文件

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…

Spring推出Spring AI框架,看看怎么个事

文章目录 概述SpringAI介绍Spring AI 提供以下功能支持的聊天模型有哪些支持的文生图的模型有哪些支持的音频到文本模型支持的嵌入模型有哪些支持的矢量数据库有哪些 概述 在当今快速发展的技术时代&#xff0c;人工智能&#xff08;AI&#xff09;已经成为各行各业的关键驱动…

Linux——awk操作符

[rootlocalhost ~] # awk BEGIN{x2;y3;print x**y,x^y,x*y,x/y,xy,x-y,x%y} 8 8 6 0 .666667 5 -1 2 赋值运算符 条件运算符 awk 中的条件运算符只有一个&#xff0c;其语法如下&#xff1a; expression?value1:value2 这是一个三目运算符&#xff0c;当表达式 expre…

#三元运算符(python/java/c)

引入&#xff1a;什么是三元运算符呢&#xff1f;无疑其操作元有三个&#xff0c;一个是条件表达式&#xff0c;剩余两个为值&#xff0c;条件表达式为真时运算取第一个值&#xff0c;为假时取第二个值。 一 Python true_expression if condition else false_expressi…

网络通讯实验报告

拓扑图 需求 1、通过DHCP服务&#xff0c;给PC4和PC5分配IP地址、网关、掩码、DNS服务器IP地址 2、Client-1要求手工配置IP地址&#xff0c;为192.168.1.1, c 3、telnet客户端可以远程登录telnet服务器进行设备管理&#xff0c;并成功修改telnet服务器的名字为123 &#xff0c…

两轮差速拖动机械臂瞄准接收口目标

下图所示&#xff0c;关节2为无动力旋转关节&#xff0c;关节4为无动力移动关节&#xff0c;关节5为旋转关节&#xff0c;差速轮可绕轮中心点4自由旋转&#xff0c;差速轮带动2和4关节运动。设计差速轮和机械臂解算方法&#xff0c;使其相互配合到达接收口&#xff0c;瞄准目标…

树上前缀和树状数组结合

怎么去分析这个题目&#xff0c;一开始我想的就是暴力dfs&#xff0c;接着枚举删除的节点&#xff0c;但是只过了百分之四十个点&#xff0c;代码如下&#xff1a;(这个代码有点像树形dp&#xff09; #include<bits/stdc.h> using namespace std;#define int long long c…

SHL笔试测评题型题库大揭秘适用公司通过技巧神助攻

⭕SHL题库外企应用的比较多&#xff0c;整体来看分为三类。 ✅第一类是综合能力&#xff0c;考察综合素质&#xff0c;要求36分钟完成24道题&#xff0c;适用范围最广。题型有安排时间问题、比例题、记忆题、排序题、日历题、图形变换题、图形推理题、拖线条题等等&#xff0c…

Linux_生产消费者模型

目录 1、生产消费者模型示意图 2、生产者消费者之间的关系 3、定义交易场所 4、实现生产消费者模型 5、伪唤醒 6、多生产多消费者的实际运用 7、POSIX信号量 7.1 初始化信号量 7.2 销毁信号量 7.3 等待信号量 7.4 发布信号量 8、生产消费的环形队列模型 8.1…

接口测试之测试原则、测试用例、测试流程详解

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、接口的介绍 软件测试中&#xff0c;常说的接口有两种&#xff1a;图形用户接口&#xff08;GUI&#xff0c;人与程序的接口&#xff09;、应用程序编程接口&…

AWS云服务器购买:亚马逊云服务器的价格真的那么贵吗?一年要花多少钱?

亚马逊云服务器是全球领先的云计算服务提供商之一&#xff0c;其服务覆盖全球多个地区&#xff0c;拥有众多的客户和合作伙伴。然而&#xff0c;对于很多人来说&#xff0c;AWS的价格一直是一个热门话题。那么&#xff0c;亚马逊云服务器的价格真的那么贵吗&#xff1f;一年要花…

python爬虫Selenium模块及测试案例详解

什么是selenium&#xff1f; &#xff08;1&#xff09;Selenium是一个用于Web应用程序测试的工具。 &#xff08;2&#xff09;Selenium 测试直接运行在浏览器中&#xff0c;就像真正的用户在操作一样。 &#xff08;3&#xff09;支持通过各种driver&#xff08;FirfoxDrive…