【数据结构初阶第十九节】八大排序系列(下篇)—[详细动态图解+代码解析]

hello,好久不见! 云边有个稻草人-CSDN博客

上篇内容,回顾一下吧【数据结构初阶第十八节】八大排序系列(上篇)—[详细动态图解+代码解析]-CSDN博客

今天我们来学习下篇

目录

(2)快速排序

【挖坑法】

—思路

—思路图解 

—代码

【lomuto前后指针法】

—思路

—思路图解 

—代码

—效果展示

—快速排序特性总结

【非递归版本快排】

—思路

—思路图解

—代码

4.归并排序

—大致思路

—大致思路图解

—代码

—归并排序特性总结

—效果展示

5.测试代码:排序性能对比

6.非比较排序—计数排序

—图解

—代码

—计数排序的特性

—效果展示

三、排序算法复杂度及稳定性分析

稳定性

四、两节课代码汇总

Stack.h

sort.h

Stack.c

sort.c

test.c

未完待续——

   ———————————————《剧终The End》———————————————


续接上篇,正文开始——

(2)快速排序

【挖坑法】
—思路
创建左右指针。⾸先从右向左找出⽐基准⼩的数据,找到后⽴即放⼊左边坑中,当前位置变为新的"坑",然后从左向右找出⽐基准⼤的数据,找到后⽴即放⼊右边坑中,当前位置变为新的"坑",结束循环后将最开始存储的分界值放⼊当前的"坑"中,返回当前"坑"下标(即分界值下标)

