【C语言数据结构——————排序(1万字)】

news2024/12/25 12:26:59

文章目录

  • 排序的概念
    •  常见排序算法
    • 分类
  • 冒泡排序
    • 时间复杂度
    • 稳定性
    •  原理
    • 实现
  • 插入排序
    • 时间复杂度
    • 稳定性
    • 实现
  • 选择排序
    •  时间复杂度
    • 稳定性
    • 实现
  • 希尔排序
    •  时间复杂度
    • 稳定性
    • 希尔排序的算法思想
    • 实现
      •  优化
  • 快速排序
    •  时间复杂度
    • 空间复杂度
    • 稳定性
    • 实现
      •  三数取中优化
  • 归并排序
    •  时间复杂度
    • 空间复杂度
    • 稳定性
    • 实现
      •  递归实现归并排序
  • 堆排序
    •  时间复杂度
    • 实现
      •  大顶堆和小顶堆的介绍
      • 向上调整算法
      • 向下调整算法
  • 计数排序
    •  时间复杂度
    • 空间复杂度
    • 稳定性
    • 实现
  • 总结

欢迎阅读新一期的c语言数据结构模块————排序

✒️个人主页:-_Joker_-

🏷️专栏:C语言数据结构

📜代码仓库:c_code

🌹🌹欢迎大佬们的阅读和三连关注,顺着评论回访🌹🌹


排序的概念

排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程叫做排序。

常见排序算法

快速排序、希尔排序、堆排序、直接选择排序、基数排序、计数排序、冒泡排序、插入排序、归并排序等。

分类

◆稳定排序:假设在待排序的文件中,存在两个或两个以上的记录具有相同的关键字,在

用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序方法

是稳定的。其中冒泡排序,插入排序,基数排序,归并排序、基数排序都属于稳定排序。

◆就地排序:若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间为O(1)

◆不稳定排序:假设在待排序的文件中,存在两个或两个以上的记录具有相同的关键字,在

用某种排序法排序后,若这些相同关键字的元素的相对次序仍然不变,则这种排序方法

是不稳定的,其中选择排序,快速排序,希尔排序,堆排序都属于不稳定排序。


冒泡排序

冒泡排序是我们学习编程接触的第一个排序方式,它的优点是比较稳定,而且比较容易掌握。作为我们第一个接触到排序,它的缺点也非常明显,它的时间复杂度是O(n²),这就导致冒泡排序会非常慢,并不适用于排序,只适合用于教学,是一个具有教学意义的启蒙排序方式。

时间复杂度

冒泡排序的时间复杂度为O(n²)

稳定性

由于冒泡排序并没有改变元素的相对次序,所以冒泡排序是一个稳定的排序

原理
  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 

  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。 
  3. 针对所有的元素重复以上的步骤,除了最后一个。 
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较
冒泡排序的实现:

冒泡排序的算法思路主要就是两层嵌套的循环语句。外层循环控制第1到第 n-1 趟排序,而内层循环则控制每一趟排序中对前面未排好序的元素进行比较和交换。

#include<stdio.h>

int main()
{
    int a[6]={20,40,10,5,50,30};
    int i = 0;
    for(j=0;j<5;j++)//外部总共要遍历n-1次(n为元素个数)
    {
        for(i=0;i<5-j;i++)//每一次将最大值放在最后,前面的数比较次数-1,只需要和最大值前面的元素比较
        {
            if(a[i]>a[i+1])//比较相邻两者大小关系,如果前面元素大则需要改变位置
            {
                trmp = a[i];//通过中间量交换两者位置
                a[i]=a[i+1];
                a[i+1]=temp;
            }
        }
    }
 
    return 0;
}

插入排序

插入排序是指在待排序的元素中,假设前面n-1(其中n>=2)个数已经是排好顺序的,现将第n个数插到前面已经排好的序列中,然后找到合适自己的位置,使得插入第n个数的这个序列也是排好顺序的。按照此法对所有元素进行插入,直到整个序列排为有序的过程,称为插入排序 。

时间复杂度

