数据结构:直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序,计数排序(C实现)

在这里插入图片描述

个人主页 : 个人主页
个人专栏 : 《数据结构》 《C语言》

文章目录

  • 前言
  • 一、插入排序
    • 1.直接插入排序
    • 2.希尔排序
  • 二、选择排序
    • 1. 选择排序
    • 2.堆排序
  • 三、交换排序
    • 1.冒泡排序
    • 2.快速排序(递归)
      • a.hoare版(PartSort1)
      • b.挖坑法(PartSort2)
      • c.前后指针法(PartSort3)
    • 3.快速排序(非递归)
  • 四、归并排序
    • 归并排序(递归)
    • 归并排序(非递归)
  • 五、计数排序
  • 总结


前言

排序:使一串数据,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
在这里插入图片描述


一、插入排序

插入排序的思路:把待排序数组,逐个插入到已经排好序的有序数组中,直到所有待排序数组插入完成,的到一个新的有序数组。

1.直接插入排序

假如要排序为升序数组。
遍历待排序数组,将待排序数组元素与已排序数组元素比较,如果已排序数组元素大于待排序数组元素,已排序数组元素后移,待排序数组再次于前一个已排序数组比较,直到遍历完已排序数组或待排序数组元素大于已排序数组元素。
在这里插入图片描述

// 插入排序
//遍历待排序数组,每次选择数组元素 与 已排序数组元素比较,如果该数组元素小于已排序数组元素,已排序元素后移
//直到该数组元素遍历到首或大于已排序数组元素,插入该位置。
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int j = i;
		int tmp = a[i + 1];
		while (j >= 0)
		{
			if (tmp < a[j])
			{
				a[j + 1] = a[j];
			}
			else
			{
				break;
			}

			j--;
		}

		a[j + 1] = tmp;
	}
}
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  • 稳定性:稳定

2.希尔排序

我们要知道 待排序数组越接近有序,直接插入排序算法的时间效率越高
那么我们如果使一个待排序数组快速变成接近有序的数组,再对接近有序的数组进行一次直接插入排序,就是希尔排序

  • 那对于希尔排序的一个问题,如何使待排序数组快速变成接近有序数组

这就要使用gap(增益变量),对待排序数组每隔gap的元素进行直接插入排序,再对待排序数组每隔(gap/2)的元素进行直接插入排序,再对待排序数组每隔(gap/2)的元素进行直接插入排序…
直到gap为1时,待排序数组已经接近有序数组。在对待排序数组直接插入排序即可。

如下:对数组{9,1,2,5,7,4,8,6,3,5}进行希尔排序
在这里插入图片描述

// 希尔排序
//1、使待排序数组变成接近有序的数组   2、对接近有序的数组直接插入排序  O(n)
//使用gap(增益变量)来使待排序数组快速变成接近有序的数组
void ShellSort(int* a, int n)
{
	int gap = n;

	while (gap > 1)
	{
		gap = gap / 3 + 1; // + 1 保证最后一次排序一定是插入排序 or gap /= 2
		for (int i = 0; i < n - gap; i++)
		{
			int j = i;
			int tmp = a[j + gap];
			while (j >= 0)
			{
				if (a[j] > tmp)
				{
					a[j + gap] = a[j];
				}
				else
				{
					break;
				}

				j -= gap;
			}

			a[j + gap] = tmp;
		}
	}
}
  • 时间复杂度:O(N^1.3)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

二、选择排序

选择排序的思想:每次从待排序数组中选择出最大or最小的元素,放入已排序数组后,直到待排序数组中没有元素时,数组完成排序。

1. 选择排序

在这里插入图片描述
每次从待排序数组中选择最小的元素,与已排序数组的后一个元素交换,直到待排序数组中没有元素结束。


// 选择排序
//遍历待排序数组,每次选择最小的待排序数组元素,与待排序数组首元素交换。
void SelectSort(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		int minIndex = i;
		for (int j = i + 1; j < n; j++)
		{
			if (a[minIndex] > a[j])
			{
				minIndex = j;
			}
		}
		swap(&a[minIndex], &a[i]);
	}
}
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  • 稳定性:稳定