—思路图解 
—代码
//挖坑法
int _QuickSort(int* arr, int left, int right)
{int hole = left;int key = arr[left];while (left < right){//从右往左找比基准值小的while (left < right && arr[right] > key){right--;}arr[hole] = arr[right];hole = right;//从左往右找比基准值大的while (left < right && arr[left] < key){left++;}arr[hole] = arr[left];hole = left;}arr[hole] = key;return hole;
}//快排
void QuickSort(int* arr, int left, int right)
{if (left >= right){return;}//1.找基准值int key = _QuickSort(arr,left,right);//2.左子序列进行排序QuickSort(arr, left, key - 1);//3.右子序列进行排序QuickSort(arr, key + 1, right);
}
【lomuto前后指针法】
—思路
创建前后指针,从左往右找⽐基准值⼩的进⾏交换,使得⼩的都排在基准值的左边。
—思路图解 

—代码
//lomuto前后指针
int _QuickSort(int* arr, int left, int right)
{int key = left;int prev = left, cur = left + 1;while (cur <= right){if (arr[cur] < arr[key] && ++prev != cur)//这里的等号加不加都一样,//对于全是重复的数据时间复杂度很高{Swap(&arr[cur], &arr[prev]);}cur++;}Swap(&arr[prev], &arr[key]);return prev;
}//快排
void QuickSort(int* arr, int left, int right)
{if (left >= right){return;}//1.找基准值int key = _QuickSort(arr,left,right);//2.左子序列进行排序QuickSort(arr, left, key - 1);//3.右子序列进行排序QuickSort(arr, key + 1, right);
}
—效果展示

—快速排序特性总结
1. 时间复杂度: O ( nlogn )
2. 空间复杂度: O ( logn )

【非递归版本快排】
—思路
非递归版本的快速排序需要借助数据结构:栈。
主要思路就是利用循环来模拟递归。将区间进行入栈,两次取栈顶数据(不要忘记出栈,取栈顶数据前判断栈是否为空)作为一个区间,在这个区间内通过前面学到的某种方法得到基准值,再根据基准值得到新的左右区间再入栈,入栈前要判断要入栈的区间是否是有效区间,再两次取栈顶数据循环前面操作。
—思路图解

—代码

这里我们采用lomuto方法进行取基准值

//非递归版本的快排
void QuickSortNonR(int* arr, int left, int right)
{ST st;STInit(&st);//首先将left和right进行入栈StackPush(&st, right);StackPush(&st, left);while (!StackEmpty(&st)){//取栈顶元素--取两次int begin = StackTop(&st);StackPop(&st);int end = StackTop(&st);StackPop(&st);//找基准值int keyi = begin;int cur = begin + 1;int prev = begin;while (cur <= end){if (arr[cur] < arr[keyi] && ++prev != cur){Swap(&arr[prev], &arr[cur]);}cur++;}Swap(&arr[prev], &arr[keyi]);keyi = prev;//找到了基准值//根据基准值再去找新的左右区间再入栈//左区间:[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);}}STDestroy(&st);
}

4.归并排序

—大致思路

利用二叉树递归的思想先将数组进行递归分解,直到每个区间分的只有一个数据此时不能再分,分解之后就是合并,注意合并的是一个数组里面两个区间里的数据并不是真的新的两个数组,合并的方法是利用我们前面学到的算法题—合并两个数组;我们是将合并之后有序的数据先存放到一个新创建的tmp数组里面,再将tmp里面的数据拷贝给原数组arr,这样方便操作一些;就这样在不断递归的过程中完成排序操作。

—大致思路图解

—代码
void _MergeSort(int* arr, int left, int right, int* tmp)
{//先递归分解if (left >= right){return;}int mid = (left + right) / 2;_MergeSort(arr, left, mid, tmp);_MergeSort(arr, mid+1, right, tmp);//合并int begin1 = left, end1 = mid;int begin2 = mid + 1, end2 = right;int index = begin1;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] < arr[begin2]){tmp[index++] = arr[begin1++];}else{tmp[index++] = arr[begin2++];}}while (begin1 <= end1){tmp[index++] = arr[begin1++];}while (begin2 <= end2){tmp[index++] = arr[begin2++];}//将tmp里面的数据拷贝回arr里面for (int i = left; i <= right; i++){arr[i] = tmp[i];}
}//归并排序
void MergeSort(int* arr, int n)
{//重新创建一块空间来存放数据int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(arr, 0, n - 1,tmp);free(tmp);
}
—归并排序特性总结
1. 时间复杂度: O ( nlogn )
2. 空间复杂度: O ( n )
—效果展示

对于同样的10W个数据,不同的排序分别用了多久 

5.测试代码:排序性能对比

前面我们讲过的,这里再发一下,看一下代码就可以明白其中的道理。

// 测试排序的性能对⽐
void TestOP()
{srand(time(0));const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);int* a7 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];a7[i] = a1[i];}int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin3 = clock();SelectSort(a3, N);int end3 = clock();int begin4 = clock();HeapSort(a4, N);int end4 = clock();int begin5 = clock();QuickSortNonR(a5, 0, N - 1);int end5 = clock();int begin6 = clock();MergeSort(a6, N);int end6 = clock();int begin7 = clock();BubbleSort(a7, N);int end7 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);printf("BubbleSort:%d\n", end7 - begin7);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);
}int main()
{TestOP();return 0;
}

6.非比较排序—计数排序

计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。
操作步骤:
1)统计相同元素出现次数
2)根据统计的结果将序列回收到原来的序列中
—图解

—代码
//计数排序
void CountSort(int* arr, int n)
{//根据最大值和最小值来确定数组的大小int max = arr[0], min = arr[0];for (int i = 1; i < n; i++){if (arr[i] > max){max = arr[i];}if (arr[i] < min){min = arr[i];}}int range = max - min + 1;int* count = (int*)malloc(sizeof(int) * range);if (count == NULL){perror("malloc file!");exit(1);}//初始化range数组里面的数据都为0memset(count, 0, range * sizeof(int));//统计原数组中每个数据出现的次数,将次数存放对应的在count数组里面for (int i = 0; i < n; i++){count[arr[i] - min]++;}//将count里面的数据往arr里面去放int index = 0;for (int i = 0; i < range; i++){while (count[i]--){arr[index++] = i + min;}}
}
—计数排序的特性
计数排序在数据范围集中时,效率很高,但是适⽤范围及场景有限,只适用于整数排序,无法对小数进行排序。
时间复杂度: O(N + range) —遍历一遍 count 数组,里面的 while 循环执行了N次,就是有多少个数据就执行多少次
空间复杂度: O(range) —开辟了range个空间
稳定性:稳定
—效果展示