在插入排序中,当待排序数组是有序时,是最优的情况,只需当前数跟前一个数比较一下就可以了,这时一共需要比较N- 1次,时间复杂度为O(N)。

最坏的情况是待排序数组是逆序的,此时需要比较次数最多,总次数记为:1+2+3+…+N-1,所以,插入排序最坏情况下的时间复杂度为O(N²)。

稳定性

如果待排序的序列中存在两个或两个以上具有相同关键词的数据,排序后这些数据的相对次序保持不变,即它们的位置保持不变,通俗地讲,就是两个相同的数的相对顺序不会发生改变,则该算法是稳定的;如果排序后,数据的相对次序发生了变化,则该算法是不稳定的。关键词相同的数据元素将保持原有位置不变,所以该算法是稳定的 。

实现
void InsertSort(int* a, int n)
{

	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if ( tmp < a[end])//和前一个值比较大小
			{
				a[end + 1] = a[end];//把位置往后挪插入tmp

			}
			else
			{
				break;
			}
			--end;
		}
		a[end + 1] = tmp;
	}
		
}

选择排序

选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。 

时间复杂度

选择排序的交换操作介于 0 和 (n - 1)次之间。选择排序的比较操作为 n (n - 1) / 2 次之间。选择排序的赋值操作介于 0 和 3 (n - 1) 次之间。比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+...+1=n*(n-1)/2。交换次数O(n),最好情况是,已经有序,交换0次;最坏情况交换n-1次,逆序交换n/2次。交换次数比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。 

稳定性

选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后稳定性就被破坏了。所以选择排序是一个不稳定的排序算法。

实现
void SelectSort(int* a, int n)
{
	int begin = 0, end = n - 1;
	while (begin < end)
	{
		int min = begin, max = begin;//定义max和min用于寻找最大值和最小值
		for (int i = begin + 1; i <= end; i++)
		{
			if (a[i] > a[max])//比较最大值
			{
				max = i;
			}
			if (a[i] < a[min])//比较最小值
			{
				min = i;
			}
		}
		Swap(&a[begin], &a[max]);//交换
		if (max == begin)//如果首元素就是最大值,将最小值赋给最大值然后交换
		{
			max = min;
		}
		Swap(&a[begin], &a[min]);
		begin++;
		end--;
	}
}

希尔排序

