进阶指针(三)--- qsort函数(快速排序)的使用和(用冒泡排序)模拟实现

news2024/12/1 12:40:56

图片来源于网络

✨博客主页:小钱编程成长记
🎈博客专栏:进阶C语言
🎈推荐相关博文:进阶C语言(一)、进阶C语言(二)

进阶指针(三)

  • 8.回调函数(下)
    • 8.2 qsort函数的使用
      • 8.2.1 介绍:
      • 8.2.1 用qsort函数排序整型数组
      • 8.2.3 用qsort函数排序结构体数组
    • 8.3 用冒泡排序模拟实现qsort函数的快速排序
      • 8.3.1 回顾冒泡排序
      • 8.3.2 开始模拟
      • 8.3.3 代码展示
      • 8.3.4 用新的冒泡排序函数排序整型数组
      • 8.3.5 用新的冒泡排序函数排序结构体数组
  • 总结

8.回调函数(下)

我们接着上次的回调函数开始讲解剩下的qsort部分,如果没看过的话,大家可以先看看进阶C语言(二)

8.2 qsort函数的使用

8.2.1 介绍:

回调函数的案例:qsort

  • qsort是一个库函数,头文件是stdlib.h,声明头文件后可直接使用。
  • qsort是底层使用的快速排序的方式,是对数据进行排序的。
  • qsort可以用来排序任意类型的数据。

我们可以在网站cplusplus中查询这个函数的使用方法。
来自网络截图

qsort函数,有四个参数:
void qsort(void* base,//待排序数组的第一个元素的地址,并将其转化为void*型
			size_t num,//待排序数组的元素的个数
			size_t size,//待排序数组的一个元素的大小(单位字节)
			
			int (*compar)(const void* e1, const void* e2)
			//函数指针---compar指向了一个函数,这个函数是用来比较两个元素的; 
			//e1,e2中存放的是需要比较的两个元素的的地址
			);
compar函数:
//举例: 
比较函数--提供整型数据的比较方法 
int compar(const void* e1, const void* e2)  
{ 		
	return *(int*)e1 - *(int*)e2;//升序排序, 	
//当结果>0(e1指向的元素位于e2之后)时,返回一个>0的数; 	 	 
//当结果==0(e1指向的元素和e2指向的元素相同),返回0;
//当结果<0(e1指向的元素位于e2之前)时,返回一个<0的数; 
}
注意重点:

1.排序整型数组,两个元素可以直接用>比较
2.排序结构体数组,两个结构体的数据可能不能直接使用>比较,
》也就是说,不同类型的数据,比较大小的方式有差异。

  • void* 是无具体类型的指针类型
  • void* 类型的指针可以存放各种类型数据的地址
  • void* 类型的指针不能解引用,也不能进行 ± 整数的操作(因为是无类型,不知道要跳过几个字节)

void* 类型的指针不能解引用,我们可以先强转为其它类型再进行±操作。
qsort并不知道它要排序的数组中元素的类型,并且不同类型数据的比较方式不同。
所以在使用qsort之前,要先给它提供要比较的类型数据的比较方法。

8.2.1 用qsort函数排序整型数组

用qsort函数排序整型数组

#include <stdio.h>
#include <stdlib.h>

//比较函数--提供整型数据的比较方法
int int_compar(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;//升序排序,
	//当结果>0(e1指向的元素位于e2之后)时,返回一个>0的数;
	//当结果==0(e1指向的元素等于e2指向的元素)时,返回0;
	//当结果<0(e1指向的元素位于e2之前)时,返回一个<0的数;
}