这么强 ?!!!

0 ?!真假的

三、排序算法复杂度及稳定性分析

稳定性

假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。(就是相同的数据排序之后的相对次序保持不变)
自己把前面的所有排序算法都理解透彻并能自己实现出来,自己理解下面的表格就会很轻松,不然都忘记了就会很痛苦。。。对于稳定性自己找出实例后独立分析

四、两节课代码汇总

Stack.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>//定义栈的结构
typedef int STDataType;
typedef struct Stack
{STDataType* arr;int capacity;  //栈的容量int top;       //栈顶
}ST;//初始化
void STInit(ST* ps);//销毁
void STDestroy(ST* ps);//入数据
void StackPush(ST* ps, STDataType x);//出数据
void StackPop(ST* st);//取栈顶元素
STDataType StackTop(ST* ps);//判空
bool StackEmpty(ST* ps);//获取栈中有效的数据个数
int STsize(ST* ps);

sort.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<memory.h>void Print(int* arr, int n);
void BubbleSort(int* arr, int n);
void HeapSort(int* arr, int n);
void InsertSort(int* arr, int n);
void ShellSort(int* arr, int n);
void SelectSort(int* arr, int n);
void QuickSort(int* arr, int left, int right);//非递归版本的快排
void QuickSortNonR(int* arr, int left, int right);//归并排序
void MergeSort(int* arr, int n);//计数排序
void CouuntSort(int* arr, int n);

Stack.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"//初始化
void STInit(ST* ps)
{assert(ps);ps->arr = NULL;ps->capacity = ps->top = 0;  //此时栈为空,栈顶=栈底
}//销毁
void STDestroy(ST* ps)
{assert(ps);if (ps->arr){free(ps->arr);}ps->arr = NULL;ps->capacity = ps->top = 0;
}//入数据
void StackPush(ST* ps, STDataType x)
{assert(ps);//判断空间是否足够if (ps->capacity == ps->top){//申请空间int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));if (tmp == NULL){perror("realloc file!");exit(1);}ps->arr = tmp;ps->capacity = newCapacity;}//空间足够ps->arr[ps->top++] = x;
}//出数据
void StackPop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));ps->top--;
}//判空
bool StackEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}//取栈顶元素
STDataType StackTop(ST* ps)
{assert(ps);assert(!StackEmpty(ps));return ps->arr[ps->top - 1];
}//获取栈中有效的数据个数
int STsize(ST* ps)
{assert(ps);return ps->top;
}

sort.c