2.堆排序

堆排序详解
堆排序就是将待排序数组,构建为大堆(升序)or小堆(降序),然后将堆顶元素与待排序数组最后元素交换,删除堆最后的数据,再次选择新的堆顶元素。重复上述操作即可。

如下: 对数组 {16, 72, 31, 94, 53, 23}降序
在这里插入图片描述
在这里插入图片描述

// 堆排序
//升序建大堆
void AdjustDwon(int* a, int n, int parent)
{
	int child = parent * 2 + 1;
	while (parent < n)
	{
		//选择左右孩子较大值
		if (child + 1 < n && a[child] < a[child + 1])
		{
			child++;
		}

		if (child < n && a[parent] < a[child])
		{
			swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}


void HeapSort(int* a, int n)
{
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)
	{
		AdjustDwon(a, n, i);
	}

	int end = n - 1;
	while (end > 0)
	{
		swap(&a[0], &a[end]);
		AdjustDwon(a, end, 0);
		end--;
	}
}
  • 时间复杂度:O(N*logN)
  • 空间复杂度:O(1)
  • 稳定性:不稳定

三、交换排序

交换排序思想:根据待排序数组中两个元素的比较结果交换两个元素在待排序数组中的位置。

1.冒泡排序

在这里插入图片描述
从待排序数组中每次比较相邻的两个元素,如果前一个元素大于后一个元素,交换两个元素。如果前一个元素小于等于后一个元素,不变。继续向后比较相邻的两个元素。

void swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}

// 冒泡排序
void BubbleSort(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		int flag = 1;
		for (int j = 0; j < n - i - 1; j++)
		{
			if (a[j] > a[j + 1])
			{
				flag = 0;
				swap(&a[j], &a[j + 1]);
			}
		}
		//如果flag == 1表示这趟比较,并未交换元素,表示数组已经有序
		if (flag == 1)
		{
			break;
		}
	}
}
  • 时间复杂度:O(N^2)
  • 空间复杂度:O(1)
  • 稳定性:稳定

2.快速排序(递归)

快速排序(递归)思路:任取待排序数组中的某个元素为基准值,以该基准值为标准,将待排序数组分成左右两个子序列,左子序列都小于基准值,右子序列都大于该基准值,然后左右子序列重复该操作,直到左右子序列只有一个元素or没有元素结束,此时数组有序。

//类似于二叉树的先序遍历
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;

	int pivot = PartSort3(a, left, right);
	//int pivot = PartSort2(a, left, right);
	//int pivot = PartSort1(a, left, right);
	//区间[left, pivot - 1]  pivot  [pivot + 1, right]

	QuickSort(a, left, pivot - 1);
	QuickSort(a, pivot + 1, right);
}

那么快排是如何以基准值来区分左右子序列?

a.hoare版(PartSort1)

以待排序数组第一个元素为基准值,定义两个变量(left,right)分别指向待排序数组的左右边界。
先移动right,找到小于基准值的元素,right停止移动。移动left,找到大于基准值的元素,left停止移动,交换left 与 right的元素。重复上述操作,直到left 与 right 指向同一个元素,交换此时基准值 与 left指向的元素。就完成了以基准值为标准,将数组分成左右子数组。

如下:对数组{6,1,2,7,9,3,4,5,10,8}以6为基准值,来划分左右子序列
在这里插入图片描述
注意

如何保证left 与 right 相遇的位置值一定小于基准值?

left 与 right相遇有两种情况:

  • left 遇到 right ,此时right已经停止移动,代表right已经找到了小于基准值的元素,left 与 right相遇的值小于基准值
  • right 遇到 left,上一次left 与 right 都找到相应元素并交换 or 此时left指向的就是数组最左边,此时left指向元素小于等于基准值,left 与 right相遇的值小于基准值

这是以右边界为基准值为列。如果以左边界为基准值,要保证left 与 right相遇元素小于基准值,要left先移动。

