C++-排序

news2024/10/5 21:59:31

文章目录

        • 常数操作
        • 时间复杂度
        • 空间复杂度
          • O(N^2) O(1) 数据情况发生变化不影响流程
    • 选择排序
    • 冒泡排序
          • 使用抑或运算
            • 提取出不为零的数最右边的1
        • 1. 实现两个变量交换值
        • 2. 数组中一种数字出现奇数次,other是偶数次,找到那一种数字
        • 3. 数组中有两种数字出现奇数次,other是偶数次,找到那两种数字
          • O(N^2) O(1) 数据情况发生变化影响流程
    • 插入排序(码牌)
        • 二分法
        • 对数器
    • 归并排序
          • 最小和问题
            • 不漏算
            • 不重复计算
        • 荷兰国旗问题
    • 快排
          • version1
          • version2
          • version3
          • 扩容
          • 使用系统提供的堆-黑盒测试
    • 桶排序
      • 计数排序
      • 基数排序
          • 数据结构如何实现入桶出桶模拟?
    • 稳定性
          • 选择排序-否-O(n^2)
          • 冒泡排序-是-O(n^2)
          • 插入排序-O(n^2)
          • 归并-是-O(nlogn)
          • 快排-否-O(nlogn)
          • 堆排-否-O(nlogn)
        • 改进
          • 冒泡排序-是-O(n^2)
          • 插入排序-O(n^2)
          • 归并-是-O(nlogn)
          • 快排-否-O(nlogn)
          • 堆排-否-O(nlogn)
        • 改进

动图帮助理解网站

排序方法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序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(n^1.3)O(n^2)O(1)不稳定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定
归并排序O(n*logn)O(n*logn)O(n*logn)O(n)稳定
快速排序O(n*logn)O(n*logn)O(n^2)O(logn)~O(n)不稳定

常数操作

一个操作如果和样本的数据量没有关系,每次都是固定时间内完成的操作,叫做常数操作

数组获取值:固定时间,常数操作.连续空间,距离和偏移量可以直接确认.链表不是连续空间

时间复杂度

具体来说,先要对一个算法流程非常熟悉,然后去写出这个算法流程中,发生了多少常数操作,
进而总结出常数操作数量的表达式。

在表达式中,只要高阶项,不要低阶项,也不要高阶项的系数,剩下的部分如果为f(N),那
么时间复杂度为O(f(N))。

先看时间复杂度指标,如果指标可以决出优劣即可,如果不能决出优劣指标相同,就需要再比较不同数据样本下的时间,常数项时间.

空间复杂度

另外开辟空间大小.

O(N^2) O(1) 数据情况发生变化不影响流程

选择排序

void SelectSort(int* a, int n)
	{
		if (a == nullptr || n < 2)
			return;
		for (int i = 0; i < n - 1; i++)
		{
			int minIndex = i;
			for (int j = i + 1; j < n; j++)
			{
				minIndex = a[minIndex] > a[j] ? j : minIndex;
			}
			swap(a[minIndex], a[i]);
		}
	}

冒泡排序

void BubbleSort(int* a, int n)
	{
		if (a == nullptr || n < 2)
			return;
		for (int e = n - 1; e > 0; e--)//右区间边界,一直向左缩小(因为一次遍历将最大值交换到最后)
		{
			for (int i = 0; i < e; i++)
			{
				if (a[i] > a[i + 1])
					swap(a[i], a[i + 1]);
			}
		}
	}
使用抑或运算
提取出不为零的数最右边的1
int rightOne=num&(~num+1);

image-20230601223400786

1. 实现两个变量交换值

不开辟另外的空间,但是两个变量必须指向两个空间,否则就会将这个位置的数值改为0.

抑或运算性质:

  1. 可理解为无进位相加
  2. 满足交换律 结合律

2. 数组中一种数字出现奇数次,other是偶数次,找到那一种数字

从头抑或到尾,得到的就是那个数字.

3. 数组中有两种数字出现奇数次,other是偶数次,找到那两种数字

从头抑或到尾得到eor,eor某一位必然不相同为1.根据这一位对数组进行分类,