#include"sort.h"
#include"Stack.h"void Print(int* arr, int n)
{for (int i = 0; i < n; i++){printf("%d ", arr[i]);}printf("\n");
}void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}//冒泡排序
void BubbleSort(int* arr, int n)
{for (int i = 0; i < n; i++){int exchange = 0;for (int j = 0; j < n - i - 1; j++){if (arr[j] < arr[j + 1]){exchange = 1;Swap(&arr[j], &arr[j + 1]);}}if (exchange == 0){break;}}
}//向下调整数据
void AdjustDown(int* arr, int parent, int n)
{int child = parent * 2 + 1;while (child < n){//找出左右孩子中最小的->小堆 >//找出左右孩子中最大的->大堆 <if (child + 1 < n && arr[child] < arr[child + 1]){child++;}// < 建小堆// > 建大堆 if (arr[child] > arr[parent]){Swap(&arr[parent], &arr[child]);parent = child;child = parent * 2 + 1;}else{break;}}
}//堆排序
void HeapSort(int* arr, int n)
{//向下调整算法建堆for (int i = (n - 2) / 2; i >= 0; i--){AdjustDown(arr, i, n);}//堆排序int end = n - 1;while (end > 0){//end指向的是最后一个数据Swap(&arr[0], &arr[end]);//有效的数据个数减了1AdjustDown(arr, 0, end);end--;}
}//直接插入排序
void InsertSort(int* arr, int n)
{for (int i = 0; i < n - 1; i++){int end = i;int tmp = arr[end + 1];while (end >= 0){if (arr[end] > tmp){arr[end + 1] = arr[end];end--;//--是为了让tmp与区间前面的元素进行挨个比较,最后找到合适的位置}else{break;}}//此时end可能等于-1,或者是因为end指向的元素 < tmp,此时我们还没有进行最后的赋值,//这时我们都要把tmp里面的数据赋值给arr[end+1]arr[end + 1] = tmp;}
}//希尔排序
void ShellSort(int* arr, int n)
{int gap = n;//用来控制gap,当gap==1时就是直接插入排序while (gap > 1)//不能等于1,等于1的话最后会死循环{gap = gap / 3 + 1;//保证最后一次gap一定为1,/3,是为了让每组数据个数较恰当for (int i = 0; i < n - gap; i++){int end = i;int tmp = arr[end + gap];while (end >= 0){if (arr[end] > tmp){arr[end + gap] = end;end-=gap; }else{break;}}arr[end + gap] = tmp;}}
}直接选择排序
//void SelectSort(int* arr, int n)
//{
//	for (int i = 0; i < n; i++)
//	{
//		int mini = i;
//		//找后面区间里最小值的下标
//		for (int j = i; j < n; j++)
//		{
//			if (arr[j] < arr[mini])
//			{
//				mini = j;
//			}
//		}
//		Swap(&arr[i], &arr[mini]);
//	}
//}//直接插入排序
void SelectSort(int* arr, int n)
{int begin = 0;int end = n - 1;while (begin < end){int mini = begin, maxi = begin;//在后面区间内找maxi,minifor (int j = begin+1; j <= end; j++){if (arr[j] < arr[mini]){mini = j;}if (arr[j] > arr[maxi]){maxi = j;}}if (maxi == begin){maxi = mini;}Swap(&arr[begin], &arr[mini]);Swap(&arr[end], &arr[maxi]);begin++;end--;}
}Hoare版本找基准值
//int _QuickSort(int* arr, int left, int right)
//{
//	int key = left;
//	left++;
//	while (left <= right)
//	{
//		//找比基准值大的
//		while (left <= right && arr[left] < arr[key])
//		{
//			left++;
//		}
//		//找比基准值小的
//		while (left <= right && arr[right] > arr[key])
//		{
//			right--;
//		}
//		if (left <= right)
//		{
//			Swap(&arr[right--], &arr[left++]);
//		}
//	}
//	//将right指向的数据和key指向的数据进行交换
//	Swap(&arr[key], &arr[right]);
//
//	return right;
//}挖坑法
//int _QuickSort(int* arr, int left, int right)
//{
//	int hole = left;
//	int key = arr[left];
//	while (left < right)
//	{
//		//从右往左找比基准值小的
//		while (left < right && arr[right] > key)
//		{
//			right--;
//		}
//		arr[hole] = arr[right];
//		hole = right;
//
//		//从左往右找比基准值大的
//		while (left < right && arr[left] < key)
//		{
//			left++;
//		}
//		arr[hole] = arr[left];
//		hole = left;
//	}
//	arr[hole] = key;
//	return hole;
//}//lomuto前后指针
int _QuickSort(int* arr, int left, int right)
{int key = left;int prev = left, cur = left + 1;while (cur <= right){if (arr[cur] < arr[key] && ++prev != cur){Swap(&arr[cur], &arr[prev]);}cur++;}Swap(&arr[prev], &arr[key]);return prev;
}//快排
void QuickSort(int* arr, int left, int right)
{if (left >= right){return;}//1.找基准值int key = _QuickSort(arr,left,right);//2.左子序列进行排序QuickSort(arr, left, key - 1);//3.右子序列进行排序QuickSort(arr, key + 1, right);
}//非递归版本的快排
void QuickSortNonR(int* arr, int left, int right)
{ST st;STInit(&st);//首先将left和right进行入栈StackPush(&st, right);StackPush(&st, left);while (!StackEmpty(&st)){//取栈顶元素--取两次int begin = StackTop(&st);StackPop(&st);int end = StackTop(&st);StackPop(&st);//找基准值int keyi = begin;int cur = begin + 1;int prev = begin;while (cur <= end){if (arr[cur] < arr[keyi] && ++prev != cur){Swap(&arr[prev], &arr[cur]);}cur++;}Swap(&arr[prev], &arr[keyi]);keyi = prev;//找到了基准值//根据基准值再去找新的左右区间再入栈//左区间:[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);}}STDestroy(&st);
}void _MergeSort(int* arr, int left, int right, int* tmp)
{//先递归分解if (left >= right){return;}int mid = (left + right) / 2;_MergeSort(arr, left, mid, tmp);_MergeSort(arr, mid+1, right, tmp);//合并int begin1 = left, end1 = mid;int begin2 = mid + 1, end2 = right;int index = begin1;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] < arr[begin2]){tmp[index++] = arr[begin1++];}else{tmp[index++] = arr[begin2++];}}while (begin1 <= end1){tmp[index++] = arr[begin1++];}while (begin2 <= end2){tmp[index++] = arr[begin2++];}//将tmp里面的数据拷贝回arr里面for (int i = left; i <= right; i++){arr[i] = tmp[i];}
}//归并排序
void MergeSort(int* arr, int n)
{//重新创建一块空间来存放数据int* tmp = (int*)malloc(sizeof(int) * n);_MergeSort(arr, 0, n - 1,tmp);free(tmp);
}//计数排序
void CountSort(int* arr, int n)
{//根据最大值和最小值来确定数组的大小int max = arr[0], min = arr[0];for (int i = 1; i < n; i++){if (arr[i] > max){max = arr[i];}if (arr[i] < min){min = arr[i];}}int range = max - min + 1;int* count = (int*)malloc(sizeof(int) * range);if (count == NULL){perror("malloc file!");exit(1);}//初始化range数组里面的数据都为0memset(count, 0, range * sizeof(int));//统计原数组中每个数据出现的次数,将次数存放对应的在count数组里面for (int i = 0; i < n; i++){count[arr[i] - min]++;}//将count里面的数据往arr里面去放int index = 0;for (int i = 0; i < range; i++){while (count[i]--){arr[index++] = i + min;}}
}

test.c

#include"sort.h"void test()
{int arr[] = { 5,3,9,6,2,4,7,1,8 };int n = sizeof(arr) / sizeof(int);printf("排序前:");Print(arr, n);/*InsertSort(arr, n);*//*BubbleSort(arr, n);*/CountSort(arr,n);printf("排序后:");Print(arr, n);}// 测试排序的性能对⽐
void TestOP()
{srand(time(0));const int N = 100000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);int* a7 = (int*)malloc(sizeof(int) * N);int* a8 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];a7[i] = a1[i];a8[i] = a1[i];}int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin3 = clock();SelectSort(a3, N);int end3 = clock();int begin4 = clock();HeapSort(a4, N);int end4 = clock();int begin5 = clock();QuickSort(a5, 0, N - 1);int end5 = clock();int begin6 = clock();MergeSort(a6, N);int end6 = clock();int begin7 = clock();BubbleSort(a7, N);int end7 = clock();int begin8 = clock();CountSort(a8, N);int end8 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);printf("BubbleSort:%d\n", end7 - begin7);printf("CountSort:%d\n", end8 - begin8);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);free(a8);
}int main()
{//TestOP();test();return 0;
}

