【数据结构】八大排序算法(梭哈)

news2025/3/9 10:32:16

目录

  • 1.直接插入排序
  • 2. * 希尔排序
    • 关于希尔排序的时间复杂度
  • 3.选择排序
  • 4. * 堆排序
  • 5.冒泡排序
  • 6. * 快速排序
    • 6.1递归快排
      • 6.1.1 hoare版
      • 6.1.2 挖坑法
      • 6.1.3 前后指针法
      • 6.1.4 关于每个区间操作的结束位置总是小于key
      • 6.1.5 关于有序原数据的效率优化
    • 6.2 非递归快排
  • 7. * 归并排序
    • 7.1 递归版归并
    • 7.2 非递归版归并
  • 8. 非比较排序
    • 计数排序
  • 排序算法时间复杂度和稳定性

1.直接插入排序

  • 稳定排序,最坏时间复杂度O(N^2),最好O(N)
//直接插入排序
void InsertSort(int* a, int n)
{
	//从下标为1处开始
	for (int i = 1; i < n; i++)
	{
		int tmp = a[i];
		int end = i - 1;
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			//因从头开始进行插入比较,即保证了待插入值之前的元素已经是有序的了
			//故后部的插入比较若已满足排序要求,则直接跳出循环,并将与tmp比较
			//的end位置的后一位置为tmp
			else
			{
				break;
			}
		}
		a[end + 1] = tmp;
	}
}

 
 

2. * 希尔排序

  • 分组插排,先进行预排序,使目标数组接近有序(对间隔为gap的数进行插入排序)
  • 再直接插入排序(gap=1)
  • gap的变化一般为 gap/=2 或 gap=gap/3+1
  • 不稳定排序,时间复杂度O(N*1.3)
void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		//控制gap
		gap /= 2;	
		for (int i = gap; i < n; i++)
		{
			//下标为i处的tmp值与在其之前每间隔gap的元素比较
			//不满足排序顺序则后移
			//且每次都是与之前的元素比较,以此能保证
			//每次tmp值比较的停止位置之前都是有序的
			int tmp = a[i];
			int end = i - gap;
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			//比较满足排序要求则停止,将与tmp比较的end位置的后一位置为tmp
			a[end + gap] = tmp;
		}
	}
}

关于希尔排序的时间复杂度

  • gap变化到1,执行次数为log2N或log3N
  • 每个gap内的执行次数量级都为N,系数可能不同,
  • gap变化至1时,相当于直接插入排序,并且经过预排序,已经为最好情况,量级为N
  • 结论:希尔排序的时间复杂度为 O(N^1.3),(优于O(N*logN))

 

3.选择排序

  • 可单边遍历,也可两边同时遍历
  • 两边遍历时,每次遍历找到的最小值放左边,最大值放右边
  • 注意考虑left于maxi 或 right 与 mini 重叠时要进行修正
  • 不稳定排序,时间复杂度为O(N^2)
//选择排序
void SelectSort(int* a, int n)
{
	单边找小
	//int left = 0;
	//
	//while (left < n)
	//{
	//	int mini = left;
	//	//注意每次遍历起点为left
	//	for (int i = left; i < n; i++)
	//	{
	//		if (a[i] < a[mini])
	//		{
	//			mini = i;
	//		}
	//	}
	//	Swap(&a[left++], &a[mini]);
	//}
	
	//双边同时找
	//每次遍历范围为[left, right]
	int left = 0, right = n - 1;
	while (left < right)
	{
		int mini = left, maxi = right;
		for (int i = left; i <= right; i++)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}
			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}
		Swap(&a[left++], &a[mini]);
		//因为这里先交换了left和mini,可能maxi与left重叠
		//直接交换maxi处的最大值已经通过left被交换到mini了
		//所以考虑此情况需要重置maxi到已交换到的mini处
		if (left == maxi)
		{
			maxi = mini;
		}
		Swap(&a[right], &a[maxi]);
		
	}

}

 