再从新从头抑或一遍那一位为1的数字,偶数次的直接没,最后得到的一个不是a,就是b.

最后eor^eor’就是另一个数字.

O(N^2) O(1) 数据情况发生变化影响流程

插入排序(码牌)

数据情况发生变化影响流程.如果是想要的有序状态,就是O(N).按照算法最差情况估计时间复杂度O(N^2).

	//想让0~i的范围内有序
	void InsertSort(vector<int>& a, int n)
	{
		if (a.size()==0 || n < 2)
			return;
		for (int i = 1; i < n-1; i++)
		{
			for (int j = i - 1; j >= 0 && a[j] > a[j + 1]; j--)
			{
				swap(a[j], a[j + 1]);
			}
		}
	}

二分法

image-20230607113552401

class BS
{
public:
	//有序
	bool BSExist(int* a, int n, int x)
	{
		if (a == nullptr || n < 2)
			return false;
		int l = 0, r = n - 1;
		while (l < r)
		{
			int mid = l + ((r-l) >> 2);
			if (a[mid] > x)
				r = mid - 1;
			else if (a[mid] < x)
				l = mid + 1;
			else
				return true;
		}
		return a[l]==x;
	}
	//有序
	//找到最左侧大于等于x的位置值
	int BSNearLeft(int* a, int n,int x)
	{
		if (a == nullptr || n < 2)
			return -1;
		int l = 0, r = n - 1;
		int index = -1;
		while (l < r)
		{
			int mid = l + (r - l) / 2;
			if (a[mid] >= x)
			{
				index = mid;
				r = mid - 1;
			}
			else if (a[mid] < x)
			{
				l = mid + 1;
			}
		}
		return index;
	}
	//无序
	//找局部最小值
	int FindOneLessValue(int* a, int n)
	{
		if (a == nullptr || n == 0)
			return -1;
		//0位置
		if (n == 1 || a[0] < a[1])
			return a[0];
		//n-1位置
		if (a[n - 1] < a[n - 2])
			return a[n - 1];

		//[0,n-1]位置上必存在拐点,也就是局部最小值,直接取mid
		int l = 0, r = n - 1;
		int mid = 0;
		while (l < r)
		{
			mid = l + (r - l) / 2;
			if (a[mid] < a[mid + 1] && a[mid] < a[mid - 1])
				return mid;
			else if (a[mid - 1] < a[mid])
				r = mid - 1;
			else if (a[mid + 1] < a[mid])
				l = mid + 1;
		}
		return l;
	}
};

对数器

image-20230607113528436

归并排序

image-20230607130040457

class MergeSort
{
public:
	//拆分为二分,则b=2 a=2 log(b,a)==d==1 
	// d:其他操作是将N个数据->tmp中,tmp->arr原数组所以是2*T(N)是O(N)
	//T(N)=N^1*logN
	//O(N^2)的选择冒泡,几乎比较了将近N次才完成一个数位置的确定
	//归并:左有序区间开始和右边有序区间依次比较,没有浪费比较次数
	void mergeSort(vector<int>& arr)
	{
		if (arr.size() < 2)
			return;
		merageSortHelper(arr,0,arr.size()-1);
	}
	void merageSortHelper(vector<int>& arr, int l, int r)
	{
		if (l == r)return;
		int mid = l + ((r - l) >> 1);
		merageSortHelper(arr,l,mid);
		merageSortHelper(arr,mid+1,r);
		merge(arr,l,mid,r);
	}
	void merge(vector<int>& arr, int l, int mid, int r)
	{
		vector<int>tmp(r-l+1);
		int i = 0;
		int p1 = l;
		int p2 = mid + 1;
		while (p1 <= mid && p2 <= r)
		{
			tmp[i++] = arr[p1] > arr[p2] ? arr[p2++] : arr[p1++];
		}
		while (p1 <= mid)
			tmp[i++] = arr[p1++];
		while (p2 <= r)
			tmp[i++] = arr[p2++];
		for (i = 0; i < tmp.size(); i++)
			arr[l + i] = tmp[i];
	}
};

image-20230607133500698

最小和问题

