带你手撕排序算法

news2024/10/9 12:30:52

文章目录

  • 前言
  • 一、排序的相关概念
  • 二、插入排序
    • 1.直接插入
      • (1)算法思想
      • (2)算法讲解
      • (3)代码及解析
      • (4)代码总结
    • 2.希尔排序( 缩小增量排序 )
      • (1)算法思想
      • (2)算法讲解
      • (3)代码及其解析
      • (4)代码总结
  • 三、选择排序(改进版)
    • 1.直接选择排序
      • (1)算法思想
      • (2)算法讲解
      • (3)算法注意事项
      • (4)代码及解析
      • (5)算法总结
    • 2.堆排序
      • (1)堆的介绍
      • (2)算法思想
      • (3)算法讲解
      • (4)代码及解析
      • (5)时间复杂度讲解
      • (6)算法总结
  • 三、交换排序
    • 1.冒泡排序
      • (1)算法思想
      • (2)算法讲解
      • (3)算法代码
      • (4)算法总结
    • 2.快速排序
      • (1)算法思想
      • (2)挖坑法
      • (3)左右指针法(不建议使用)
      • (4)前后指针法
      • (5)总代码及解析
      • (6)注意事项及改进
      • (7)算法总结
  • 三、归并排序
    • 1.归并排序
      • (1)算法思想
      • (2)算法讲解
      • (3)代码及解析
      • (4)算法总结
  • 总结


在这里插入图片描述

前言

鸽了好久了,希望大家能够理解,排序算法的学习和码文确实挺费时间的,本篇文章重要讲解以下排序算法和其拓展,其他排序以后会补充


在这里插入图片描述

一、排序的相关概念

概念提前说明一下,方便大家理解后续文章

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

二、插入排序

1.直接插入

(1)算法思想

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

在这里插入图片描述

(2)算法讲解

在这里插入图片描述

我们这里设排好了的数组的最后一位的位置为end,设temp = a[end + 1]

在这里插入图片描述

end+1=2, 2向前找比它小的数,如果没找到或者已经到头了,就将比他大的数全部为后面移动一位,所以这里5位后面移动一位,然后将已经保存在temp的2赋给啊a[end+1]

可能有人说这种情况不典型,好再讲一个比较典型的
在这里插入图片描述

这里3向前面找比他小的,然后他找到了2,在没找到之前,讲4,5,6向移动一位,在找到后,将3赋给找到的数的前面一位

以下为完整过程
在这里插入图片描述

(3)代码及解析

void InsertSort(int* a, int m)
{
	int i;
	for (i = 0; i < m - 1; ++i)
	{
		int end = i;
		int temp = a[end + 1];
		while (end >= 0)
		{
			if (a[end] > temp)//这一步是将大于temp的数全部向后移动
			{
				a[end + 1] = a[end];
				end--;
			}
			else//找到比temp小的,就直接退出			
			{
				break;
			}	
		}
		a[end + 1] = temp;
	}
}

(4)代码总结

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:最坏情况为逆序时,或者接近逆序时O(N^2),最好情况为升序时,或者接近升序时O(N)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定

当接近有序时,我们将比temp大的数移动的次数将会减少,所以算法的效率更高,因此我们就需要对原本的数据进行处理,使得效率得以提升,那就是希尔排序

2.希尔排序( 缩小增量排序 )

(1)算法思想

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

(2)算法讲解

这里放一张图,基本就清楚了

我们对其进行分组,每组都用直接插入排序进行排序,那么整体就接近有序了,当gap=1时就是直接插入排序了
在这里插入图片描述

(3)代码及其解析

可能有细心的小伙伴就发现了,无非就是将插入排序的1改成了gap吗?也确实是这样,无非是在插入排序上加了一个while循环控制gap而已