4. * 堆排序

  • 先建堆,再调堆
  • 现在原数组上构建出堆,排升序建小堆,排降序建大堆,
  • 建好堆再将堆顶与尾部数据交换,同时有效位减一,对交换后的堆顶进行向下调整,
  • 若为排升序建小堆,第一次交换并调整后,尾部为最大值,堆顶为次大值,以此循环,完成排序
  • 不稳定排序,时间复杂度为O(N*logN)

void AdjustUp(int* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
			break;
	}
}

void AdjustDown(int* a, int parent, int n)
{
	int child = 2 * parent + 1;

	while (child < n)
	{
		if (child + 1 < n && a[child + 1] > a[child])
		{
			child++;
		}
		if (a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
		}
		else
			break;
		parent = child;
		child = 2 * parent + 1;
	}
}
void HeapSort(int* a, int n)
{
	向上调整建堆
	//for (int i = 1; i < n; i++)
	//{
	//	AdjustUp(a, i);
	//}


	//向下调整建堆
	for (int i = n - 1; i >= 0; i--)
	{
		AdjustDown(a, (i - 1) / 2, n);
	}
	int end = n;
	//首尾交换向下调整排序
	for (int i = n - 1; i >= 0; i--)
	{
		Swap(&a[i], &a[0]);
		end--;
		AdjustDown(a, 0, end);
	}
}

 

5.冒泡排序

  • 稳定排序,时间复杂度为O(N^2)

在这里插入图片描述

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

 
 

6. * 快速排序

6.1递归快排

6.1.1 hoare版

  • 将头位置的元素作为基准值
  • 小于基准值的放左边,大于基准值的放右边
  • 最后将基准值放至比较结束位置
  • 根据基准值最后位置将数组分割成两个区间(剔除基准值)
  • 对分割后的区间进行分治
  • 不稳定排序,时间复杂度为 O(N*logN)
  • 类似二叉树的前序,递归深度为 logN
    在这里插入图片描述
//hoare版
int PartSort1(int* a, int left, int right)
{

	//keyi位置的值会影响快排效率
	//如果a[keyi]本身最大或最小,
	//为最坏情况,时间复杂度O(N2)
	//为保证较高效率,决定keyi时
	//尽量保证其为一个适中对值,将其放到left位置处


	//优化1.生成一个随机位置keyi
	/*if (left < right)
	{
		int randi = left + (rand() % (right - left));
		Swap(&a[left], &a[randi]);
	}*/
	
	//优化2.三数取中
	int mid = GetMidPos(a, left, right);
	Swap(&a[left], &a[mid]);
	//优化方案使用一组有序的用例进行测试
	//有序用例的数据个数如果较大,会栈溢出
	//可在release版本下测试较多的数据

	int keyi = left;
	
	
	while (left < right)
	{
		//left和right每次移动都要判断left<right
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
		while (left < right && a[left] <= a[keyi])
		{
			left++;
		}
		
		//交换同时不同各自向中移动,下次循环自会移动
		Swap(&a[left], &a[right]);
	}
	Swap(&a[keyi], &a[left]);
	return left;
}

 

6.1.2 挖坑法

  • 记录首个数据key
  • 右边先走找到小将其填入坑,同时其所处位置成为坑
  • 左边后走找到大将其填入坑,同时其所处位置成为坑
  • 左后L与R相遇在坑上,最后向此坑中填入key
  • 返回最后的相遇位置作为分割区间点
    在这里插入图片描述
//挖坑法
int PartSort2(int* a, int left, int right)
{
	//三数取中
	int mid = GetMidPos(a, left, right);
	Swap(&a[left], &a[mid]);
	//优化方案使用一组有序的用例进行测试
	//有序用例的数据个数如果较大,会栈溢出
	//可在release版本下测试较多的数据

	int key = a[left];
	int pit = left;
	while (left < right)
	{
		while (left < right && a[right] >= key)
		{
			right--;
		}
		a[pit] = a[right];
		pit = right;
		while (left < right && a[left] <= key)
		{
			left++;
		}
		a[pit] = a[left];
		pit = left;
	}
	a[pit] = key;
	return pit;
}

 

6.1.3 前后指针法

  • cur向右找小,找到 prev++,cur与prev 交换值
  • cur 没找到,cur++
  • cur 加至越界,跳出循环,key值与此时的prev交换
  • 返回最后的prev 作为分割区间点