left要不要从基准值的位置开始移动?

  • left必须从基准值的位置开始移动,假设对数组{0,2,5,9,1,3}进行快排,如果以0为基准值,left从2的位置开始移动,会导致2到0的左边去,使数组变为{2,0,5,9,1,3}。就不符合快排的划分。
//三数取中  针对已经有序的数组
int GetMiddle(int* a, int left, int right)
{
	int mid = (right - left) / 2 + left;

	if (a[mid] > a[left])
	{	
		if (a[mid] < a[right])
		{
			//left < mid < right
			return mid;
		}
		else if(a[left] > a[right])
		{
			//right < left < mid
			return left;
		}
		else
		{
			//left < right = mid
			return right;
		}
	}
	else
	{
		if (a[right] > a[left])
		{
			//mid < left < right
			return left;
		}
		else if (a[mid] < a[right])
		{
			//mid < right < left
			return right;
		}
		else
		{
			//right <= mid <= left
			return mid;
		}
	}
}

// 快速排序hoare版本
//注意1. 如何保证每次left == right时的值,小于等于keyi的值
//结束时两种情况  a.right遇left停,上一次循环结束时,right 与 left的值互换,此时left的值为小于等于keyi的值
//                b.left遇right停,这次循环right结束时,此时right的值小于等于keyi的值
//注意2. left开始要从keyi的位置起步
//如果left从keyi+1的位置起步,假如数组所有元素大于keyi的值,循环结束交换left与keyi的值,回造成keyi左右的值都大于keyi
int PartSort1(int* a, int left, int right)
{
	int keyi = GetMiddle(a, left, right);
	swap(&a[keyi], &a[left]);
	keyi = left;

	while (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;
}

b.挖坑法(PartSort2)

挖坑法与hoare的思路类似,保存基准值位置的元素(key),使right找小于等于key的元素,left找大于key的元素,只不过left 与 right每次找到元素时,直接赋值到hole(坑位)处。不需要等left 与 right 都找到元素,才进行操作。

在这里插入图片描述

//三数取中
int GetMiddle(int* a, int left, int right)
{
	int mid = (right - left) / 2 + left;

	if (a[mid] > a[left])
	{	
		if (a[mid] < a[right])
		{
			//left < mid < right
			return mid;
		}
		else if(a[left] > a[right])
		{
			//right < left < mid
			return left;
		}
		else
		{
			//left < right = mid
			return right;
		}
	}
	else
	{
		if (a[right] > a[left])
		{
			//mid < left < right
			return left;
		}
		else if (a[mid] < a[right])
		{
			//mid < right < left
			return right;
		}
		else
		{
			//right <= mid <= left
			return mid;
		}
	}
}


// 快速排序挖坑法  
//每找到一个不符合要求的数,交换
int PartSort2(int* a, int left, int right)
{
	int keyi = GetMiddle(a, left, right);
	swap(&a[keyi], &a[left]);

	int key = a[left];
	int hole = left;
	while (left < right)
	{
		while (left < right && a[right] > key)
		{
			right--;
		}
		swap(&a[hole], &a[right]);
		hole = right;

		while (left < right && a[left] <= key)
		{
			left++;
		}
		swap(&a[hole], &a[left]);
		hole = left;
	}

	a[hole] = key;
	return hole;
}

c.前后指针法(PartSort3)

前后指针法也就是双指针法,一个指针cur遍历待排序数组,一个指针prev指向小于等于基准值(key)的最后一个元素。如果cur指向元素小于等于key,使prev先移动,在交换cur 与 prev指向的元素。如果cur指向元素大于key,cur移动,prev不动。直到cur遍历完数组,交换prev指向元素 与
key.。即可将数组分成小于key key 大于key的三部分。

在这里插入图片描述

//三数取中
int GetMiddle(int* a, int left, int right)
{
	int mid = (right - left) / 2 + left;

	if (a[mid] > a[left])
	{	
		if (a[mid] < a[right])
		{
			//left < mid < right
			return mid;
		}
		else if(a[left] > a[right])
		{
			//right < left < mid
			return left;
		}
		else
		{
			//left < right = mid
			return right;
		}
	}
	else
	{
		if (a[right] > a[left])
		{
			//mid < left < right
			return left;
		}
		else if (a[mid] < a[right])
		{
			//mid < right < left
			return right;
		}
		else
		{
			//right <= mid <= left
			return mid;
		}
	}
}

//思路类似于,在数组中删除val的值。
int PartSort3(int* a, int left, int right)
{
	int keyi = GetMiddle(a, left, right);
	swap(&a[keyi], &a[left]);

	keyi = left;
	int prev = left;
	for (int cur = left + 1; cur <= right; cur++)
	{
		//不能判断为 prev + 1 != cur 如果9,1,2,3,4,5,6。此时keyi的值为9。cur遍历到2时,会使9与2交换,使keyi的值发生改变
		if (a[cur] < a[keyi] && ++prev != cur)
		{
			//prev++;
			swap(&a[prev], &a[cur]);
		}
	}

	swap(&a[prev], &a[keyi]);
	return prev;
}

3.快速排序(非递归)

用栈的先进后出模拟递归。
先将此时数组元素范围[0,sz]压栈,然后将栈顶数据出栈,定为start 与 end。在以start 与 end为区间,选取基准值(key),划分左子序列,右子序列。再将左子序列,右子序列的区间分别入栈。重复上述过程,如果左右子区间不存在就不入栈,直到栈中没有数据,此时数组已完成排序。

如下:
在这里插入图片描述

栈的代码在这里

//三数取中
int GetMiddle(int* a, int left, int right)
{
	int mid = (right - left) / 2 + left;

	if (a[mid] > a[left])
	{	
		if (a[mid] < a[right])
		{
			//left < mid < right
			return mid;
		}
		else if(a[left] > a[right])
		{
			//right < left < mid
			return left;
		}
		else
		{
			//left < right = mid
			return right;
		}
	}
	else
	{
		if (a[right] > a[left])
		{
			//mid < left < right
			return left;
		}
		else if (a[mid] < a[right])
		{
			//mid < right < left
			return right;
		}
		else
		{
			//right <= mid <= left
			return mid;
		}
	}
}

//思路类似于,在数组中删除val的值。
int PartSort3(int* a, int left, int right)
{
	int keyi = GetMiddle(a, left, right);
	swap(&a[keyi], &a[left]);

	keyi = left;
	int prev = left;
	for (int cur = left + 1; cur <= right; cur++)
	{
		//不能判断为 prev + 1 != cur 如果9,1,2,3,4,5,6。此时keyi的值为9。cur遍历到2时,会使9与2交换,使keyi的值发生改变
		if (a[cur] < a[keyi] && ++prev != cur)
		{
			//prev++;
			swap(&a[prev], &a[cur]);
		}
	}

	swap(&a[prev], &a[keyi]);
	return prev;
}


// 快速排序 非递归实现
//借助栈的先进后出,先进左区间,再进右区间。
void QuickSortNonR(int* a, int left, int right)
{
	Stack s;
	StackInit(&s);

	StackPush(&s, left);
	StackPush(&s, right);
	while (!StackEmpty(&s))
	{
		int end = StackTop(&s);
		StackPop(&s);
		int stark = StackTop(&s);
		StackPop(&s);

		int pivot = PartSort3(a, stark, end);
		// [start, pivot - 1]  pivot  [pivot + 1, end]
		//左区间
		if (stark < pivot - 1)
		{
			StackPush(&s, stark);
			StackPush(&s, pivot - 1);
		}
		//右区间
		if (pivot + 1 < end)
		{
			StackPush(&s, pivot + 1);
			StackPush(&s, end);
		}
	}

	StackDestroy(&s);
}

  • 快排的时间复杂度:O(NlogN)
  • 快排的空间复杂度:O(logN)
  • 稳定性:不稳定
  • 如果是对一组元素相同的数据处理,那么快排的时间复杂度就退化为O(N^2),三路划分可以解决这类问题。

四、归并排序

归并排序思路:先将待排序数组分解为有序数组,再两两合并有序数组。

归并排序(递归)

在这里插入图片描述
如上图,我们对数组{10,6,7,1,3,9,4,3}进行分解,直到每个区间只有一个元素时(保证每个区间都是有序的),再两两合并区间(需要借助额外的数组tmp来保存合并的数组,再将tmp数组copy置原数组中)。[类似于二叉树的后序遍历]

// 归并排序递归实现
void _MergeSort(int* a, int start, int end, int* tmp)
{
	if (start == end)
		return;

	int mid = (end - start) / 2 + start;
	//[start, mid] [mid + 1, end]
	_MergeSort(a, start, mid, tmp);
	_MergeSort(a, mid + 1, end, tmp);

	//合并有序数组
	int begin1 = start, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin1;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] <= a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}

	while (begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}

	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
	//要注意每次copy数组的起始位置
	memcpy(a + start, tmp + start, sizeof(int)*(end - start + 1));
}