//打印函数
void print(int arr[], size_t sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

int main()
{
	int arr[] = { 0,9,8,7,6,5,4,3,2,1 };
	size_t sz = sizeof(arr) / sizeof(arr[0]);
	print(arr, sz);
	//快速排序
	qsort(arr, sz, sizeof(arr[0]), int_compar);
	print(arr, sz);
	return 0;
}

8.2.3 用qsort函数排序结构体数组

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//结构体
struct Stu
{
	char name[20];
	int age;
};



按年龄排序
打印函数
//void print_test1(struct Stu *s1, size_t sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%s %d ", s1[i].name, s1[i].age);
//	}
//	printf("\n");
//}
//
比较函数
//int compare_age(const void* e1, const void* e2)
//{
//	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
//}
//
//void test1()
//{
//	struct Stu s1[] = { {"zhangsan", 20},{"lisi", 12},{"wangwu", 30} };
//	size_t sz = sizeof(s1) / sizeof(s1[0]);
//
//	print_test1(s1, sz);//排序前
//	qsort(s1, sz, sizeof(s1[0]), compare_age);
//	print_test1(s1, sz);
//}



//按名字字母ASCII从小到大排序
//打印函数
void print_test2(struct Stu* s2, size_t sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d ", s2[i].name, s2[i].age);
	}
	printf("\n");
}

//比较函数
int compare_name(const void* e1, const void* e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);
}

void test2()
{
	struct Stu s2[] = { {"zhangsan", 20},{"lisi", 12},{"wangwu", 30} };
	size_t sz = sizeof(s2) / sizeof(s2[0]);

	print_test2(s2, sz);//排序前
	qsort(s2, sz, sizeof(s2[0]), compare_name);
	print_test2(s2, sz);
}

int main()
{
	//test1();
	test2();
	return 0;
}

8.3 用冒泡排序模拟实现qsort函数的快速排序

目标: 包含回调函数,使用冒泡排序的算法,模拟实现一个排序函数(qsort),可以排序任意类型的数据。

8.3.1 回顾冒泡排序

冒泡排序的思想: 两两相邻的元素进行比较

在这里插入图片描述
在这里插入图片描述

//冒泡排序
#include <stdio.h>

//冒泡排序函数
void bubble_sort(int arr[], size_t sz)
{
	int i = 0;
	//冒泡排序的趟数
	for (i = 0; i < sz-1; i++)
	{
		int j = 0;
		//每趟要比较的对数
		for (j = 0; j < sz - 1 - i; j++)
		{
			//判断是否要交换
			if (arr[j] > arr[j + 1])
			{
				//交换
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}		
		}
	}
}

//打印函数
void print_arr(int arr[], size_t sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

void test()
{
	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };//降序
	size_t sz = sizeof(arr) / sizeof(arr[0]);
	print_arr(arr, sz);//排序前
	
	//升序排列
	bubble_sort(arr, sz);
	print_arr(arr, sz);//排序后
}


int main()
{
	test();
	return 0;
}

8.3.2 开始模拟

通过上面对冒泡排序的回顾,我们得到冒泡排序函数的基本框架:

//冒泡排序函数
void bubble_sort(int arr[], size_t sz)
{
	int i = 0;
	//冒泡排序的趟数
	for (i = 0; i < sz-1; i++)
	{
		int j = 0;
		//每趟要比较的对数
		for (j = 0; j < sz - 1 - i; j++)
		{
			//判断是否要交换
			if (arr[j] > arr[j + 1])
			{
				//交换
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}		
		}
	}
}
qsort函数:

在这里插入图片描述