//前后指针法
int PartSort3(int* a, int left, int right)
{
	//三数取中
	int mid = GetMidPos(a, left, right);
	Swap(&a[left], &a[mid]);
	//优化方案使用一组有序的用例进行测试
	//有序用例的数据个数如果较大,会栈溢出
	//可在release版本下测试较多的数据

	int keyi = left;
	int prev = left, cur = left;
	while (cur <= right)
	{
		if (a[cur] >= a[keyi])
		{
			cur++;
		}
		else
		{
			Swap(&a[++prev], &a[cur++]);
		}
	}
	Swap(&a[keyi], &a[prev]);
	return prev;
}

6.1.4 关于每个区间操作的结束位置总是小于key

  • 因为是右边先走,所以能保证相遇位置能小于左边的 key,即右边向左找小的停止位置一定比key小
  • 有几种R停止的情况
    • R 找到小,L 没找到大,直接遇到 R
    • R 没找到小,直接遇到 L,相遇点小于 key,或者直接走到key

6.1.5 关于有序原数据的效率优化

  • 如果原数据本身是有序的,快速排序的时间复杂度会达到 O(N^2)
  • 优化方案使用一组有序的用例进行测试
  • 有序用例的数据个数如果较大,会栈溢出
  • 可在release版本下测试较多的数据,(debug模式下数据个数为10000都会栈溢出)

Release模式下测试数据个数为100000的有序数组
在这里插入图片描述
 

两种优化方式

//优化1.生成一个随机位置keyi
	if (left < right)
	{
		int randi = left + (rand() % (right - left));
		Swap(&a[left], &a[randi]);
	}
	
优化2.三数取中
	int mid = GetMidPos(a, left, right);
	Swap(&a[left], &a[mid]);
	//优化方案使用一组有序的用例进行测试
	//有序用例的数据个数如果较大,会栈溢出
	//可在release版本下测试较多的数据

同样条件下优化后测试
在这里插入图片描述

  • 三数取中取到的key一定是一个较为适中的值
  • 而随机选key有可能仍然是最值
  • 相对来说,三数取中法优化更彻底

 

6.2 非递归快排

  • 非递归的优化目的主要是因为递归快排如果处理较多数据,递归的层次太深,很容易导致栈溢出
  • 将递归改为循环,并且运用栈实现快排的非递归版

非递归快排用过栈实现
在这里插入图片描述