//类似于二叉树的后序遍历
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * (n + 1));
	if (tmp == NULL)
	{
		perror("malloc:");
		exit(-1);
	}
	
	_MergeSort(a, 0, n - 1, tmp);
	free(tmp);
}

归并排序(非递归)

归并排序的非递归实现并不需要借助栈或队列,只用循环即可完成。
我们先对待排序数组中一个元素与一个元素两两合并,再对数组中两个元素与两个元素两两合并,再对数组中四个元素与四个元素两两合并,直到要合并的元素个数大于数组元素结束,此时数组有序。

在这里插入图片描述

如果在合并最后一组有序数组时,有一下情况要注意:

  • 情况1:end2 > begin2 > end1 > sz(数组元素个数 - 1),begin1 < sz。
  • 情况2:end2 > begin2 > sz(数组元素个数 - 1), begin1 < end1 = sz
  • 情况3:end2 > sz,begin1 < end1 < begin2 < sz
    在这里插入图片描述
    对于情况1,情况2而言,我们只需要结束这次合并即可,因为begin1 到 sz的区间内数组是有序的
    对于情况3而言,我们只需要改变end2即可,使end2 = sz。
// 归并排序非递归实现
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * (n + 1));
	if (tmp == NULL)
	{
		perror("malloc:");
		exit(-1);
	}
	
	for (int gap = 1; gap < n; gap *= 2)
	{
		for (int i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = begin2 + gap - 1;

			if (end1 >= n || begin2 >= n)
				break;
			if (end2 >= n)
				end2 = n - 1;

			int j = begin1;
			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));
		}//for (int i = 0; i < n; i += 2 * gap)
	}//for (int gap = 1; gap <= n / 2; gap++)

	free(tmp);
}
  • 时间复杂度:O(NlogN)
  • 空间复杂度:O(N)
  • 稳定性:稳定
  • 归并排序思路更多解决的是外排序问题