数据结构初阶的所有内容就更新完了,后面还有一些加餐内容。下面我们正式开启C++和Linux的内容。。。

完—— 

未完待续——

   ———————————————《剧终The End》———————————————

 剧终_TRK_高音质在线试听_剧终歌词|歌曲下载_酷狗音乐

(放学骑车的路上随机播放到了这首歌,感觉挺应景的,就它喽。看到一条评论:比起剧终,我更喜欢未完待续)  

(你相信星座吗,我一开始不相信,后来发现真的有点像,说实话现在也不咋相信,但是这是巧合吗还是,疑惑)

至此结束!

我是云边有个稻草人。。。

期待与你的下一次相遇,再见!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Open WebUI下载的模型文件(Model)默认存放在哪里?

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Ollama部署LLM专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2025年2月21日21点21分 &#x1f004;️文章质量&#xff1a;95分 文章目录 使用CMD安装存放位置 默认存放路径 Open WebUI下…

XSS漏洞学习(1)

XSS漏洞学习&#xff08;1&#xff09; HTTP协议回顾 HTTP的请求方式 常用 GET 请求从服务器获取资源 HEAD 类似于GET请求&#xff0c;只不过不会返回实体数据&#xff0c;只获取报头 POST 向服务器提交数据 PUT 替换服务器的内容 不常用 DELETE 请求服务器删除指定的…