如何模拟:

  1. 首先要给冒泡排序函数传递数组的首元素地址,
    因为我们要模仿qsort排序任意类型的数据,所以形参要能接收任意类型的地址。
    上篇文章讲了void* 类型的指针可以接收任意类型的地址,所以参数我们可以这样写bubble_sort(void *base)

  2. 想要给任意一个数组排序,都要先知道数组有几个元素,
    因为计算数组 / 元素大小的操作数sizeof的返回值是size_t类型的,
    所以参数可以写成bubble_sort(void *base, size_t num)

  3. 有了首元素地址和数组元素个数还不够,还不能知道每个元素的地址。
    站在冒泡排序函数的角度并不知道传来的是什么类型的地址,所以不能通过指针+1的方式找到下一个元素的地址,
    在这里插入图片描述
    但是我们可以将要排序数组每个元素的大小(字节)传过来,知道了一个元素有几个字节,指针跳过这几个字节就指向了下一个元素。 所以参数可以写成bubble_sort(void *base, size_t num, size_t size)

  4. 进阶指针(三)中讲过,不同类型的数据比较大小的方式可能不同, 所以要排序数据的程序员需要先给冒泡排序函数 传 数据的比较函数,冒泡排序函数用函数指针接收,所以参数可以写成 bubble_sort(void *base, size_t num, size_t size, int compar(const void *e1, const void *e2))

  5. 比较函数:
    int compar(const void *e1, const void *e2)
    因为要排序多种类型的数据,所以要用void*类型的指针接收。
    e1是一个指针,存放一个要比较元素的地址
    e2是一个指针,存放一个要比较元素的地址
    e1指向的元素 > e2指向的元素,返回 > 0的整型数字
    e1指向的元素 == e2指向的元素,返回整型数字0
    e1指向的元素 < e2指向的元素,返回 < 0的整型数字
    这也是比较函数返回类型是int的原因。

  6. 在冒泡排序函数中要调用比较函数,来判断两个元素是否需要交换,返回值>0交换。
    比较函数中的参数应该填要比较元素,那就要先找到元素的地址。
    站在冒泡排序函数的角度并不知道传来的是什么类型的地址,所以不能通过指针+1的方式找到下一个元素的地址。
    已知首元素的地址,元素的个数num,一个元素占size字节,我们可以将首元素的地址强转成char*型的,指针向后移size个字节就指向了下一个元素,(一个size个字节大小的元素的地址,在数值上==这个元素所占的第一个字节的地址)
    (char *) base + size * 1 就是下标为1的元素的地址,
    (char *)base + size * j 是下标为 j 的元素的地址,
    (char *)base + size * (j+1) 是下标为 j+1 的元素的地址。
    在这里插入图片描述