五、计数排序

计数排序也就是建立一个映射关系,来进行排序。
我们先在待排序数组中查找最大值(max) 与 最小值(min),再创建一个空间(tmp)大小为(max - min + 1)的数组,将次tmp置0,遍历待排序数组,将每个元素 - min所对应在tmp的位置+1。再遍历tmp空间,如果tmp中元素不为0的,将其加上min,放入待排序数组并将tmp中元素减一。

在这里插入图片描述

// 计数排序
void CountSort(int* a, int n)
{
	int min = a[0], max = a[0];
	for (int i = 0; i < n; i++)
	{
		if (min > a[i])
			min = a[i];
		if (max < a[i])
			max = a[i];
	}

	int* tmp = (int*)malloc(sizeof(int) * (max - min + 1));
	if (tmp == NULL)
	{
		perror("malloc");
		exit(-1);
	}
	memset(tmp, 0, sizeof(int) * (max - min + 1));

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

	int k = 0;
	int i = 0;
	while (i < (max - min + 1))
	{
		if (tmp[i] != 0)
		{
			a[k++] = i + min;
			tmp[i] -= 1;
		}
		else
		{
			i++;
		}
	}

	free(tmp);
}
  • 时间复杂度:O(N)
  • 对于数组元素并不是集中的,会造成空间浪费