【统计学相关笔记】抽样基本定理的证明

抽样基本定理的证明 法 1 法 2 什么是 辅助统计量&#xff1f; 法 3

基于Asp.net的物流配送管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

vue-treeselect 【单选/多选】的时候只选择最后一层(绑定的值只绑定最后一层)

欢迎访问我的个人博客 &#xff5c;snows_ls BLOGhttp://snows-l.site 一、单选 1、问题&#xff1a; vue-treeselect 单选的时候只选择最后一层&#xff08;绑定的值只绑定最后一层&#xff09; 2、方法 1、只需要加上 :disable-branch-nodes"true" 就行&#xff0…

Python的那些事第四十五篇:继承自Nose的测试框架Nose2

Nose2:继承自Nose的测试框架 摘要 本文深入探讨了Nose2这一继承自Nose的测试框架。在软件开发过程中,测试是确保代码质量和稳定性的重要环节,而测试框架为测试工作的开展提供了有力支持。Nose2作为Nose的继承者,在保留Nose优势的基础上进行了诸多改进和扩展,为Python测试…

LLM后训练:解锁大型语言模型推理能力的关键路径

引言&#xff1a;从语言生成到逻辑推理的跃迁 大型语言模型&#xff08;LLMs&#xff09;通过预训练掌握了海量语言模式&#xff0c;但其核心缺陷——幻觉、逻辑断裂、价值观偏差——暴露了单纯预训练的局限性。后训练&#xff08;Post-Training&#xff09;作为预训练后的精修…

Rabit

之前发过rabit了&#xff0c;所以这里不再赘述&#xff0c;讲讲原理 在线Rabbit加密 | Rabbit解密- 在线工具 (sojson.com) rabbit加密原理 Rabbit加密算法是一种流密码算法&#xff0c;由Daniel J. Bernstein设计&#xff0c;并被广泛用于多种加密和安全通信应用中。它的设…

coding ability 展开第四幕(滑动指针——巩固篇)超详细!!!!

文章目录 前言水果成篮思路 找到字符串中所有字母异位词思路 串联所有单词的子串思路 最小覆盖子串思路 总结 前言 本专栏上一篇博客&#xff0c;带着大家从认识滑动窗口到慢慢熟悉 相信大家对滑动窗口已经有了大概的认识 其实主要就是抓住——一段连续的区间 今天来学习一些滑…

“消失的中断“

“消失的中断” 1. 前言 在嵌入式开发过程中&#xff0c;中断必不可少。道友们想必也经常因为中断问题头疼不已&#xff0c;今天来说说一个很常见的问题&#xff0c;“消失的中断”。最近项目在使用第三方MCAL的时候&#xff0c;就遇到了I2C中断丢失的问题&#xff0c;排查起…