转化为右边有多少个数比我大,我就累加几次的问题.

不漏算

任何一个数x的历程,左侧区间先和自己比然后合并为一个部分,计算产生小和,右侧区间再与自己所在有序区间合并,然后组成更大的部分,再和这一更大的部分右边更大的部分合并计算小和…

不重复计算

只有在左组和右组合并时才会产生小和的计算,组成的有序区间内部是不会有小和的计算的.

class SmallSum
{
public:
	int smallSum(vector<int>& arr)
	{
		if (arr.size() < 2)return 0;
		return mergeSort(arr,0,arr.size()-1);
	}
	int mergeSort(vector<int>& arr, int l, int r)
	{
		if (l == r)return 0;
		int mid = l + ((r - l)) >> 1;
		return mergeSort(arr,l,mid)+
				mergeSort(arr,mid+1,r)+
				merge(arr,l,mid,r);
	}
	int merge(vector<int>& arr, int l, int mid, int r)
	{
		vector<int>tmp(r-l+1);
		int i = 0;
		int p1 = l, p2 = mid + 1;
		int res = 0;
		while (p1 <= mid && p2 <= r)
		{
			res += arr[p1] < arr[p2] ? arr[p1] * (r - p2 + 1) : 0;
			tmp[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];//相等时一定是p2++,保证后续最小和正确性
		}
		while (p1 <= mid)
			tmp[i++] = arr[p1++];
		while (p2<=r)
			tmp[i++] = arr[p2++];
		for (i = 0; i < tmp.size(); i++)
			arr[l + i] = tmp[i];
		return res;
	}
};

荷兰国旗问题

image-20230607134950866

class NetherlandsFlag
{
public:
	//1. [i]<num [i]和less区间右边的数字交换,less区间右扩,i++
	//2. [i]>num [i]和more区间左边的数字交换,more区间左扩,i不变,因为此时i位置值是刚交换过来的,还不知道是啥值
	//3. [i]==num[i],i++即可,不做交换处理
	//动态观察就是less区间推着==区间向右挤压待定区域接近more区间,反之亦然.
	//如何推?相等区间最左(右)边值和[i](<num)交换,然后i++,实现的,反之亦然.
	pair<int,int> partition(vector<int>& arr,int l,int r,int p)
	{
		int less = l-1;
		int more = r + 1;
		while (l<more)
		{
			if (arr[l] < p)
			{
				swap(arr[l], arr[less + 1]);
				less++;
				l++;
			}
			else if (arr[l] > p)
			{
				swap(arr[l], arr[more - 1]);
				more--;
			}
			else
			{
				l++;
			}
		}
		return std::make_pair(less+1,more-1);//返回中间=区域的左边界和右边界
	}
};

快排

version1

就是将最后一个数当作num,让前n-1个数,[0,n-2]进行区间划分,最后将num和more区间最左边的值进行交换即可,这样搞定num一个数…然后划分左区间(<=num),右区间(>num)各自重复刚才的操作,取区间最后一个值作为num…;

version2

进行荷兰国旗问题,num和more区间最左值交换之后和前面的=num的区间合并,=num的区间一批数就不用再处理了,效率相对于version1更快点.再依次将less和more进行处理.

不管哪个版本,当是升序且不重复值的时候,每次partition只能搞定一个num值,即划分值num打的很极端,要么是最大要么是最小,最坏情况即T(N)=O(N^2).只有num是中间值1/2时才是最好的即

T(N)=2*T(N/2)+O(N)=>T(N)=O(N*logN)

version3

那么我随机选择一个数字作为num,然后对区间进行划分,可能我就选中那个使得数组一半一半的一种情况,也可能造成T(N/3)+T(2N/3)+O(N),选值也可能造成T(N/4)+T(3N/4)+O(N),每一种可能的概率是等价的1/N,因为我是在N个数中随机选择一个值进行对区间的划分,所有可能情况求期望就是O(N*logN)