希尔排序(Shell's Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。

希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。

时间复杂度

希尔排序的时间复杂度在最好和最坏情况下都是O(nlog²n),平均时间复杂度是O(nlogn),但是实际上希尔排序的时间复杂度是O(n^1.5),所以对于中小规模的排序希尔排序都是非常好用的,但是对于大型数据要稍微吃力。

稳定性

由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以希尔排序是不稳定的。

希尔排序的算法思想

先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行插入排序;然后,取第二个增量d2 = …

该方法实质上是一种分组插入方法。

比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行分组,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。

一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

实现
void ShelltSort(int* a, int n)
{
	int gap = 3;//给定跳过的步数
	for (int i = 0; i < gap; i++)
	{
		for (int j = 0; j < n - gap; j += gap)
		{
			int end = j;
			int tmp = a[end + gap];//按步数进行插入排序
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
	
}

此方法还可以进一步优化

优化
void ShelltSort(int* a, int n)
{

	int gap = n;
	while (gap > 1)
	{
		gap = gap / 2;
		//gap > 1时是预排序
		//gap == 1时就是插入排序
		for (int j = 0; j < n - gap; ++j)
		{
			int end = j;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

快速排序

人如其名,快速排序简称快排,快速排序采用的是分治思想,即在一个无序的序列中选取一个任意的基准元素pivot,利用pivot将待排序的序列分成两部分,前面部分元素均小于或等于基准元素,后面部分均大于或等于基准元素,然后采用递归的方法分别对前后两部分重复上述操作,直到将无序序列排列成有序序列。 

快速排序算法通过多次比较和交换来实现排序,其排序流程如下: 

  • 首先设定一个分界值,通过该分界值将数组分成左右两部分。
  • 将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于分界值,而右边部分中各元素都大于或等于分界值。
  • 然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
  • 重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。
时间复杂度

快排在理想的条件下的排序速度是非常快的,可以达到O(n log n)。但是在最坏情况下,快排的时间复杂度为O(n²),平均时间复杂度为O(n log n)。

空间复杂度

由于快排需要使用递归进行实现,递归需要消耗栈空间,所以空间复杂度为O(log n)

稳定性

由于快排在进行交换的过程中,会将元素的相对位置给打乱,所以快排属于不稳定排序

实现
void QuickSort(int* a, int begin, int end) {
    int i = begin; 
    int j = end;
    if(i >= j) {
        return;
    }
 
    int tmp = a[begin];
    while(i != j) {
        while(a[j] >= tmp && i < j) {
            j--;
        }
	while(a[i] <= tmp && i < j) {
            i++;
        }
	if(i < j) {
            swap(a[i], a[j]);
        }
    }

    swap(a[begin], array[high]);
    //递归
    QuickSort(a, begin, i - 1);
    QuickSort(a, i + 1, end);
}

三数取中优化

快排同样也可以进行优化,我们可以添加一个三数取中来提高快排的效率。

int GetMiddle(int* a, int left, int right)
{
	int mid = (left + right) / 2;
	if (a[left] < a[mid])
	{
		if (a[mid] < a[right])
			return mid;
		else if (a[left] > a[right])
			return left;
		else
			return right;
	}
	else
	{
		if (a[mid] > a[right])
			return mid;
		else if (a[left] < a[left])
			return left;
		else
			return right;
	}
}

通过三个值寻找中间值的方法,可以极大程度减少快排的时间复杂度,可以使某些极端情况下的快排由O(n²)优化成O(nlongn),这对于快排无疑是非常重要的优化。

下面是优化后的代码

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

//部分排序
int partsort1(int* a, int left, int right)
{
	int mid = GetMiddle(a, left, right);
	Swap(&a[left], &a[mid]);

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

//递归实现快排
void QuickSort(int* a, int begin, int end)
{
	if (begin >= end)
		return;
	int key = partsort3(a, begin, end);
	QuickSort(a, begin, key - 1);
	QuickSort(a, key + 1, end);
}

归并排序

归并排序是建立在归并操作上的一种有效、稳定的排序算法,简称归排,该算法采用非常经典的分治法(分治法可以通俗的解释为:把一片领土分解,分解为若干块小部分,然后一块块地占领征服,被分解的可以是不同的政治派别或是其他什么,然后让他们彼此异化),归并排序的思路很简单,速度呢,也仅此于快速排序,归并排序由于它出色的稳定性和稳定的时间复杂度,使得它的效率比快排要更高。

时间复杂度

归并排序的时间复杂度为O(n log n),是速度仅次于快排的排序

空间复杂度

由于归并排序需要使用到一个临时空间用于存放合并后的结果,所以它的空间复杂度为O(n)

稳定性

由于归并排序的算法是通过将序列中待排序数字分为若干组,每个数字分为一组,然后将若干组两两合并,保证合并的组都是有序的,之后再重复第二步的操作,直到剩下最后一组即为有序数列,所以这就保证了相对顺序不会改变,所以是稳定的。

实现
void MergeSortNonR(int* a, int n)
{
	int gap = 1;
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	while (gap < n)
	{
		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;
			//[begin1,end1] [begin2,end2]两组归并
			int index = i;
			if (begin2 >= n)
			{
				break;
			}
			//修正越界情况
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			while (begin1 <= end1 && begin2 <= end2)
			{
				if (a[begin1] <= a[begin2])
				{
					tmp[index++] = a[begin1++];
				}
				else
				{
					tmp[index++] = a[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[index++] = a[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[index++] = a[begin2++];
			}
			//归并一组后,将数据拷贝回原数组
			memcpy(a + i, tmp + i, (end2 - i + 1) * sizeof(int));
		}
		gap *= 2;
	}
}

归并排序同样也可以通过递归来实现,下面是通过递归方法所实现的归并排序


递归实现归并排序
void _MergeSort(int* a, int* tmp, int begin, int end)
{
	if (end >= begin)
	{
		return;
	}
	int mid = (end + begin) / 2;
	_MergeSort(a, tmp, begin, mid);
	_MergeSort(a, tmp, mid + 1, end);
	//归并到tmp数组中,再拷贝回去
	//a->[begin, mid-1] [mid, end]->tmp
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int index = begin;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[index++] = a[begin1++];
		}
		else
		{
			tmp[index++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[index++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[index++] = a[begin2++];
	}
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin));
}

void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	_MergeSort(a, tmp, 0, n - 1);
	free(tmp);
}

堆排序

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它也是不稳定排序。
堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆, 注意 : 没有要求结点的左孩子的值和右孩子的值的大小关系。
每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆

时间复杂度

堆排序的最坏,最好还有平均时间复杂度均为O(nlogn)

实现

堆排序的基本思想是:

  1. 将待排序序列构造成一个大顶堆
  2. 此时,整个序列的最大值就是堆顶的根节点。
  3. 将其与末尾元素进行交换,此时末尾就为最大值。
  4. 然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
大顶堆和小顶堆的介绍:
  • 大顶堆:每个节点的值都大于或者等于它的左右子节点的值: arr[i] >= arr[2i + 1] && arr[i] >= arr[2i + 2]

  • 小顶堆:每个节点的值都小于或者等于它的左右子节点的值: arr[i] <= arr[2i + 1] && arr[i] <= arr[2i + 2]

我们在实现归排的时候,如果需要排成升序,我们需要建大堆,若是要排成降序则需要建小堆

简称升序建大堆,降序建小堆

实现
//向上调整
void AdjustUp(HPDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child > 0)
	{
		if (a[child] < a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

//向下调整
void AdjustDown(HPDataType* a, int n, int parent)
{
	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)
{
	//建堆(升序建大堆)
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end ,0);
		--end;
	}
}

这里再介绍一下向上调整和向下调整

向上调整算法

所谓向上调整,字面意思就是把数不断的和上面的数做调整。

如果已经存在堆,再插入一个结点,从插入的结点开始,向上依次调整。

调整:如果插入的结点不需要调整,即插入该结点,依旧是堆。

如果插入的结点不满足堆结构,就要对该结点的父亲结点调整,调整完因为改变了父亲结点,就要迭代调整新的孩子结点。

类似下图

那我们在看图片下面的情况可以看到我们在我们在堆的末尾空白位置插入了一个数9,那么此时为了保证堆维持一个大根堆,我们必须要把我们这个新插入的数和它的父亲节点作比较,如果这个新插入的数大于父亲,那么就和父亲交换位置。
那么我们怎么找到它的父亲节点呢?用孩子节点下标求父亲节点下标:Parent = (Child - 1) / 2;
此时9是大于8的,所以我们交换两数的位置,交换完毕后继续用9和他的父亲进行比较,10>9所以不需要调整了

向下调整算法

同样的,向下调整算法字面意思就是把数据和它的孩子节点作比较,然后做出相应的调整。我们这里一样的用大根堆做示例。

注意:向下调整算法有一个前提(左右子树必须是一个堆,才能调整)
也就是说要执行向下调整必须要保证根节点的左右子树都是小根堆或大根堆我们才能执行向下调整。
此时根节点是2,2小于它的的孩子,那么我们就要和它的孩子交换位置,但是具体和哪个孩子交换位置呢?我们需要和两个孩子中大的那个孩子交换,那么我们就需要找到孩子节点的下标,还记得我们上面提到的通过父亲节点找孩子节点的公式吗。
LeftChild = Parent * 2 + 1; //左孩子的节点下标
RightChild = Parent * 2 + 2; //右孩子的节点下标

然后依次向下交换调整


计数排序

计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,快于任何比较排序算法。

时间复杂度

时间复杂度是O(n+k):通过上面的代码可知最终的计数算法花费的时间是3n+k,则时间复杂度是O(n+k)。 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序,堆排序。

空间复杂度

空间复杂度是O(k):如果出去最后的返回数组,则空间复杂度是2k,则空间复杂度是O(k)

稳定性

由于统计数组可以知道该索引在原数组中排第几位,相同的元素其在原数组中排列在后面,其从原数组的后面遍历,其在最终数组中的索引也在后面,所以相同的元素其相对位置不会改变。计数排序是稳定排序

实现
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*)malloc(sizeof(int) * range);
	if (count == NULL)
	{
		perror("malloc fail");
		return;
	}

	//映射数据 统计个数
	memset(count, 0, sizeof(int) * range);

	for (int i = 0; i < n; i++)
	{
		count[a[i] - min]++;
	}

	//排序
	int j = 0;
	for (int i = 0; i < range; i++)
	{
		while (count[i]--)
		{
			a[j++] = i + min;
		}
	}
}

计数排序最大的好处就是它的稳定性,在某些情况下时间复杂度可以做到惊人的O(1),比快速排序还要更快,能想出这种算法的人可谓是真正的佬。


最后放一张图供各位参考,可以保存起来方便以后快速查找


总结

创作不易,花了几个小时才写出来,感谢各位的三连关注,顺着评论回访🌹🌹

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

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

相关文章

windows下OOM排查

如下有一段代码 package com.lm.demo.arthas.controller;import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;import java.util.A…

Notepad++安装插件和配置快捷键

Notepad是一款轻量级、开源的文件编辑工具&#xff0c;可以编辑、浏览文本文件、二进制文件、.cpp、.java、*.cs等文件。Notepad每隔1个月&#xff0c;就有一个新版本&#xff0c;其官网是&#xff1a; https://github.com/notepad-plus-plus/notepad-plus-plus。这里介绍其插件…

maven之父子工程版本控制案例实战,及拓展groupId和artifactId的含义

<parent>标签 用于父子工程项目&#xff0c;什么是父子工程&#xff1f; 顾名思义&#xff0c;maven父子项目是一个有一个父项目&#xff0c;父项目下面又有很多子项目的maven工程&#xff0c;当然&#xff0c;子项目下面还可以添加子项目&#xff0c;从而形成一个树形…

GPS学习(一):在ROS2中将GPS经纬度数据转换为机器人ENU坐标系,在RVIZ中显示坐标轨迹

文章目录 一、GPS模块介绍二、坐标转换转换原理参数解释&#xff1a; 增加回调函数效果演示 本文记录在Ubuntu22.04-Humbel中使用NMEA协议GPS模块的过程&#xff0c;使用国产ROS开发板鲁班猫(LubanCat )进行调试。 一、GPS模块介绍 在淘宝找了款性价比较高的轮趣科技GPS北斗双…

AD7321代码SPI接口模数转换连接DAC0832输出verilog

名称&#xff1a;AD7321代码12位ADC&#xff0c;SPI接口模数转换连接DAC0832输出 软件&#xff1a;QuartusII 语言&#xff1a;VHDL 代码功能&#xff1a; 使用VHDL语言编写代码&#xff0c;实现AD7321的控制&#xff0c;将模拟信号转换为数字信号&#xff0c;再经过处理后…

fatfs对于exFAT的使用

f_mkfs的介绍 f_mkfs是FatFs库中的一个函数&#xff0c;用于在指定的磁盘上执行格式化操作。它可以用于创建新的文件系统或重新格式化已有的文件系统。 函数原型如下&#xff1a; FRESULT f_mkfs (const TCHAR* path, // 磁盘路径BYTE opt, // 格式化选项DWORD a…

【QT】点击按钮弹出对话框的注意事项

在stack区创建对话框对象 模态对话框&#xff0c;不可以对其他窗口进行操作。 模态窗口用dlg.exec()显示窗口。 问题代码1: MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) {ui->setupUi(this);//点击新建按钮&#xff0c;弹出一…

设计模式【Iterator 模式】

Iterator 模式 1.什么是 Iterator 模式 Iterator 模式就是按照顺序遍历数据集合。 2.示例程序 1.Aggregate 接口 Aggregate 接口是要遍历的集合的接口&#xff0c;声明方法 iterator &#xff0c;实现了该接口的类可以通过 iterator 方法遍历数据集合的元素。 public int…

H5游戏分享-全民找房祖名qmxzfzm

H5游戏分享-全民找房祖名qmxzfzm 一开始就比较简单 后面就会越来越难&#xff0c;而且也有时间限制 游戏的源码 <!DOCTYPE html> <html><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width,ini…

【神印王座】易军献身为林鑫挡箭,万万没想到林鑫太坑,大跌眼镜

【侵权联系删除】【文/郑尔巴金】 深度爆料&#xff0c;《神印王座》动漫最新剧集中&#xff0c;龙皓晨离开后&#xff0c;恶魔族新的援兵突然出现&#xff0c;使得队友们面临了前所未有的困境。这次战斗中&#xff0c;易军与圣采儿等人决定正面攻击恶魔统领&#xff0c;这无疑…

JVM基础:字节码文件详解①

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、Java虚拟机的组成二、字节码文件的组成2.1 为什么要了解字节码文件&#xff1f;2.2 如何“窥探”字节码文件的奥秘&#xff1f;2.2.1 使用工具打开字节码文件2.…

09循环嵌套

循环嵌套顾名思义循环里面套循环 # 循环嵌套顾名思义循环里面套循环a 1 b 0 while a < 10:# print(1, a)b 1while b < a and b < 10:print("%d*%d%d" % (b, a, a * b), end" ")b 1print()a 1format 格式化运算符 只需要填入数据即可 print(…

Mathtype使用指南01:下载与安装

目录 介绍&#xff1a; 安装 介绍&#xff1a; MathType 是一款广泛用于数学和科学文档创建的强大数学编辑工具。它允许用户轻松地在各种文档类型中插入数学方程、符号和公式&#xff0c;是学术界、工程领域、出版界和教育机构中的专业人士常用的工具。下面是关于 MathType 的…

ChineseChess6 2023.10.28

中国象棋残局&#xff1a;黑一卒一车 这红棋好像也是无解哦

如何使用ffmpeg制作透明背景的视频

最近我们尝试在网页上叠加数字人讲解的功能&#xff0c;发现如果直接在网页上放一个矩形的数字人视频&#xff0c;效果会很差&#xff0c;首先是会遮挡很多画面的内容&#xff0c;其次就是不管使用任何任务背景&#xff0c;画面都和后面的网页不是很协调&#xff0c;如图所示&a…

2-多媒体数据压缩国际标准

文章目录 多媒体数据压缩编码的重要性和分类为什么要压缩?计算: 未压缩音频的数据率简答: 环绕声系统-作业题9(简述7.4.3全景声)计算: 未压缩图像的数据量-作业题10(估计尺寸及容量)计算: 未压缩视频的数据率 为什么能压缩?数据压缩编码的两大类无损压缩算法: LZ77-作业题6-(…

Visual Studio Code的下载与安装

Visual Studio Code&#xff08;简称 VS Code&#xff09;是由 Microsoft 开发的免费、开源的文本编辑器&#xff0c;适用于多种操作系统&#xff0c;包括 Windows、macOS 和 Linux。它的设计目标是成为一款轻量级、高效的代码编辑工具&#xff0c;同时提供丰富的扩展和功能&am…

计算机毕业设计 基于SpringBoot大学生就业服务平台的设计与实现 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

【数据结构】交换排序

⭐ 作者&#xff1a;小胡_不糊涂 &#x1f331; 作者主页&#xff1a;小胡_不糊涂的个人主页 &#x1f4c0; 收录专栏&#xff1a;浅谈数据结构 &#x1f496; 持续更文&#xff0c;关注博主少走弯路&#xff0c;谢谢大家支持 &#x1f496; 冒泡、快速排序 1. 冒泡排序2. 快速…

Android应用:实现网络加载商品数据【OKHttp、Glide、Gson】

实现网络加载商品数据的功能&#xff1a; 1、在AndroidManifest.xml中声明网络权限&#xff1b; 2、在app/build.gradle中添加okhttp, glide, gson等必需的第3方库&#xff1b; 3、在MainActivity中通过OkHttpClient连接给定的Web服务&#xff0c;获取商品数据&#xff1b;对…