//冒泡排序函数
void bubble_sort(const void *base, size_t num, size_t size, int compar(const void *e1, const void *e2))
{
	int i = 0;
	//冒泡排序的趟数
	for (i = 0; i < num-1; i++)
	{
		int j = 0;
		//每趟要比较的对数
		for (j = 0; j < num - 1 - i; j++)
		{
			//判断是否要交换
			if ((compar((char*)base + size*j, (char*)base + size*(j+)) > 0)
			{
				//交换
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}		
		}
	}
}
  1. 如果两个元素需要交换,因为站在冒泡排序函数的角度不知道有排序数组的类型,所以不能直接用 * 解地址将元素整个交换。(*访问的范围是类型的大小)。
    我们知道一个元素有size个字节,所以可以一个字节一个字节的交换,先创建一个字节的空间用来过渡,通过这个空间来交换。
    在这里插入图片描述
//注意:函数不能嵌套定义
//交换函数
void swap(char *buf1, char *buf2)
{
	char tmp = *buf1;
	*buf1 = *buf2;
	*buf2 = tmp;
} 

//判断是否要交换
if ((compar((char*)base + size*j, (char*)base + size*(j+)) > 0)
{
	//交换
	swap((char*)base + size*j, (char*)base + size*(j+1))
}		

8.3.3 代码展示

//交换函数
void swap(char *buf1, char *buf2)
{
	char tmp = *buf1;
	*buf1 = *buf2;
	*buf2 = tmp;
} 

//冒泡排序函数---泛型编程-什么类型都支持的编程
void bubble_sort(const void *base, size_t num, size_t size, int compar(const void *e1, const void *e2))
{
	int i = 0;
	//冒泡排序的趟数
	for (i = 0; i < num-1; i++)
	{
		int j = 0;
		//每趟要比较的对数
		for (j = 0; j < num - 1 - i; j++)
		{
			//判断是否要交换
			if ((compar((char*)base + size*j, (char*)base + size*(j+)) > 0)//此时,compar指向的函数就是回调函数
			{
				//交换
				swap((char*)base + size*j, (char*)base + size*(j+1))
			}		
		}
	}
}

8.3.4 用新的冒泡排序函数排序整型数组

#include <stdio.h>


通用冒泡函数
//交换函数
void swap(char* buf1, char* buf2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

//泛型编程---什么类型都支持的编程
void bubble_sort(const void* base, size_t num, size_t size, int compar(const void* e1, const void* e2))
{
	int i = 0;
	//冒泡排序的趟数
	for (i = 0; i < num - 1; i++)
	{
		//一趟冒泡排序
		int j = 0;
		for (j = 0; j < num - 1 - i; j++)
		{
			//通过比较判断两个元素是否需要交换
			if (compar((char*)base + size * j, (char*)base + size * (j + 1)) > 0)
			{
				//交换
				swap((char*)base + size * j, (char*)base + size * (j + 1), size);
			}
		}
	}
}



//打印函数
void print_test1(int* arr, size_t sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}

//比较函数
int compare_int(const void* e1, const void* e2)
{
	return *(int*)e1 - *(int*)e2;
}

//主要程序
void test1()
{
	int arr[] = { 0,9,8,7,6,5,4,3,2,1 };
	size_t sz = sizeof(arr) / sizeof(arr[0]);

	print_test1(arr, sz);
	bubble_sort(arr, sz, sizeof(arr[0]), compare_int);
	print_test1(arr, sz);
}

int main()
{
	test1();
	return 0;
}

8.3.5 用新的冒泡排序函数排序结构体数组

注意:
  • ->的优先级比 强制转换操作符 高。
  • strcmp用来比较字符串,头文件是string.h
  • 函数在使用之前要先声明,函数的定义也是一种特殊的声明
#include <stdio.h>
#include <string.h>

通用冒泡函数
//交换函数
void swap(char* buf1, char* buf2, size_t size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *buf1;
		*buf1 = *buf2;
		*buf2 = tmp;
		buf1++;
		buf2++;
	}
}

//泛型编程---什么类型都支持的编程
void bubble_sort(const void* base, size_t num, size_t size, int compar(const void* e1, const void* e2))
{
	int i = 0;
	//冒泡排序的趟数
	for (i = 0; i < num-1; i++)
	{
		//一趟冒泡排序
		int j = 0;
		for(j=0; j<num-1-i; j++)
		{
			//通过比较判断两个元素是否需要交换
			if (compar((char*)base + size * j, (char*)base + size * (j + 1)) > 0)
			{
				//交换
				swap((char*)base + size * j, (char*)base + size * (j + 1), size);
			}
		}
	}
}





//结构体
struct Stu
{
	char name[20];
	int age;
};


按年龄比较
比较函数——给排序函数提供要排序的数据的比较方法。函数在使用之前要先声明,函数的定义也是一种特殊的声明
//int compar_age(const void* e1, const void* e2)
//{
//	return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
//}
//
//
//
打印函数
//void print_test1(struct Stu* S1, size_t sz)
//{
//	int i = 0;
//	for (i = 0; i < sz; i++)
//	{
//		printf("%s %d  ", S1[i].name, S1[i].age);
//	}
//	printf("\n");
//}
//
//
主要程序
//void test1()
//{
//	struct Stu S1[] = { {"zhangsan", 20},{"lisi", 12},{"wangwu", 30} };
//	size_t sz = sizeof(S1) / sizeof(S1[0]);
//
//	print_test1(S1, sz);//排序前
//
//	bubble_sort(S1, sz, sizeof(S1[0]), compare_age);//按年龄排序
//	print_test1(S1, sz);//排序后
//}




//按名字的字母大小(ASCII)从小到大排序

//打印函数
void print_test2(struct Stu* S2, size_t sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%s %d ", S2[i].name, S2[i].age);
	}
	printf("\n");
}


//比较函数
int compare_name(const void *e1, const void *e2)
{
	return strcmp(((struct Stu*)e1)->name, ((struct Stu*)e2)->name);//->的优先级比 强制转换操作符 高。strcmp用来比较字符串,头文件是string.h
}


//主要程序
void test2()
{
	struct Stu S2[] = { {"zhangsan", 20},{"lisi", 12},{"wangwu", 30} };
	size_t sz = sizeof(S2) / sizeof(S2[0]);

	print_test2(S2, sz);//排序前
	bubble_sort(S2, sz, sizeof(S2[0]), compare_name);//按名字排序
	print_test2(S2, sz);
}



int main()
{
	//test1();
	test2();
}

总结

本篇文章我们学习了qsort函数,如何用冒泡排序模拟qsort函数实现能够排序任意类型的数据。最后,感谢大家的阅读!大家一起进步!

点赞收藏加关注,C语言学习不迷路!
图片来源于网络

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

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

相关文章

​中秋团圆季《乡村振兴战略下传统村落文化旅游设计》许少辉八月新著

​中秋团圆季《乡村振兴战略下传统村落文化旅游设计》许少辉八月新著 ​中秋团圆季《乡村振兴战略下传统村落文化旅游设计》许少辉八月新著

手动实现BERT

本文重点介绍了如何从零训练一个BERT模型的过程&#xff0c;包括整体上BERT模型架构、数据集如何做预处理、MASK替换策略、训练模型和保存、加载模型和测试等。 一.BERT架构   BERT设计初衷是作为一个通用的backbone&#xff0c;然后在下游接入各种任务&#xff0c;包括翻译…

Azure Arc 概要:功能、管理和应用场景详解,AZ900 考点示例

文章目录 本文大纲一、什么是 Azure Arc二、使用 Azure Arc 可以做什么操作三、使用 Azure Arc 可以管理什么资源3.1 如何使用Azure Arc与服务器? 四、Azure Arc 支持的主要场景五、在 AZ900 中的考点示例5.1 示例题 15.2 示例题 2 本文大纲 本文思维导图概述的主要内容&…

【C/C++】C/C++面试八股

C/C面试八股 C和C语言的区别简单介绍一下三大特性多态的实现原理虚函数的构成原理虚函数的调用原理虚表指针在什么地方进行初始化的&#xff1f;构造函数为什么不能是虚函数虚函数和纯虚函数的区别抽象类类对象的对象模型内存对齐是什么&#xff1f;为什么要内存对齐static关键…

嵌入式Linux应用开发-第十章LED模板总线设备驱动模型

嵌入式Linux应用开发-第十章LED模板总线设备驱动模型 第十章 LED模板驱动程序的改造&#xff1a;总线设备驱动模型10.1 原来的框架10.2 要实现的框架10.3 写代码10.3.1 注意事项10.3.2 实现 platform_device结构体10.3.3 实现 platform_driver结构体 10.4 课后作业 第十章 LED模…

CCF CSP认证 历年题目自练Day13

CCF CSP认证 历年题目自练Day13 题目一 试题编号&#xff1a; 201612-1 试题名称&#xff1a; 中间数 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   在一个整数序列a1, a2, …, an中&#xff0c;如果存在某个数&#xff0c;大…

web:[极客大挑战 2019]BabySQL

题目 点进页面显示如下 查看源代码 先尝试一下万能密码 没用&#xff0c;or被过滤了 试着双写看看 回显一串&#xff0c;也不是flag 先查询列数尝试一下&#xff0c;把union select过滤了&#xff0c;使用双写 构造payload /check.php?usernameadmin&password1 %27 ununi…

基于Java的医院住院管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言系统功能具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序&#xff08;小蔡coding&#xff09;有保障的售后福利 代码参考源码获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域…

ShowDoc部署与应用:文档管理的最佳实践

在项目开发和协作中&#xff0c;文档管理扮演着至关重要的角色。ShowDoc作为一款卓越的开源文档管理工具&#xff0c;不仅提供强大的文档管理功能&#xff0c;还具备简单易用的协作和部署特性。我们的项目团队最初选择了ShowDoc作为文档管理工具&#xff0c;用以促进前后端协作…

【超分:光谱响应函数】

Spectral Response Function-Guided Deep Optimization-Driven Network for Spectral Super-Resolution &#xff08;光谱响应函数引导的深度优化驱动网络光谱超分辨&#xff09; 高光谱图像&#xff08;HSI&#xff09;是许多研究工作的关键。光谱超分辨率&#xff08;SSR&a…

mysql面试题5:索引、主键、唯一索引、联合索引的区别?什么情况下设置了索引但无法使用?并且举例说明

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说索引、主键、唯一索引、联合索引的区别? 索引、主键、唯一索引和联合索引是数据库中常用的索引类型,它们有以下区别: 索引:索引是一种数…

时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解

时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解 目录 时序分解 | Matlab实现SSA-VMD麻雀算法优化变分模态分解时间序列信号分解效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SSA-VMD麻雀搜索算法SSA优化VMD变分模态分解 可直接运行 分解效果好…

JavaScript Web APIs第二天笔记

Web APIs - 第2天 学会通过为DOM注册事件来实现可交互的网页特效。 能够判断函数运行的环境并确字 this 所指代的对象理解事件的作用&#xff0c;知道应用事件的 3 个步骤 学习会为 DOM 注册事件&#xff0c;实现简单可交互的网页特交。 事件 事件是编程语言中的术语&#xff…

笔试强训Day7

T1&#xff1a;合法括号序列判断 链接&#xff1a;合法括号序列判断__牛客网 给定一个字符串A和其长度n&#xff0c;请返回一个bool值代表它是否为一个合法的括号串&#xff08;只能由括号组成&#xff09;。 经典括号匹配问题&#xff0c;考察栈的使用 #include<iostre…

freertos中函数调用和启动第一个任务(栈相关!!!!!!)

本内容仅就一些较难理解的点讲解&#xff0c;请结合其它文章实用 在函数调用时&#xff0c;m3的处理器使用r0-r3共四个寄存器传参&#xff0c;其余的使用栈传参。 但是&#xff0c;如果传入的参数是全局变量&#xff0c;则不需传参&#xff0c;因为全局变量在函数内部是可见的…

YOLO训练心得

文件框架 通过简单的模型训练&#xff0c;对于YOLO的理解更加透彻了。 detect.py文件 如上图所示&#xff0c;weights表示权重。source表示识别图像的位置。 train.py文件 如上图所示&#xff0c;weights是权重&#xff0c;我们通常使用YOLO提供的训练权重进行训练。data是训…

ADworld reverse wp easyre-153

逆向分析 做逆向题先查壳, 就像做pwn先checksec一样 用PEid查不出来, 用Exeinfo PE可以查出ELF文件的壳 用工具直接脱upx壳, kali自带的工具或者手动安装一个windows的upx工具 脱壳之后拖入IDA32 int __cdecl main(int argc, const char **argv, const char **envp) {int …

SLAM从入门到精通(amcl定位使用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 学习slam&#xff0c;一般就是所谓的边定位、边制图的知识。然而在实际生产过程中&#xff0c;比如扫地机器人、agv、巡检机器人、农业机器人&…

Sentinel学习——sentinel的使用,引入依赖和配置 对消费者进行流控 对生产者进行熔断降级

前言 Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 本篇博客介绍sentinel的使用&#x…

Bug:elementUI样式不起作用

前端问题合集&#xff1a;VueElementUI 1. Vue引用Element-UI时&#xff0c;组件无效果解决方案 前提&#xff1a; 已经安装好elementUI依赖 //安装依赖 npm install element-ui //main.js中导入依赖并在全局中使用 import ElementUI from element-ui Vue.use(ElementUI)如果此…