//快速排序非递归
void QuickSortNor(int* a, int left, int right)
{
	//创建栈
	ST st;
	StackInit(&st);
	st.a = (int*)malloc(sizeof(int) * (right - left + 1));
	if (st.a == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	//首先将数组头尾压入栈
	StackPush(&st, right);
	StackPush(&st, left);
	
	while (!StackEmpty(&st))
	{
		//依次取栈顶作为一次排序的区间
		int begin = StackTop(&st);
		StackPop(&st);
		int end = StackTop(&st);
		StackPop(&st);
		int keyi = PartSort3(a, begin, end);

		//将[begin,keyi-1] [keyi+1,end]区间的边界(若存在)入栈
		//先入右边界,后入左边界,以确保拿到栈顶先处理左边界
		if (keyi + 1 < end)
		{
			StackPush(&st, end);
			StackPush(&st, keyi + 1);
		}
		if (keyi - 1 > begin)
		{
			StackPush(&st, keyi - 1);
			StackPush(&st, begin);
		}
	}
}

 
 

7. * 归并排序

  • 先分割,在由下至上逐层归并
  • 每次归并结果放入一个临时数组
  • 最后将临时数组的数据拷贝到原数组

7.1 递归版归并

在这里插入图片描述

void _MergeSort(int* a, int left, int right, int* tmp)
{
	if (left >= right)
	{
		return;
	}
	int mid = (left + right) / 2;

	//分治[left, mid] [mid+1, right]
	_MergeSort(a, left, mid, tmp);
	_MergeSort(a, mid + 1, right, tmp);
	
	int i = left;
	int j = mid+1;
	int k = 0;

	//某一半区间全部放入了tmp,跳出循环
	while (i <= mid && j <= right)
	{
		if (a[i] < a[j])
		{
			tmp[k++] = a[i++];
		}
		else
		{
			tmp[k++] = a[j++];
		}
	}
	//某一半区间全部放入了tmp,将另一半剩余元素全部移入tmp
	while (j <= right)
	{
		tmp[k++] = a[j++];
	}
	while (i <= mid)
	{
		tmp[k++] = a[i++];
	}

	//将tmp中归并后的有序数组按原位置拷贝到原数组
	memcpy(a + left, tmp, sizeof(int) * (right - left + 1));

}

void MergeSort(int* a, int n)
{
	//开辟一块临时空间暂存归并后的有序数组
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	int left = 0;
	int right = n - 1;
	_MergeSort( a, left, right, tmp);
}

 

7.2 非递归版归并

  • 非递归的归并排序主要是要处理越界问题
  • 如果产生越界,根据情况将某一边界进行重置
    在这里插入图片描述
  • 两种实现方法,基本思想一致,只是拷贝的时机不一样,第二种方法可简化到两种情况
  • 一种是梭哈版:一个gap循环内的多组数归并完拷贝一次,
  • 一种非梭哈版:一个gap循环内的一组数归并完随即拷贝
void MergeSortNoR(int* a, int n)
{
	//梭哈版--一个gap循环内的多组数归并完拷贝一次
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	int gap = 1;

	while (gap < n)
	{
		int j = 0;

		for (int i = 0; i < n; i += 2 * gap)
		{
			//控制归并的两部分
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;

			//处理几种越界问题,根据发生前后(调试发现)
			if (begin2 >= n)
			{
				end2 = n - 1;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			if (end1 >= n)
			{
				end1 = n - 1;
			}
			//[begin1, end1] [begin2, end2]
			while (begin1 <= end1 && begin2 <= end2)
			{
				//这行代码决定排序是否稳定, <= 则稳定
				//若相等,前面的数先放,可确保相等数据相对位置不变)
				if (a[begin1] < a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}

			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
		}
		memcpy(a, tmp, sizeof(int) * n);
		gap *= 2;
	}



	//非梭哈版,一个gap循环内的一组数归并完随即拷贝
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}

	int gap = 1;

	while (gap < n)
	{
		int j = 0;

		for (int i = 0; i < n; i += 2 * gap)
		{
			//控制归并的两部分
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
			printf("[%d, %d][%d, %d] ", begin1, end1, begin2, end2);

			//处理几种越界问题,根据发生前后(调试发现)
			if (end1 >= n || begin2 >= n)
			{
				break;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			/*if (begin2 >= n)
			{
				end2 = n - 1;
			}
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			if (end1 >= n)
			{
				end1 = n - 1;
			}*/
			//[begin1, end1] [begin2, end2]
			while (begin1 <= end1 && begin2 <= end2)
			{
				//这行代码决定排序是否稳定, <= 则稳定
				//若相等,前面的数先放,可确保相等数据相对位置不变)
				if (a[begin1] < a[begin2])
				{
					tmp[j++] = a[begin1++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}

			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
			//拷贝
			memcpy(a + i, tmp + i, sizeof(int)* (end2 - i + 1));
			
		}
		printf("\n");
		gap *= 2;
	}
}

  

8. 非比较排序

计数排序

  • 统计每个数据出现的次数
  • 将次数相对映射至计数数组,(根据原数据范围实现相对映射)
  • 根据计数数组重写原数组
  • 适用于范围不大且数据集中的整型排序
  • 时间复杂度为 O(N+range),range 为原数据的分布范围
void CountSort(int* a, int n)
{
	//相对映射
	int min = a[0], max = a[0];
	for (int i = 0; i < n; i++)
	{
		if (a[i] < min)
		{
			min = a[i];
		}
		if (a[i] > max)
		{
			max = a[i];
		}
	}
	int range = max - min + 1;
	int* count = (int*)calloc(range, sizeof(int));
	if (count == NULL)
	{
		printf("calloc fail\n");
		exit(-1);
	}
	//计数
	for (int i = 0; i < n; i++)
	{
		count[a[i] - min]++;
	}
	//重写
	int i = 0;
	for (int j = 0; j < range; j++)
	{
		while (count[j]--)
		{
			a[i++] = j + min;
		}
	}
	
	free(count);
	count = NULL;
}

 

排序算法时间复杂度和稳定性

稳定性:排序后相等元素的相对位置是否改变
在这里插入图片描述

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

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

相关文章

计算机网络考试复习——第五章

本章考察范围为5.1 5.3 5.4这三部分。 该层传输的单位是报文段 5.1 运输层协议概述&#xff1a; 5.1.1 进程之间的通信&#xff1a; 运输层是向它上面的应用层提供通信服务。它属于面向通信部分的最高层&#xff0c;同时也是用户功能的最低层。 屏蔽作用&#xff1a;运输层…

flutter系列之:如何自定义动画路由

文章目录 简介自定义跳转使用flutter动画基础实现一个自定义的route总结 简介 flutter中有默认的Route组件&#xff0c;叫做MaterialPageRoute&#xff0c;一般情况下我们在flutter中进行跳转的话&#xff0c;只需要向Navigator中传入一个MaterialPageRoute就可以了。 但是Ma…

让你的three.js动起来

让你的three.js动起来 简介 本节主要是给实例添加动画效果&#xff0c;以及加了一些小插件用以实现帧率检测、gui可视化配置、动态监听屏幕大小变化刷新和鼠标操控功能。 引入的插件js&#xff1a; three.jsdat.gui.jsStats.jsTrackballControls.js 实际效果&#xff1a; …

Java 线程状态有哪些?

文章目录 Java 线程状态有哪些&#xff1f;初始状态&#xff08;NEW&#xff09;可运行状态&#xff08;RUNNABLE&#xff09;就绪状态运行状态 阻塞状态&#xff08;BLOCKED&#xff09;等待状态&#xff08;WAITING&#xff09;超时等待&#xff08;TIMED_WAITING&#xff09…

一次打靶场记录

题目提示 1、目录爆破 在对靶场进行信息收集、目录扫描之后发现结果存在www.zip,data.zp 两个备份文件 下载回来解压之后发现www.zip是网站备份文件&#xff0c;data.zip是数据库文件&#xff0c;存在一个maccms的数据库 苹果cms的数据库&#xff0c;导入本地数据库。 admin…

【并发编程Python】为什么Python这么慢

Python速度慢的所有原因 Python作为一门非常优秀的计算机语言&#xff0c;其速度慢给Python减了很多分&#xff0c;也是其一直被诟病的主要原因之一&#xff0c;通常情况下&#xff0c;Python比Java/C慢约5-10倍&#xff0c;在一些特殊的情况下Python甚至比C慢100~200倍&#x…

数据结构——B树和B+树

数据结构——B树和B树 一、B树1.B树的特征2.B树的插入操作3.B树的删除操作4.B树的缺点 二、B树B树的特征 平衡二叉树或红黑树的查找效率最高&#xff0c;时间复杂度是O(nlogn)。但不适合用来做数据库的索引树。 因为磁盘和内存读写速度有明显的差距&#xff0c;磁盘中存储的数…

玩转肺癌目标检测数据集Lung-PET-CT-Dx ——③整理、验证数据,建立Dataset对象

文章目录 数据整理整理出所有的dcm文件整理出所有的xml标注文件整理数据①——舍弃错误的标注文件整理数据②——两个标注文件指向同一个目标图片的情况封装函数&#xff0c;传入xml文件&#xff0c;显示标注效果 整理数据③——将PETCT的三通道图像转成平扫CT的单通道图像格式…

企业费控,驶向「一体化」

在数字化于企业内部各个环节实现平权、成为标配的当下&#xff0c;财务&#xff0c;这个被称为“控制企业生命力”的核心环节&#xff0c;是否应该拥有新的价值&#xff1f; 作者| 皮爷 出品|产业家 2022年年中&#xff0c;施伟和分贝通的团队接到一项“特殊需求”。 这个…

在职读研专业——劳动经济学

研究方向&#xff1a;劳动经济学主要研究劳动力市场现象及其所引起的劳动力资源配置等相关问题&#xff0c;包括劳动力供给、劳动力需求、就业、工资、人力资本投资、收入分配等。例如&#xff1a;劳动力市场失衡背后各种因素的变化&#xff0c;如何通过资源的配置使劳动资源配…

MySQL innobackupex 备份工具使用总结

前言 在MySQL备份以及搭建从库的过程中&#xff0c;我们针对比较小的库大多采用的是mysqldump&#xff0c;简单&#xff0c;方便。但是在大库进行搭建从库的时候&#xff0c;且数据库主机没有一个很好的存储来满足备份&#xff0c;这个时候就需要使用innobackupex来协助你来做一…

Pocsuite3框架POC/EXP编写练习:Flask(Jinja2) 服务端模板注入漏洞

Pocsuite3 是由知道创宇 404 实验室打造的一款基于 GPLv2 许可证开源的远程漏洞测试框架。可以用来编写POC/EXP&#xff0c;今天借助Flask框架下的SSTI漏洞练习记录一下Pocsuite3框架的配置和编写过程。 官方文档&#xff1a;Pocsuite3 是什么&#xff1f; | Pocsuite3 安装 …

小黑继续跟着沛奇老师学携程:携程基础3

3.异步编程 3.1事件循环 理解成一个死循环&#xff0c;去检测并执行某些代码 # 伪代码任务列表 [任务1&#xff0c;任务2&#xff0c;任务3&#xff0c;...] while True:可执行的任务列表&#xff0c;已完成的任务列表 去任务列表中检查所有任务&#xff0c;将可执行和已完…

安装、启动和登陆doccano

一、安装 1、使用的Pycharm安装的doccano 2、初始化数据库 doccano init 3、创建用户名和密码 # admin是用户名&#xff0c;pass是密码&#xff0c;都可以自定义 doccano createuser --username admin --password pass 二、启动 1、在一个Terminal终端启动webserver服务 …

自适应控制专栏目录及介绍

目录 自适应控制专栏目录及介绍第一篇&#xff1a;[具有不确定参数系统的自适应跟踪控制设计_ADi_hhh的博客-CSDN博客](https://blog.csdn.net/qq_45830323/article/details/129713051)第二篇&#xff1a;[&#xff08;SISO&#xff09;单输入单输出系统的模型参考自适应控制_A…

cdh Hue集成sentry的权限管理详细步骤

hue登录hue的第一个用户要用hue用户创建,默认hue为超级用户,hue用户页面的权限可以管理很多用户操作,比如查看hdfs目录,使用其他组件,授权功能等等 一.hive的配置 1.关闭模拟,开启sentry 2.添加配置(注意配置的位置) <property> <name>sentry.hive.tes…

【C++11】lambda表达式

目录 lambda表达式 1.1 lambda表达式出现的原因 1.2 lambda表达式语法 1.3 函数对象与lambda表达式 lambda表达式 1.1 lambda表达式出现的原因 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用 std::sort 方法 测试代码 #include <…

苹果撤离中国市场?中国市场太重要,印度制造是备胎

苹果在中国之行后&#xff0c;却计划进一步扩大印度制造iPhone的比例&#xff0c;甚至将iPhone15全数交给印度制造&#xff0c;业界因此认为苹果正在离开中国市场&#xff0c;然而这完全是臆想&#xff0c;中国市场对苹果来说仍然非常重要&#xff0c;它不会轻易舍弃这个市场。…

【Unity VR开发】结合VRTK4.0:添加碰撞忽略器

语录&#xff1a; 最远的旅行&#xff0c;是从自己的身体到自己的心&#xff0c;是从一个人的心到另一个人的心。坚强不是面对悲伤不流一滴泪&#xff0c;而是擦干眼泪后微笑面对以后的生活。 前言&#xff1a; 模块化提供了一种允许两个或者多个对象忽略彼此碰撞的方法&#x…

Logstash:多管道配置

我们大多数人已经熟悉 Elastic 产品。 在此博客中&#xff0c;我们将逐步介绍配置 Logstash 以使用多个管道摄取和处理数据的步骤。 Logstash 是一种开源数据处理管道&#xff0c;可让你摄取、转换和输出数据。 它是从各种来源收集和处理大量数据的强大工具&#xff0c;可用于管…