总结

以上就是我对于直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序的理解。感谢支持!!!
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【云驻共创】华为云之手把手教你搭建IoT物联网应用充电桩实时监控大屏

文章目录 前言1.什么是充电桩2.什么是IOT3.什么是端、边、云、应用协同4.什么是Astro轻应用 一、玩转lOT动态实时大屏&#xff08;线下实际操作&#xff09;1.Astro轻应用说明1.1 场景说明1.2 资费说明1.3 整体流程 2.操作步骤2.1 开通设备接入服务2.2 创建产品2.3 注册设备2.4…

vue页面转pdf后分页时文字被横向割裂

效果 预期效果 //避免分页被截断async outPutPdfFn (id, title) {const _t this;const A4_WIDTH 592.28;const A4_HEIGHT 841.89;// dom的id。let target document.getElementById(pdf);let pageHeight target.scrollWidth / A4_WIDTH * A4_HEIGHT;// 获取分割dom&#xf…

static相关知识点详解

文章目录 一. 修饰成员变量二. 修饰成员方法三. 修饰代码块四. 修饰类 一. 修饰成员变量 static 修饰的成员变量&#xff0c;称为静态成员变量&#xff0c;该变量不属于某个具体的对象&#xff0c;是所有对象所共享的。 public class Student {private String name;private sta…

MySQL-Centos下MySQL5.7安装教程

MySQL安装教程 一&#xff0c;卸载MySQL二&#xff0c;安装MySQL三&#xff0c;mysql登录四&#xff0c;修改配置文件 一&#xff0c;卸载MySQL 1.如果你的机器上mysqld服务器还在运行&#xff0c;那么第一步就是要停掉服务。 systemctl stop mysqld;2.查看系统中安装的关于m…

vim 常见操作

Vim 工作模式 1、vim 三种基本的工作模式 vim有三种基本的工作模式&#xff0c;分别为&#xff1a;命令模式、末行模式、编辑模式。关于这三种工作模式的介绍&#xff0c;请见下文。 1.1、命令模式 使用vim打开文件之后&#xff0c;首先进入命令模式&#xff0c;它是vim编辑…

RISC-V公测平台发布· CoreMark测试报告

一. CoreMark简介 CoreMark是一款用于评估CPU性能的基准测试程序&#xff0c;它包含了多种不同的计算任务&#xff0c;包括浮点数、整数、缓存、内存等方面的测试。CoreMark的测试结果通常被用来作为CPU性能的参考&#xff0c;它可以帮助开发人员和系统管理员评估不同处理器和…

iOS 如何对整张图分别局部磨砂,并完全贴合

官方磨砂方式 - (UIVisualEffectView *)effectView{if(!_effectView){UIBlurEffect *blur [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];_effectView [[UIVisualEffectView alloc] initWithEffect:blur];}return _effectView; }使用这种方式对一张图的上半部分和…

数学建模大全及优缺点解读

分类模型 1、距离聚类&#xff08;系统聚类&#xff09;&#xff08;常用&#xff0c;需掌握&#xff09; 优点&#xff1a; ①将一批样本数据按照他们在性质上的亲密程度在没有先验知识的情况下自动进行分类 ②是一种探索性的分析方法&#xff0c;分类结果不一定相同 例如&am…

住宅IP:解锁更快速、稳定的互联网,你准备好了吗?

随着互联网的广泛普及&#xff0c;我们对网络的需求也越来越高。无论是工作、学习还是娱乐&#xff0c;我们都希望能够享受到更快速、稳定的互联网连接。而在实现这一目标的过程中&#xff0c;住宅IP正逐渐崭露头角&#xff0c;成为了一种备受关注的解决方案。那么&#xff0c;…

用户端Web自动化测试-L2

目录&#xff1a; 高级定位-css高级定位-xpath显式等待高级使用高级控件交互方法网页 frame 与多窗口处理文件上传&#xff0c;弹框处理自动化关键数据记录电子商务产品实战 1.高级定位-css css 选择器概念 css 选择器有自己的语法规则和表达式css 定位通常分为绝对定位和相…