void ShellSort(int* a, int m)
{
	int gap = m;
	while (gap > 1)
	{
		gap = gap / 3 + 1;//这里加一就可以保证gap最后为1,从而变成直接插入排序
		for (int i = 0; i < m - gap; i++)
		{
			int end = i;
			int temp = a[end + gap];
			while (end >= 0)
			{
				if (a[end] > temp)
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = temp;
		}
	}
}

(4)代码总结

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试对比。
  3. 希尔排序的时间复杂度不好计算,需要进行推导,推导出来平均时间复杂度: O(N1.3—N2)
  4. 稳定性:不稳定

三、选择排序(改进版)

1.直接选择排序

(1)算法思想

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的
数据元素排完

(2)算法讲解

maxi向前面找最大的数,maxi记录最大的数的下标,mini向前找最小的数,mini记录最小的数的下标,然后将min与begin位置的值交换,将max与end位置的值交换
在这里插入图片描述

(3)算法注意事项

如果在maxi交换或者mini的交换过程中交换的值刚好出现在begin或者end,那么就会出现bug,bug有以下处理方法

在这里插入图片描述
你问我为什么手写?哈哈哈,手写的更加引人瞩目一点,你要是说我字丑,我就打洗你(

(4)代码及解析

void SelectSort(int* a, int m)
{
	int begin = 0;
	int end = m - 1;
	while (begin < end)
	{
		int maxi = begin;
		int mini = begin;
		for (int i = begin; i <= end; i++)
		{
			if (a[maxi] < a[i])
			{
				maxi = i;
			}
			if (a[mini] > a[i])
			{
				mini = i;
			}
		}
		Swap(&a[end], &a[maxi]);
		if (mini == end)//这里不懂看注意事项
		{
			mini = maxi;
		}
		Swap(&a[begin], &a[mini]);

		begin++;
		end--;
	}
}

(5)算法总结

  1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  2. 时间复杂度:传统O(N^2),改进的代码能到N*logN
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

2.堆排序

堆排序就需要对前面的二叉树有一定的理解才能弄明白,如果不懂的可以移步至我的前一篇文章

(1)堆的介绍

一张图解决

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

(2)算法思想

堆排序主要用的是向下调整算法·,向下调整算法建立在左右子树已经是大堆或者是小堆才能有用,那么向下调整的思想是怎么实现的?
如果我们是建大堆,向下调整算法是将一个节点与其子节点的最大值比较比较,如果子节点有比其大的,就交换两者的值,然后继续向下,将交换的节点的子节点继续向下比直到叶子节点(此算法有一个大前提),就是子节点必须是大堆或者小堆

那么就有人问如果子节点不是大堆或者小堆怎么办?我们可以从最底部不是叶子节点的位置开始(因为叶子节点本身就身就是大堆或者小堆),对每个每个节点都使用向下调整算法,一直调到root节点,那么一个堆就完成了,然后最大的值放在最后,然后继续对这个最大的数的前面的数建堆,然后继续与未排序好的数组的交换将是不是就ok了呢?这就是堆排序的思想,总是搞出最大的数排在最后

(3)算法讲解

我们拿这个二叉树讲
在这里插入图片描述
这里我们建大堆,我们首先找到最后一个非叶子节点8,然后用8比较其节点,无需交换在到7这个节点,其应该与9交换,然后就到2,其应该与6交换(这是建堆的过程,后面的交换过程我就不讲了)
在这里插入图片描述
然后看这图
在这里插入图片描述

(4)代码及解析

//向下调整代码(父子关系不清楚的看堆的介绍)
void AdjustDown(int* a, int n, int root)
{
	int parent = root;
	int child = parent * 2 + 1;
	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
		{
			++child;
		}
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
//堆排序算法
void HeapSort(int* a, int n)
{
	
	int i;
	int end = n - 1;
	//建堆,将一个数组建成一个堆的样子
	for (i = (n - 1 - 1) / 2; i >= 0; --i)
	{
		AdjustDown(a, n, i);
	}
	//交换堆的root到最后,然后将数组的大小减小,然后继续向下用调整算法
	while (end > 0)
	{
		Swap(a, &a[end]);
		end--;
		AdjustDown(a, end + 1, 0);//因为这个数组已经是一个堆了所以我们只需要对其用向下调整算法就行了
	}

}

(5)时间复杂度讲解

这个算法的时间复杂度不好求解,所以我来讲解一下

有人问为什么用图?因为图清晰明了(忽略字,说字丑的小心我打洗你)
求堆排序的复杂度需要知道高中的数列的错位相减法(自行了解)
在这里插入图片描述

(6)算法总结

  1. 堆排序使用堆来选数,效率就高了很多。
  2. 时间复杂度:向下调整算法O(N)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

三、交换排序

基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排
序的特点是:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

1.冒泡排序

(1)算法思想

与水中的气泡上浮相似,大的先上去,小的后上去

(2)算法讲解

一图解决
在这里插入图片描述

(3)算法代码

这里偷下懒,更加推荐各位去看我前面的文章,这里对冒泡排序有更加深刻的解释冒泡排序改进

(4)算法总结

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

2.快速排序

(1)算法思想

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序
元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有
元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所
有元素都排列在相应位置上为止
在这里插入图片描述
在这里插入图片描述

(2)挖坑法

先设立一个key记录begin的值,再在begin处设个坑pivot,先让end从后往前找比key小的值,找到了就将这个值放入坑中,然后这个比key小的值就成为了坑,然后用begin向后找比key大的值找到了就放入坑中,重复上述过程最后begin和end相交,这个位置就是key应该到的位置(代码中的三数取中后面的改进方法会讲)

//挖坑法
int PartSort1(int* a, int left, int right)
{

	int begin = left, end = right;
	int mid = GetMidIndex(a, left, right);//三数取中
	Swap(&a[mid], &a[begin]);
	int key = a[begin];
	int pivot = begin;
	while (begin < end)
	{
		while (begin < end && a[end] >= key)
		{
			end--;
		}
		a[pivot] = a[end];
		pivot = end;
		while (begin < end && a[begin] <= key)
		{
			begin++;
		}
		a[pivot] = a[begin];
		pivot = begin;
	}
	a[begin] = key;
	return pivot;
}

(3)左右指针法(不建议使用)

先设立一个keyi用来记录begin,用begin向后找比keyi大的值,找到了就停下,让end从后往前找比key小的值找到了就停下,然后交换两者的值,两者相遇的位置即是keyi的位置,然后交换keyi位置的值和相遇位置的值

//左右指针法
int PartSort2(int* a, int left, int right)
{
	int mid = GetMidIndex(a, left, right);
	Swap(&a[left], &a[mid]);
	int begin = left, end = right;
	int keyi = begin;
	while (begin < end)
	{
		while (begin < end && a[end] >= a[keyi])
		{
			end--;
		}
		while (begin < end && a[begin] <= a[keyi])
		{
			begin++;
		}
		Swap(&a[begin], &a[end]);
	}
	Swap(&a[keyi], &a[begin]);
	return begin;
}

(4)前后指针法

keyi记录begin,设prev = left, cur = left + 1,让cur往后面找比key小的值,找到了就给prev++,然后给交换prev和cur的值,一直重复直到cur>=n,prev的位置就应该放key,下面是一个例子的过程
在这里插入图片描述

(5)总代码及解析

//三数取中
int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) >> 1;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
		{
			return mid;
		}
		else if (a[left] > a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
	else//a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
//挖坑法
int PartSort1(int* a, int left, int right)
{

	int begin = left, end = right;
	int mid = GetMidIndex(a, left, right);//三数取中
	Swap(&a[mid], &a[begin]);
	int key = a[begin];
	int pivot = begin;
	while (begin < end)
	{
		while (begin < end && a[end] >= key)
		{
			end--;
		}
		a[pivot] = a[end];
		pivot = end;
		while (begin < end && a[begin] <= key)
		{
			begin++;
		}
		a[pivot] = a[begin];
		pivot = begin;
	}
	a[begin] = key;
	return pivot;
}
//左右指针法
int PartSort2(int* a, int left, int right)
{
	int mid = GetMidIndex(a, left, right);
	Swap(&a[left], &a[mid]);
	int begin = left, end = right;
	int keyi = begin;
	while (begin < end)
	{
		while (begin < end && a[end] >= a[keyi])
		{
			end--;
		}
		while (begin < end && a[begin] <= a[keyi])
		{
			begin++;
		}
		Swap(&a[begin], &a[end]);
	}
	Swap(&a[keyi], &a[begin]);
	return begin;
}
//前后指针法
int PartSort3(int* a, int left, int right)
{
	int mid = GetMidIndex(a, left, right);
	Swap(&a[left], &a[mid]);
	int prev = left, cur = left + 1;
	int keyi = left;
	while (cur <= right)
	{
		while (a[cur] < a[keyi] && ++prev != cur)//自己交换自己浪费资源++prev != cur是减少不必要的浪费
		{
			Swap(&a[prev], &a[cur]);
		}
		++cur;
	}
	Swap(&a[prev], &a[keyi]);
	return prev;
}
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
	{
		return;
	}
	int keyindex = PartSort3(a, left, right);//可以调用3种方法的任意一种
	if (keyindex - 1 - left > 10)
	{
		QuickSort(a, left, keyindex - 1);
	}
	else
	{
		InsertSort(a + left, keyindex - 1 - left + 1);
	}
	if (right - (keyindex + 1) > 10)
	{
		QuickSort(a, keyindex + 1, right);
	}
	else
	{
		InsertSort(a + keyindex + 1, right - (keyindex + 1) + 1);
	}
}

(6)注意事项及改进

看到这里,有人可能有两个疑问
1.三数取中是什么,为什么要用三数取中?
2.快排主代码中为什么有插入排序?

>1.三数取中是将头和尾还有中间值这3个数中取一个·不大不小的值来当key,可以有效地防止出现数据有序(升序和降序)的最坏的情况
>因为一旦有序,每一次都相当于遍历了,效率很低
>2.这快排主要是依靠递归实现的,一旦区间分的很小后,递归深度会很深,所以被分成较小的区间时,数据比较有序,这时用插入排序效率更好

(7)算法总结

  1. 快速排序整体的综合性能和使用场景都是比较好的,所以才敢叫快速排序
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(logN)
  4. 稳定性:不稳定

三、归并排序

1.归并排序

(1)算法思想

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

(2)算法讲解

两图解决,当们将一组数据分为两半,用begin1和begin2分别指向两边的数据的首元素,依次比较,将小的放到另外的一个数组,在任意一个数组被拿完后,将另外一个数组全部复制过去,如果这个数组两边是有序的,我们就完成了,可惜两边不是有序的,那我们就继续分,直到分成只有一个,一个数据他始终有序,然后将两个一个的数组合在一起归并,这两个数据就有序了,然后这两个和另外的合并,直到完全合并,就行了
在这里插入图片描述
在这里插入图片描述

(3)代码及解析

void _MergeSort(int* a, int left, int right, int* temp)
{
	if (left >= right)
	{
		return;
	}
	int mid = (left + right) >> 1;
	_MergeSort(a, left, mid, temp);
	_MergeSort(a, mid + 1, right, temp);
	//这里用二叉树的知识理解,左右节点就是一层,当我我们解决掉一层后,我们就需要对这个代码进行归并
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = left;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			temp[index++] = a[begin1++];
		}
		else
		{
			temp[index++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		temp[index++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		temp[index++] = a[begin2++];
	}
	for (int i = left; i <= right; i++)
	{
		a[i] = temp[i];
	}
}

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

(4)算法总结

  1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问
    题。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(N)
  4. 稳定性:稳定

总结

在这里插入图片描述
好了,这篇文章总算爆肝完了(哭),希望对你有帮助,有错误请指正,谢谢

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

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

相关文章

maxcomputer的分区表相关操作

– 查看xsxw(学生行为表定义) desc xsxw; – 查看xsxw1(学生行为表定义) desc xsxw1; – 上面的两张表是通过ddl语句创建的分区表 – 创建ddl语句如下 – CREATE TABLE IF NOT EXISTS xsxw1( – xwsj STRING COMMENT ‘行为时间’, – xh STRING COMMENT ‘学号’, – xwdd ST…

基于OptiSystem的LD\LED\EDFA仿真分析

1、客户需求&#xff1a; &#xff08;1&#xff09; 仿真LD、LED直接调制系统的输出光谱&#xff0c;观察系统输出性能。 &#xff08;2&#xff09; 采用EDFA的光纤通信系统&#xff0c;实现对多路光波信号的放大&#xff0c;实现200km、40Gbit/s的传输。用仿真软件搭建一个…

关系数据库——关系代数

文章目录一、传统的集合运算二、专门的关系运算1.选择&#xff08;restriction&#xff09;2.投影&#xff08;Projection&#xff09;3.连接&#xff08;join&#xff09;1&#xff09;等值连接2&#xff09;自然连接4.除&#xff08;Division&#xff09;一、传统的集合运算 …

《深入浅出计算机组成原理》学习笔记 Day17

冒险和预测&#xff08;一&#xff09;1. 结构冒险2. 数据冒险参考1. 结构冒险 结构冒险本质上是一个硬件层面的资源竞争问题&#xff0c;也就是一个硬件电路层面的问题。 CPU 在同一个时钟周期内&#xff0c;同时在运行两条计算机指令的不同阶段&#xff0c;但这两个不同阶段…

Github消息推送到Telegram,并使用Vercel部署

Github buibuibui Telegram 仓库地址&#xff1a;https://github.com/yesmore/gh-buibuibui-tg 借助 Github 的 Webhooks、Vercel’s Serverless API 和 Telegram Bot&#xff0c;连接 Github 和 Telegram&#xff0c;在 Telegram chat 中接收仓库的消息。 效果&#xff1a;你…

深入分析ConcurrentHashMap1.8的扩容实现

什么情况会触发扩容 当往hashMap中成功插入一个key/value节点时&#xff0c;有可能触发扩容动作&#xff1a; 1、如果新增节点之后&#xff0c;所在链表的元素个数达到了阈值 8&#xff0c;则会调用treeifyBin方法把链表转换成红黑树&#xff0c;不过在结构转换之前&#xff0…

做跨境电商日本市场,如何才能让客户满意?

跨境电商作为互联网技术的产物&#xff0c;现如今早就风靡全世界。我国跨境电商行业的发展起步时间比较晚&#xff0c;但在各方力量的加持下&#xff0c;行业的发展日趋完善&#xff0c;行业对国内经济的带动作用也更加明显。当下许多国潮品牌在Starday等跨境电商服务平台的支持…

如何选择研发效能管理平台?好用的研发效能管理平台有哪些

本文将对比介绍8款比较知名的效能度量管理平台&#xff1a;1.PingCode&#xff1b;2.思码逸&#xff1b;3.云效&#xff1b;4.金山云&#xff1b;5.Git&#xff1b;6.Jenkins&#xff1b;7.Bamboo&#xff1b;8.Docker。但在对比研发效能平台之前&#xff0c;我们先来聊一些研发…

Linux驱动开发基础__POLL机制

目录 1 适用场景 2 POLL机制的内核代码详解 2.1 sys_poll 函数 2.2 do_sys_poll 函数 2.3 do_poll函数 3 poll机制使用流程 4 驱动编程 5 应用编程 6 代码 6.1 gpio_key_drv.c 6.2 button_test.c 6.3 Makefile 可以看 字符设备驱动程序之poll机制 那篇文章中的机…

【认证相关】FTA

FTA 测试需要涉及的工作与流程测试大致流程及涉及的工作送测Lab 之前需做的准备工作项目与测试样机基本信息如下信息请填写发给MTK&#xff0c;以便MTK 了解基本的认证项目与产品信息PICS 相关MTK 会提供一份Chip 的default PICS&#xff0c;但是客户还需要自行修改一些项的Val…

分享154个ASP源码,总有一款适合您

ASP源码 分享154个ASP源码&#xff0c;总有一款适合您 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c; 154个ASP源码下载链接&#xff1a;https://pan.baidu.com/s/1Jt3X-WAZv-rZswzjwyEtSQ?pwdt46u 提取码&#x…

【C++初阶】七、STL---vector模拟实现

目录 一、模拟实现接口总览 1.1 接口总览 1.2 vector整体框架 1.3 vector成员变量介绍 二、vector模拟实现 2.1 构造函数 2.1.1 无参构造 2.1.2 迭代器区间构造 2.1.3 n个val构造 2.1.4 拷贝构造 2.2 赋值运算符重载 2.2.1 传统写法 2.2.2 现代写法 2.3 析构函数…

蓝桥杯刷题018——和与乘积(贪心)

2021国赛&#xff1a;和与乘积 题目描述 给定一个数列 &#xff0c;问有多少个区间[L,R] 满足区间内元素的乘积等于他们的和&#xff0c;即 输入描述 输入第一行包含一个整数 n&#xff0c;表示数列的长度。 第二行包含 n 个整数&#xff0c;依次表示数列中的数 a1​,a2​,⋯,a…

【Vue】模板语法——文本插值

一、模板语法什么是模板语法Vue 使用一种基于 HTML 的模板语法&#xff0c;使我们能够声明式地将其组件实例的数据绑定到呈现的 DOM 上。所有的 Vue 模板都是语法层面合法的 HTML&#xff0c;可以被符合规范的浏览器和 HTML 解析器解析。在底层机制中&#xff0c;Vue 会将模板编…

(十四)docker安装nacos

一、简介 操作系统&#xff1a;Linux CentOS 7.3 64位 docker版本&#xff1a;19.03.8 nacos版本&#xff1a;默认拉取最新版本 二、实践 1、拉取镜像 docker pull nacos/nacos-server 2、运行容器 docker run --name nacos -p 8848:8848 \ --privilegedtrue \ --restar…

二、什么是GStreamer

GStreamer是一个用于创建流媒体应用程序的框架。基本的设计来自俄勒冈研究生院的视频管道&#xff0c;还有一些来自DirectShow的想法。 GStreamer的开发框架使编写任何类型的流媒体应用程序成为可能。GStreamer框架旨在使编写处理音频或视频或两者同时处理的应用程序变得容易。…

01_学习springdoc的基本使用

文章目录1 什么是 springdoc ?2 springdoc 基本信息3 maven 依赖4 正文来袭4.1 给 Controller 加注解4.2 给 Model 加注解5 大功告成1 什么是 springdoc ? 网上冲浪&#x1f3c4;&#x1f3fb;‍♂️时&#xff0c;无意间发现 java web 应用程序的在线接口文档&#xff0c;除…

开源大数据分析平台的内容有什么?

在大数据时代&#xff0c;做好数据管理是非常重要的一个步骤。可以给企业做出正确的经营决策&#xff0c;指引新的发展方向。因此&#xff0c;随着数字化时代的到来&#xff0c;很多企业都倾向于寻找适宜的开源大数据分析平台&#xff0c;以此提升企业办公协作效率&#xff0c;…

【184】Win10下Java8调用Python的face_recognition库来实现人脸识别

前言 face_recognition 是一个开源的、人脸识别的Python库。本文讲解了在 Windows 10操作系统上&#xff0c;使用 Java8 来调用 Python 的 face_recognition 库来实现人脸识别。虽然 Java8 有 Jython&#xff0c;但是由于截至发文时 Jython 支持的版本太老&#xff08;只有Pyt…

oracle——列表分页查询(原理)

文章目录前言数据表的准备分页sql1、简单分页实现2、排序分页3、排序优化前言 在平时的开发中&#xff0c;Oracle的分页查询用的特别多&#xff0c;接下来不止是说使用&#xff0c;更讲分页sql写法的原理。 数据表的准备 创建一张数据表&#xff0c;并填充大量的数据。 cre…