阿里云魔笔低代码应用开发平台快速搭建教程

AI低代码&#xff0c;大模型时代应用开发新范式 什么是魔笔 介绍什么是魔笔低代码应用开发平台。 魔笔是一款面向全端&#xff08;Web、H5、全平台小程序、App&#xff09;场景的模型驱动低代码开发平台&#xff0c;提供一站式的应用全生命周期管理&#xff0c;包括可视化开发…

Obsidian Copilot:打造你的专属 AI 笔记助手

Obsidian Copilot作为一款非常受欢迎的Obsidian插件&#xff0c;不仅极大地提升了用户的笔记管理和信息检索效率&#xff0c;还通过其多样化的AI功能为用户带来了前所未有的便捷体验。本文将详细介绍Obsidian Copilot的核心特点、使用方法及个人体验分享。 核心特点 Obsidian…

聊聊 Redis 的一些有趣的特性(上)

聊聊 Redis 的一些有趣的特性&#xff08;上&#xff09; 一、持久化 Redis 是内存数据库&#xff0c;数据全部保存在内存中。如果服务器发生宕机&#xff0c;内存中的数据将会全部丢失。为防止系统崩溃后数据丢失&#xff0c;Redis 提供了持久化功能&#xff0c;可将内存中的…

【结构设计】3D打印创想三维Ender 3 v2

【结构设计】3D打印创想三维Ender 3 v2 文章目录 前言一、Creality Slicer1.2.3打印参数设置二、配件更换1.捆扎绑扎线2.气动接头3D打印机配件插头3.3D打印机配件Ender3pro/V2喷头套件4.读卡器 TF卡5.micro sd卡 三、调平四、参考文章总结 前言 使用工具&#xff1a; 1.创想三…

吴恩达机器学习笔记复盘(五)均方误差函数

只讲了线性回归的代价函数。 均方误差&#xff08;Mean Squared Error, MSE&#xff09; 均方误差&#xff08;MSE&#xff09;基于最小二乘法&#xff0c;通过计算预测值与真实值之间差值的平方的平均值来衡量模型的误差。 原理 假设我们有一组数据集&#xff0c;其中是第…

Vue生命周期_Vue生命周期钩子

一、生命周期介绍 每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤&#xff0c;比如设置好数据侦听&#xff0c;编译模板&#xff0c;挂载实例到 DOM&#xff0c;以及在数据改变时更新 DOM。 在此过程中&#xff0c;它也会运行被称为生命周期钩子的函数&#xff0c;让…

arthas常用命令

文章目录 1. dashboard仪表板2. 通过thread命令来获取到math-game.jar进程的Main Class3. 通过jad来反编译Main Class4. watch监视5. 退出arthas6. 小结 欢迎关注 性能测试和优化 专栏&#xff1a;https://blog.csdn.net/qq_41684621/category_12910565.html 1. dashboard仪表…

c#Winform也可以跨平台了GTK框架GTKSystem.Windows.Forms

一、简介 >> 新版下载&#xff0c;问题求助 QQ群&#xff1a;1011147488 1032313876 236066073&#xff08;满&#xff09; Visual Studio原生开发&#xff0c;无需学习&#xff0c;一次编译&#xff0c;跨平台运行. C#桌面应用程序跨平台&#xff08;windows、linux、…

Vue3 Pinia的getters属性

Pinia的getters属性 定义一个bigSum&#xff0c;值是sum*10 可以写成箭头函数的形式upperSchool中使用了this&#xff0c;不能写成箭头函数的形式

Atcoder ABC397-D 题解

https://atcoder.jp/contests/abc397/tasks/abc397_dhttps://atcoder.jp/contests/abc397/tasks/abc397_d 题目描述&#xff1a; 确定是否存在一对正整数,使得 思路&#xff1a; 首先对方程进行转化 设 即 接下来确定的范围 根据立方差公式 因此&#xff0c;我们可以从到来…