class QuickSort
{
public:
	void quickSort(vector<int>& arr)
	{
		if (arr.size() < 2)
			return;
		quickSortHelper(arr, 0, arr.size() - 1);
	}
	void quickSortHelper(vector<int>& arr, int l, int r)
	{
		if (l < r)
		{
			swap(arr[l + (int)(rand() * (r - l + 1))], arr[r]);
			pair<int, int>p = partition(arr,l,r);
			quickSortHelper(arr,l,p.first-1);
			quickSortHelper(arr,p.second+1,r);
		}
	}
	pair<int, int>partition(vector<int>& arr, int l, int r)
	{
		int less = l - 1;
		int more = r + 1;
		while (l < more)
		{
			if (arr[l] > arr[r])
			{
				swap(arr[less + 1], arr[l]);
				l++;
				less++;
			}
			else if (arr[l] < arr[r])
			{
				swap(arr[more - 1], arr[l]);
				more--;
			}
			else
				l++;
		}
		swap(arr[r],arr[more]);
		return make_pair(less+1,more-1);
	}
};

空间复杂度

需要记录划分区间的中间值的位置,最差情况是O(N),当取到值正好二分区间时,情况就是O(logN)

只有记录了中点信息,才能确定右区间的范围,所以这个点需要记录,因为递归栈的存在记录了这个点的信息.

image-20230607222920687

数组从0出发连续的数字,可以想象为一个完全二叉树,左孩子2*i+1,右孩子是2*i+2,父亲节点是(i-1)/2

image-20230607222953303

class Heap
{
public:
	//我们认为前heapSize个值作为堆来看待
	// 
	//需求: 一个个在index位置添加值,如何建立大堆
	//向上调整
	void HeapInsert(vector<int>& arr, int index)
	{
		//index=0时,(index-1)/2=0,依然不满足条件
		while (arr[index] > arr[(index - 1) >> 1])
		{
			swap(arr[index],arr[(index-1)>>1]);
			index = (index - 1) >> 1;
		}
	}

	//	需求: 返回堆中最大值,并将他移除之后,仍然保持大堆
	// 将第heapSize-1位置的值放在0位置处,从顶开始向下调整
	// 选出两个孩子中较大值,比较之后交换位置
	// 交换跳出条件:
	//1. 交换之后没有孩子节点继续向下
	//2. 父亲节点大于max孩子节点
	//向下调整
	void HeapIfy(vector<int>& arr, int index, int heapSize)
	{
		int left = 2 * index + 1;
		while (left < heapSize)
		{
			int largest = left + 1 < heapSize && arr[left + 1] > arr[left] ? left + 1 : left;
			largest = arr[index] > arr[largest] ? index : largest;
			if (largest == index)
				break;
			swap(arr[largest], arr[index]);
			index = largest;
			left = index * 2 + 1;
		}
	}
	//在某一个位置发生值的改变,要么是变小了,如果保持大根堆,向下调整,变大了就向上调整
	//调整代价均为LogN级别

	//需求: 将已知数组中整理为大跟堆,我们初始化heapSize=0,认为[0,heapSize]认为是堆空间
	//就相当于一个个heapInsert操作
	void heapSort(vector<int>& arr)
	{
		if (arr.size() < 2)
			return;
		for (int i = 0; i < arr.size(); i++)//O(N)
		{
			HeapInsert(arr,i);//经历调整确定位置O(logN)
		}
		int heapSize = arr.size();
		swap(arr[0],arr[--heapSize]);
		while (heapSize > 0)//O(N)
		{
			HeapIfy(arr,0,heapSize);	//O(log(N))
			swap(arr[0],arr[--heapSize]);//O(1)
		}
	}
	//额外空间复杂度是O(1) 只需要申请几个变量空间即可
};
	//需求:将整个数组调整为大跟堆,从最后一个父亲节点开始向下调整heapIfy
	//最底层占将近一半,N/2,无法向下再调整,只看一眼,代价是1
	//倒数第二层N/4个,可以向下操作,看一眼,代价是2
	//倒数第二层N/8个,可以向下操作2次,看一眼,代价是3
	//....
	//整体复杂度就是T(N)=N/2*1+N/4*2+N/8*3....
	//从heapInsert的O(N*logN)=>O(N)
    
	//for (int i = (arr.size() - 1) / 2; i >= 0; i--)//O(N)
	//{
	//		HeapIfy(arr, i,heapSize);//经历调整确定位置O(logN)
	//}