Java IO流(四)Netty理论[模型|核心组件]

概述 Netty是由JBOSS提供的一个Java开源框架,可从Github获取独立项目Netty是一个异步的、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端(摘录官网)Netty所谓的异步是针对用户使用Channel进行IO操作,会立即返回ChannelFuture。但IO操作的任务是提…

开源容灾备份软件,开源cdp备份软件

数据的安全性和完整性面临着硬件问题、黑客攻击、人为错误等各种威胁。在这种环境下&#xff0c;开源容灾备份软件应运而生&#xff0c;通过提供自动数据备份和恢复&#xff0c;有效地保证了公司的数据安全。 一、开源容灾备份软件的定义和作用 开源容灾备份软件是一种基于开源…

SqlServer2019—解决SQL Server 无法连接127.0.0.1的问题

1、打开SQL Server 2019配置管理器 2、SQL Servere 网络配置(启用 Named Pipes 和 TCP/IP) 3、修改TCP/IP协议(右键选择属性—IP地址)&#xff0c;具体如下图所示&#xff1a; 4、重启SQL Server服务

漏洞挖掘和漏洞利用技术:讨论漏洞发现、利用和修复,深入研究不同类型漏洞的技术细节

章节一&#xff1a;引言 在当今数字化时代&#xff0c;计算机技术的迅猛发展为我们的生活带来了无数便利&#xff0c;然而也伴随着各种安全威胁。恶意黑客利用漏洞进行攻击已成为一种常见现象。本文将深入探讨漏洞挖掘和漏洞利用技术&#xff0c;以及如何修复这些漏洞&#xf…

智慧充电桩物联网方案架构

智慧充电桩物联网采用“云-管-边-端”的边缘计算物联网架构&#xff0c;融合5G、AI、Wi-Fi 6等技术&#xff0c;实现充电基础设施由数字化向智能化演进。智慧充电桩物联网方案架构设计&#xff0c;如下图所示&#xff1a; 云端&#xff1a; 物联网平台具备广泛协议的南向接入…

基于QCC_BES 平台的LMS自适应滤波算法实现

+我V hezkz17进数字音频系统研究开发交流答疑群(课题组) LMS算法是最小均方(Least Mean Square)算法的缩写。它是一种自适应滤波算法,常用于信号处理、系统辨识和自适应滤波等领域。 LMS算法的目标是通过对输入信号和期望输出信号之间的误差进行最小化,来调整滤波器的权重…

matlab使用教程(22)—非线性优化函数的设置

1.设置优化选项 可以使用由 optimset 函数创建的 options 结构体来指定优化参数。然后&#xff0c;可以将 options 作为输入传递给优化函数&#xff0c;例如&#xff0c;通过使用以下语法调用 fminbnd x fminbnd(fun,x1,x2,options) 或使用以下语法调用 fminsearch x f…

8月21-22日上课内容 第一章 MySQL数据库初始

本章结构 数据库的基本概念 概述&#xff08;总览&#xff09; 结构&#xff1a; 数据 表 数据库 数据库管理系统 数据库系统原理 数据 (Data) 描述事物的符号记录 包括数字&#xff0c;文字、图形、图像、声音、档案记录等以“记录”形式按统一的格式进行存储表 将不同…

验证码识别DLL ,滑块识别SDK,OCR图片转文字,机器视觉找物品

验证码识别DLL ,滑块识别SDK 你们用过哪些OCR提取文字&#xff0c;识图DLL&#xff0c;比如Opencv,Labview机器视觉找物品之类&#xff1f;

Selenium的使用:WEB功能测试

Selenium是ThrougthWorks公司一个强大的开源WEB功能测试工具系列&#xff0c;本系统包括多款软件 Selenium语言简单&#xff0c;用(Command,target,value)三种元素组成一个行为&#xff0c;并且有协助录制脚本工具&#xff0c;但Selenese有一些严格的限制&#xff1a; …