image-20230607222715862

image-20230607223122048

选择小根堆,将K+1个数字插入到小跟堆中,堆顶就是最小值放到数组0的位置,继续向后遍历将值放入小跟堆,得到堆顶元素,再放到1的位置,全部入堆之后依次弹出堆顶元素即可.

O(N*logK)

#include<iostream>
#include<vector>
#include<queue>
using namespace std;
class SortArrDistanceLessK
{
public:
	void sortArrDistanceLessK(vector<int>& arr, int k)
	{
		priority_queue<int,vector<int>,greater<int>> heap;
		int index = 0;
		int n = arr.size();
		for (; index < min(k, n); index++)
		{
			heap.push(arr[index]);
		}
		int i = 0;
		for (; index < n; i++,index++)
		{
			heap.push(arr[index]);
			arr[i] = heap.top();
			heap.pop();
		}
		while (!heap.empty())
		{
			arr[i++] = heap.top();
			heap.pop();
		}
	}
};
int main()
{
	//priority_queue<int, vector<int>, less<int>> heap;//大堆
	//priority_queue<int> heap;//大堆
	priority_queue<int, vector<int>, greater<int>> heap;//大堆

	heap.push(8);
	heap.push(4);
	heap.push(6);
	heap.push(1);
	heap.push(3);
	while (!heap.empty())
	{
		cout << heap.top() << " ";
		heap.pop();
	}
}
扩容

每次扩容的代价是O(N)的,因为成倍的扩容需要将源数据拷贝到新数组中,但是扩容的次数是O(logN)

整体扩容代价就是O(N*logN),均摊到单点扩容时就是O(N*logN)/N=>O(logN)

使用系统提供的堆-黑盒测试

你add一个值,它弹出栈顶值返回一个值此时就不需要手写堆.

系统自身维护好的堆结构,想更改堆中值并想让他自己调整为合法堆结构是不支持的,只能采用遍历的方式决定怎么调整,效率很低.

自己手写的支持某一个位置值开始,效率较高的决定向上或者向下调整.

所以你想更改堆结构中的某一个值并让他自己高效率调整回堆结构时,还是自己手写一个更好.

image-20230608114940477

桶排序

image-20230608115019749

不进行数值比较的排序都会受到数据状况的影响.

计数排序

思想:统计数字出现情况开辟多大空间,然后O(N)遍历数组统计词频,输出数字即可.

#include<iostream>
#include<vector>
using namespace std;
class CountSort
{
public:
	void countSort(vector<int>& arr)
	{
		if (arr.size() == 0)
			return;
		int max_num = INT_MIN;
		for (int i = 0; i < arr.size(); i++)
			max_num = max(max_num, arr[i]);
		vector<int>bucket(max_num+1);
		for (int i = 0; i < arr.size(); i++)
		{
			bucket[arr[i]]++;
		}
		int i = 0;
		for (int j = 0; j < bucket.size(); j++)
			while (bucket[j]--)
				arr[i++] = j;
	}

};

基数排序

进制的存在10进制 ,就安排10个桶(可以是任何容器,数组,链表,队列),先让数字按照个位数字区分,分别进入到0~9编号的桶中,然后依次出桶;再按照十位数字依次入桶出桶…最后数组中完成排序.

最大数字的位数决定了入桶出桶的次数

数据结构如何实现入桶出桶模拟?

统计数组中每个数字个位数字出现的频次,入count数组中

然后做成前缀和,i位置表示个位数字小于等于i的数字一共有几个,从arr数组末尾向前遍历做出桶动作,得到数字num,他的个位数字是i,入桶时count数组下标i位置这个桶中,进桶肯定是最后一个进的,所以我们将他放在help数组中,那么他在辅助数组help中的下标就是数组count[i]-1,count[i]--,依次类推完成了一次根据个位数字的入桶出桶操作.

image-20230608130347549

#include<iostream>
#include<vector>
using namespace std;
class RadixSort
{
public:
	//基数排序
	void radixSort(vector<int>& arr)
	{
		if (arr.size() == 0)
			return;
		radixSorthelper(arr, 0, arr.size() - 1,maxDigits(arr));
	}
	int maxDigits(vector<int>& arr)
	{
		int max_num = INT_MIN;
		for (int i = 0; i < arr.size(); i++)
		{
			max_num = max(max_num,arr[i]);
		}
		int res = 0;
		while (max_num != 0)
		{
			res++;
			max_num /= 10;
		}
		return res;
	}
	int getDigit(int num, int d)
	{
		return ((num / ((int)pow(10, d - 1))) % 10);
	}
	void radixSorthelper(vector<int>& arr, int begin, int end,int digit)//多少位
	{
		int radix = 10;
		int i = 0, j = 0;
		vector<int>bucket(end-begin+1);//help
		for (int d = 1; d <= digit; d++)//位数决定入桶出桶多少次
										//d=1代表这次循环是个位
		{
			vector<int>count(radix);
			for (i = begin; i <= end; i++)
			{
				j = getDigit(arr[i],d);
				count[j++];
			}
			//10个桶,计算每个桶的前缀和
			for (i = 1; i < radix; i++)
			{
				count[i] = count[i] + count[i - 1];
			}
			for (int i = end; i >= begin; i--)
			{
				j = getDigit(arr[i],d);
				bucket[count[j] - 1] = arr[i];
				count[j]--;
			}
			for (i = begin, j = 0; i <= end; i++, j++)
			{
				arr[i] = bucket[j];
			}
		}
	}
};
//int main()
//{
//	RadixSort rs;
//	cout<<rs.getDigit(123,2)<<endl;
//	cout << pow(10, 1 - 1) << endl;
//	cout << (123 / ((int)pow(10, 2 - 1))) << endl;
//	cout << ((123 / ((int)pow(10, 2 - 1))) % 10) << endl;
//}

稳定性

值相同的元素排完之后能否保证相对顺序不发生改变.

基础类型之间稳定性不重要.自定义类型为了稳定性选归并不选快排.

情景:先根据商品的价格由高到低排序,再根据好评率从低到高排序,如果稳定性好,这样开头的就是物美价廉的商品.

选择排序-否-O(n^2)

在[0,n-1]上选择最小的放在0位置处,如果是3 3 3 3 3 3 13 3 3 3 3 ,会将第一个3与1交换,第一个3和1之间的几个3的相对位置发生改变,所以不稳定

冒泡排序-是-O(n^2)

相等值时不交换就完了

插入排序-O(n^2)

[0,i]区间上做到有序,往前看相等的时候,我就不换就完了呗.

归并-是-O(nlogn)

merge时,我让前区间相等值先拷贝到tmp数组中就可以了.

那么之前的最小和问题必须先让后区间相等值考入,那么就没有稳定性了.

快排-否-O(nlogn)

partition时遇到<5的就需要和<区前一个交换

image-20230608142956420

堆排-否-O(nlogn)

很轻易就可以破坏稳定性即相对位置.

不基于比较的排序很容易可以维持稳定性.

image-20230608143610290

image-20230608143642120

image-20230608143853282

经典快排partition是01标准,可以实现奇数在前偶数在后,但是无法实现稳定性,并且空间复杂度O(1)

改进

image-20230608144227920

大样本调度按照快排O(nlogn),小范围比如<=60,就让它小区间直接插入排序O(n^2)混着用就行->综合排序.

在[0,n-1]上选择最小的放在0位置处,如果是3 3 3 3 3 3 13 3 3 3 3 ,会将第一个3与1交换,第一个3和1之间的几个3的相对位置发生改变,所以不稳定

冒泡排序-是-O(n^2)

相等值时不交换就完了

插入排序-O(n^2)

[0,i]区间上做到有序,往前看相等的时候,我就不换就完了呗.

归并-是-O(nlogn)

merge时,我让前区间相等值先拷贝到tmp数组中就可以了.

那么之前的最小和问题必须先让后区间相等值考入,那么就没有稳定性了.

快排-否-O(nlogn)

partition时遇到<5的就需要和<区前一个交换

[外链图片转存中…(img-f2PF5BCk-1691664383774)]

堆排-否-O(nlogn)

很轻易就可以破坏稳定性即相对位置.

不基于比较的排序很容易可以维持稳定性.

[外链图片转存中…(img-qxzV5zE8-1691664383775)]

[外链图片转存中…(img-ZorBBZL9-1691664383775)]

[外链图片转存中…(img-P9EHRawr-1691664383775)]

经典快排partition是01标准,可以实现奇数在前偶数在后,但是无法实现稳定性,并且空间复杂度O(1)

改进

[外链图片转存中…(img-uq2tsAV6-1691664383776)]

大样本调度按照快排O(nlogn),小范围比如<=60,就让它小区间直接插入排序O(n^2)混着用就行->综合排序.

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

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

相关文章

修改SqlSugar的WebFirst 代码生成器适配瀚高数据库

WebFirst代码生成器是果糖大数据团队开发的新一代 高性能 代码生成器&数据库设计工具&#xff0c;由.net core 3.1 sqlsugar 开发 &#xff08;此处摘抄自官网 &#x1f601;&#xff09; 官网地址 WebFirst 目前官网发布的版本并没有集成瀚高数据库的支持&#xff0c;本文…

hive on tez资源控制

sql insert overwrite table dwintdata.dw_f_da_enterprise2 select * from dwintdata.dw_f_da_enterprise; hdfs文件大小数量展示 注意这里文件数有17个 共计321M 最后是划分为了21个task 为什么会有21个task&#xff1f;不是128M 64M 或者说我这里小于128 每个文件一个map…

这34道接口测试 Jmeter面试题,你会吗?

接口测试 & Jmeter面试题 一、接口测试 1、接口测试流程 1、首先是从开发那里拿到API接口文档&#xff0c;了解接口业务、包括接口地址、请求方式&#xff0c;入参、出参&#xff0c;token鉴权&#xff0c;返回格式等信息。 2、然后使用Postman或Jmeter工具执行接口测试…

【图像恢复】基于交替乘子方法(ADMM)图像恢复算法研究[固定点收敛和应用](Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

form 表单恢复初始数据

写表单的时候&#xff0c;想做到&#xff0c;某个操作时&#xff0c;表单恢复初始数据 this.$options.data().form form 是表单的对象 <template><div><el-dialog title"提示" :visible.sync"dialogVisible"><el-form :model"…

前端学习记录~2023.7.30~JavaScript重难点实例精讲~第4章 对象

第 4 章 对象 前言4.1 对象的属性和访问方式4.1.1 对象的属性&#xff08;1&#xff09;数据属性&#xff08;2&#xff09;访问器属性 4.1.2 属性的访问方式&#xff08;1&#xff09;使用.访问属性&#xff08;2&#xff09;使用[]访问属性&#xff08;3&#xff09;两者的不…

虫情测报灯的功能优势

KH-CQPest虫情测报灯是一款利用现代光、电、数控集成的虫情测报仪器。它可以通过光学/药物诱虫方式实现自动诱虫&#xff0c;并将诱捕的害虫进行无公害红外远程自动处理&#xff0c;在完成杀虫、虫体分散、拍照、运输等作业后&#xff0c;KH-CQPest虫情测报灯会自动将监测到的虫…

Clone函数

概述 Clone函数是一种用于复制的计算机函数。在程序编写中&#xff0c;除了自定义一个拷贝构造函数来实现对象复制外&#xff0c;还可以实现一个clone函数。这需要借助编译器实现的一个隐藏拷贝构造函数&#xff0c;这样的做法&#xff0c;更省心。 中文名clone函数外文名clon…

ELF program/section segment解析

ELF program/section segment解析 1 elf program segment1.1 elf program header1.2 ELF32和ELF64示例1.2.1 ELF32 program segment1.2.2 ELF64 program segment 1.3 elf program segment数据流向图 2 elf section2.1 eld section header2.2 ELF32和ELF64示例2.2.1 ELF32 secti…

带你玩转双链表

文章目录 前言一、双链表的思路二、带头循环双链表的实现分析二、带头循环双链表的实现11.带头循环双链表实现头文件总览2.带头循环双链表的初始化3.带头循环双链表的插入4.带头循环双链表的打印和销毁5.带头循环双链表的查找和删除 三、带头循环双链表的实现21.带头循环双链表…

软考高级之系统架构师之数据通信与计算机网络

概念 OSPF 在划分区域之后&#xff0c;OSPF网络中的非主干区域中的路由器对于到外部网络的路由&#xff0c;一定要通过ABR(区域边界路由器)来转发&#xff0c;既然如此&#xff0c;对于区域内的路由器来说&#xff0c;就没有必要知道通往外部网络的详细路由&#xff0c;只要由…

文章被限流了?上不了热榜?

文章目录 惨&#xff01;惨&#xff01;&#xff01;惨&#xff01;&#xff01;&#xff01;热榜&#x1f525;热榜&#x1f525;&#x1f525;热榜&#x1f525;&#x1f525;&#x1f525;粉丝破万INSCODE AI 创作 1INSCODE AI 创作 2INSCODE AI 创作 3联系客服 最近不知道C…

Mybatis Plus条件构造器LambdaQueryWrapper

官网地址 Mybatis Plus条件构造器LambdaQueryWrapper 目前数据库数据情况&#xff0c;User表 iduser_namebirthdaysexaddress1张12023-08-10男123163.com2李12023-08-10女222163.com3张22023-08-10女999163.com4张32023-08-10男9994qq.com ## 简单介绍 如何使用各种场景 方法…

Flink源码之TaskManager启动流程

从启动命令flink-daemon.sh可以看出TaskManger入口类为org.apache.flink.runtime.taskexecutor.TaskManagerRunner TaskManagerRunner::main TaskManagerRunner::runTaskManagerProcessSecurely TaskManagerRunner::runTaskManager //构造TaskManagerRunner并调用start()方法 …

【设计模式——学习笔记】23种设计模式——中介者模式Mediator(原理讲解+应用场景介绍+案例介绍+Java代码实现)

文章目录 案例引入案例一普通实现中介者模式 案例二 介绍基础介绍登场角色尚硅谷 《图解设计模式》 案例实现案例一&#xff1a;智能家庭类图实现 案例二&#xff1a;登录页面逻辑实现说明类图实现 总结文章说明 案例引入 案例一 普通实现 在租房过程中&#xff0c;客户可能…

10个创意网站,解决你没有灵感的问题

对于设计师来说&#xff0c;有源源不断的设计灵感&#xff0c;掌握最新的设计流行趋势是非常重要的。要提高设计修养&#xff0c;必须学习和理解优秀的设计作品。在这篇文章中&#xff0c;我们对灵感创意网站进行了分类整理&#xff0c;从中选取了10个素材优良、质量优良的灵感…

为什么过去十年AI创业失败了?

始于2010年前后的这次人工智能创业实际上是集体失败了。作为从业者我们固然可以讲它需要更长的启动周期&#xff0c;我们尽快的开始第二程就可以了&#xff0c;但就像抗日战争的时候如果没有论持久战的穿插到日寇力量薄弱区建立根据地等一系列基于过往教训的新战略&#xff0c;…

浅谈油烟净化技术分类及其优缺点

安科瑞 华楠 摘 要&#xff1a;随着我国经济水平的提高&#xff0c;餐饮业的快速发展&#xff0c;饮食油烟成为继工业排放和汽车尾气之后的第三大空气污染源&#xff0c;随着GB18483-2001的推出&#xff0c;各类油烟处理环保设备不断出现。文章从净化原理、净化效率、使用成本…

unity修改单个3D物体的重力的大小该怎么处理呢?

在Unity中修改单个3D物体的重力大小可以通过以下步骤实现&#xff1a; 创建一个新的C#脚本来控制重力&#xff1a; 首先&#xff0c;创建一个新的C#脚本&#xff08;例如&#xff1a;GravityModifier.cs&#xff09;并将其附加到需要修改重力的3D物体上。在脚本中&#xff0c…

第01天 什么是CSRF ?

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; 每天一个知识点 ✨特色专栏&#xff1…