【数据结构初阶第十九节】八大排序系列(下篇)—[详细动态图解+代码解析]
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 ?!真假的
三、排序算法复杂度及稳定性分析
稳定性

四、两节课代码汇总
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_高音质在线试听_剧终歌词|歌曲下载_酷狗音乐
(放学骑车的路上随机播放到了这首歌,感觉挺应景的,就它喽。看到一条评论:比起剧终,我更喜欢未完待续)
(你相信星座吗,我一开始不相信,后来发现真的有点像,说实话现在也不咋相信,但是这是巧合吗还是,疑惑)
至此结束!
我是云边有个稻草人。。。
期待与你的下一次相遇,再见!
相关文章:
【数据结构初阶第十九节】八大排序系列(下篇)—[详细动态图解+代码解析]
hello,好久不见! 云边有个稻草人-CSDN博客 上篇内容,回顾一下吧【数据结构初阶第十八节】八大排序系列(上篇)—[详细动态图解代码解析]-CSDN博客 今天我们来学习下篇 目录 (2)快速排序 【挖坑法】 —思路 —思路…...
不可不知的分布式数据库-TiDB
不可不知的分布式数据库-TiDB 介绍TiDb架构TiDb与Mysql的区别功能特性性能表现数据可靠性运维管理成本 Docker部署TiDB1. 获取 TiDB 配置文件2. 启动 TiDB 集群3. 连接到 TiDB4. 停止和清理 TiDB 集群注意事项 实用案例TiDB实现分布式事务实现原理实现方式SQL 方式编程方式 注意…...
BUUCTF Pwn babyheap_0ctf_2017 Unsorted bin attack部分
checksec exeinfo 开启了全保护 64位 查看函数: 堆题 增删查改齐了 可以在编辑堆的时候重新设置大小 存在堆溢出 delete函数的指针清零了 无UAF 想法是通过unsorted bin泄露libc基址: from pwn import *p process(./babyheap) #p remote("node…...
AI绘画软件Stable Diffusion详解教程(11):图生图进阶篇(局部用上传蒙版重绘)
总的功能与上一篇相似,但是在Stable Diffusion网页上手工涂绘的方法,有可能会因不够精细,导致重绘的效果不佳,涂绘区与非涂绘区的衔接有可能会出问题。这个时候可以用photoshop来制作蒙版,精确的圈出需要重绘的地方&am…...
SAP的WPS导出找不到路径怎么办;上载报错怎么办
一.打开注册编辑器 二.输入以下地址 计算机\HKEY_CLASSES_ROOT\ExcelWorksheet\Protocol\StdFileEditing\Server 去除掉EXE后面的命令即可 二:WPS上载文件没反应怎么办 如何切换整合模式或多组件模式-WPS学堂 根据官方操作把整合模式改成多组件模式...
Go语言不定长参数使用详解
不定长参数(Variadic Parameters)使用详解 核心概念 语法特性:...T 表示函数可接受任意数量的T类型参数底层实现:不定长参数在函数内部实际存储为切片类型 []T展开操作符:调用时使用 slice... 可将切片展开为独立参数…...
django如何配置使用asgi
以下是 Django 配置使用 ASGI 的完整指南: 一、配置前提 Django 版本:确保使用 Django 3.0(原生支持 ASGI)必要依赖:pip install daphne channels二、基础配置步骤 1. 创建/修改 ASGI 入口文件 在 Django 项目根目录…...
在C语言基础上学Java【Java】【一】
众所周知,Java是C风格的语言,对于学过C语言的人学Java可以快速适应。 废话不多说,直接边看代码边学。 数据类型,输入和输出 public class a1 {//a1是类名,就是文件名,所有的可执行代码需要写在这个里面 /…...
使用 Promise 和 .then() 解决同异步问题
在购物车功能中,用户点击“加入购物车”或“删除购物车”时,可能会遇到数据同步问题。例如,当用户快速连续点击“删除”按钮时,可能会导致删除操作基于过时的数据,从而引发错误。为了解决这个问题,我们可以…...
defineExpose函数
在软件开发中,特别是在像 Vue.js 这样的框架中,defineExpose 是一个函数,用于显式地将组件的某些属性或方法暴露给其父组件或其他组件。这在你想控制组件的内部状态或功能对外部可见性时非常有用。 Vue.js 3 中的示例: <scri…...
LabVIEW烟气速度场实时监测
本项目针对燃煤电站烟气流速实时监测需求,探讨了静电传感器结构与速度场超分辨率重建方法,结合LabVIEW多板卡同步采集与实时处理技术,开发出一个高效的烟气速度场实时监测系统。该系统能够在高温、高尘的复杂工况下稳定运行,提供高…...
台式机电脑组装---电源
台式机电脑组装—电源 22 33 主板供电是聚集了12V,5V,3.3V的24pin CPU供电的话主要是12V的44pin供电 44pin合并之后,就是8pin 55 SATA硬盘会使用饼io口取电,从电源获取12v,5v,3.3v的电 33...
中小型企业大数据平台全栈搭建:Hive+HDFS+YARN+Hue+ZooKeeper+MySQL+Sqoop+Azkaban 保姆级配置指南
目录 背景一、环境规划与依赖准备1. 服务器规划(3节点集群)2. 系统与依赖3. Hadoop生态组件版本与下载路径4. 架构图二、Hadoop(HDFS+YARN)安装与配置1. 下载与解压(所有节点)2. HDFS高可用配置3. YARN资源配置4. 启动Hadoop集群三、MySQL安装与Hive元数据配置…...
2023年蓝桥杯 省赛 ————特殊日期
2.特殊日期 - 蓝桥云课 错误原因: 分不清大小月,将闰年的2月天数当成了28天,非闰年当成了27天,因此出错 错误代码如下: package Lanqiao;import java.util.Scanner;/*** author zb* date2025/3/16 13:22*/ public …...
电动车出入库管理软件,电动车维修保养售后服务管理系统,佳易王电动车店管理系统操作教程
一、概述 本实例以 佳易王电动车店管理系统 为例说明,其他版本可参考本实例。试用版软件资源可到文章最后了解,下载的文件为压缩包文件,请使用免费版的解压工具解压即可试用。 软件特点: 操作便捷性高 软件功能实用且…...
计算机网络-综合布线系统
工作区子系统:由信息插座、插座盒、连接跳线和适配器组成 水平子系统:由一个工作区的信息插座开始,经水平布置到管理区的内测配线架的线缆所组成 管理子系统:由交连、互连配线架组成。管理子系统为连接其它子系统提供连接手段 …...
【蓝桥杯】24省赛:数字串个数
思路 本质是组合数学问题: 9个数字组成10000位数字有9**10000可能 不包括3的可能8**10000 不包括7的可能8**10000 既不包括3也不包括77**10000 根据容斥原理:结果为 9 ∗ ∗ 10000 − 8 ∗ ∗ 10000 − 8 ∗ ∗ 10000 7 ∗ ∗ 10000 9**10000 - 8**10…...
手写一些常见算法
手写一些常见算法 快速排序归并排序Dijkstra自定义排序交替打印0和1冒泡排序插入排序堆排序欧几里得算法求最大公约数 快速排序 public class Main {public static void main(String[] args) {int nums[] {1,3,2,5,4,6,8,7,9};quickSort(nums,0,nums.length - 1);}private st…...
AI自动生成数据
文章目录 概要案例生成简单的文本数据 概要 合成数据是人工生成的数据而不是从现实世界事件中收集的数据。它用于模拟真实数据,而不会泄露隐私或遇到现实世界的限制 安装依赖:pip install langchain_experimental 合成数据的优势: 1.隐私…...
【STM32】从新建一个工程开始:STM32 新建工程的详细步骤
STM32 开发通常使用 Keil MDK、STM32CubeMX、IAR 等工具来创建和管理工程。此处是 使用 Keil MDK5 STM32CubeMX 创建 STM32 工程的详细步骤。 新建的标准库工程文件已上传至资源中,下载后即可直接使用。 标准库新建 STM32 工程的基本目录结构:STD_STM…...
【Go语言圣经3.6】
目标 概念 常量与变量的主要区别在于: 不可变性:常量在声明后其值就固定下来,不能再被修改。这保证了程序运行时不会因意外修改而导致错误。 使用不可变数据(例如数学常数 π)可以避免意外修改带来的问题 编译期计算…...
[IP]UART
UART 是一个简易串口ip,用户及配置接口简单。 波特率从9600至2000000。 该 IP 支持以下特性: 异步串行通信:标准 UART 协议(1 起始位,8 数据位,1 停止位,无奇偶校验)。 参数化配置…...
Windows主机、虚拟机Ubuntu、开发板,三者之间文件互传
以下内容源于日常学习的整理,欢迎交流。 下图是Windows主机、虚拟机Ubuntu、开发者三者之间文件互传的方式示意图: 注意,下面谈及的所有方式,都要求两者的IP地址处于同一网段,涉及到的软件资源见felm。 一、Windows主…...
4.好事多磨 1
前言 我们已经学习了创建套接字和向套接字分配地址,接下来正式讨论通过套接字收发数据。 之前介绍套接字时举例说明了面向连接的套接字和面向消息的套接字这2种数据传输方式,特别是重点讨论了面向连接的套接字。这次将具体讨论这种面向连接的服务器端/客…...
AI预测体彩排3新模型百十个定位预测+胆码预测+杀和尾+杀和值2025年3月18日第22弹
前面由于工作原因停更了很长时间,停更期间很多彩友一直私信我何时恢复发布每日预测,目前手头上的项目已经基本收尾,接下来恢复发布。当然,也有很多朋友一直咨询3D超级助手开发的进度,在这里统一回复下。 由于本人既精…...
相机标定之DLT算法学习
文章目录 1.针孔相机模型2.各个坐标系的定义1)世界坐标系(world coordinate)2)相机坐标系(camera coordinate)3)图像坐标系(film coordinate)4)像素坐标系&am…...
Flask实时监控:打造智能多设备在线离线检测平台(升级版)
前言 武林之中,最讲究的便是“掌控”。若是手下弟子忽然失踪,若是江湖好友生死未卜,岂不令人寝食难安?今日,吾等化身技术侠客,祭出Flask实时监控大法,打造一款智能多设备在线离线检测平台&…...
【计算机网络】一二章
一 二 非常棒的例子 相同的传播时延,带宽越大,该链路上所能容纳的比特数越多 相同的传播时延,带宽越大,该链路上所能容纳的比特数越多 往返时间(Round-Trip Time,RTT)s是指从发送端发送数据分组…...
003-掌控命令行-CLI11-C++开源库108杰
首选的现代C风格命令行参数解析器! (本课程包含两段教学视频。) 以文件对象监控程序为实例,五分钟实现从命令行读入多个监控目标路径;区分两大时机,学习 CLI11 构建与解析参数两大场景下的异常处理;区分三…...
如何针对大Excel做文件读取?
针对大Excel文件(如超过百万行)的读取,传统的一次性加载到内存的方式会导致 内存溢出(OOM),需采用 流式读取(Streaming) 或 分块读取(Chunk) 的策略。以下是具…...
数据链路层协议
目录 一、Mac地址 二、以太网(Mac) 三、MTU 四、ARP协议 一、Mac地址 注意:mac地址是全世界唯一的,而ip地址在不同子网中是可以重复的。 我们在之前说过,Mac地址如果想要进行网络通信,就需要让交换机记…...
【笔记】计算机网络——数据链路层
概述 链路是从一个结点到相邻结点的物理路线,数据链路则是在链路的基础上增加了一些必要的硬件和软件实现 数据链路层位于物理层和网络层之间,它的核心任务是在直接相连的节点(如相邻的交换机,路由器)之间提供可靠且…...
在制作电脑的过程中,如何区分整机性能问题和应用自身性能问题
在制作电脑的过程中,区分整机性能问题和应用自身性能问题非常重要。这两类问题的表现可能相似(如卡顿、响应慢等),但原因和解决方法完全不同。以下是区分和定位问题的方法: 1. 整机性能问题的特征 整机性能问题通常与…...
高光谱相机在水果分类与品质检测中的应用
一、核心应用领域 外部品质检测 表面缺陷识别:通过400-1000nm波段的高光谱成像,可检测苹果表皮损伤、碰伤等细微缺陷,结合图像分割技术实现快速分类。 损伤程度评估:例如青香蕉的碰撞损伤会导致光谱反射率变化&#…...
【零基础入门unity游戏开发 —— 通用篇】层级(Layer)、层级编号、层级二进制掩码和unity层级检测原理
考虑到每个人基础可能不一样,且并不是所有人都有同时做2D、3D开发的需求,所以我把 【零基础入门unity游戏开发】 分为成了C#篇、unity通用篇、unity3D篇、unity2D篇。 【C#篇】:主要讲解C#的基础语法,包括变量、数据类型、运算符、流程控制、面向对象等,适合没有编程基础的…...
9、STL中的multimap使用方法
一、了解 multimap是一个允许键(key)重复的关联容器。适合用于一对多的更新。 允许多个键拥有相同的值。基于红黑树。 multimap特性 键允许重复:允许多个键有相同的值。无 [ ] 运算法:禁止用 下标访问,因为键不唯一。…...
keepalived的工作原理和脑裂
一、Keepalived工作原理 keepalived是一个用于实现高可用和负载均衡的服务,主要基于虚拟路由协议,解决了nginx一台机器的单点故障问题。通过将两台nginx都配置keepalived,让两天nginx互为主机和备机;且keepalived通过 VRRP 协议和…...
k8s资源管理介绍
1.命令式管理常见的命令 资源管理方式 kubectl get nodes查看集群 kubectl get pods 查看所有pod kubectl get pod pod名 -o yaml 以yaml形式查看某个pod kubectl create namespace dev创建一个dev组 Namespace 是 Kubernetes 中用于隔离资源的一种机制。通过 Namespace&a…...
激光slam学习笔记10---ubuntu2004部署运行fastlivo2踩坑记录
背景:mars实验室又发福利啦!跑跑效果,验了那句,mars出品,必属精品!本人pc环境ubuntu20.04,基本流程按照readme走就行,sophus和vikit安装有些注意地方。本文做了一些部署踩坑记录&…...
Windows11 新机开荒(二)电脑优化设置
目录 前言: 一、注册微软账号绑定权益 二、此电脑 桌面图标 三、系统分盘及默认存储位置更改 3.1 系统分盘 3.2 默认存储位置更改 四、精简任务栏 总结: 前言: 本文承接上一篇 新机开荒(一) 上一篇文章地址&…...
一次模拟Windows挖矿病毒应急响应的流程及思路
什么是挖矿病毒? 挖矿病毒并非传统意义上专门用于破坏计算机系统的病毒,它本质是为了获取虚拟货币收益而非法侵占用户计算资源的恶意程序。这些虚拟货币如比特币、以太坊等,其获取过程依赖计算机的算力进行复杂运算,挖矿病毒正是…...
51单片机的寻址方式(完整)
目录 一、立即数寻址 二、直接寻址 三、寄存器寻址 四、寄存器间接寻址 五、变址寻址 六、位寻址 七、指令寻址 (一)绝对寻址 (二)相对寻址 在 51 单片机中,寻址方式是指在执行指令时,CPU 寻找操作…...
深入理解 Linux 的 top 命令:实时监控系统性能
在 Linux 系统管理和性能优化中,top 命令是一个不可或缺的工具。它可以实时显示系统的进程信息和资源使用情况,帮助管理员快速定位性能瓶颈。本文将详细介绍 top 命令的输出内容及其使用方法,帮助你更好地掌握系统性能监控。 一、top 命令简介 top 是一个动态显示系统状态的…...
Excel(函数篇):IF函数、FREQUNCY函数、截取函数、文本处理函数、日期函数、常用函数详解
目录 IF函数等于判断区间判断与AND函数、OR函数一同使用IFNA函数和IFERROR函数 FREQUNCY函数、分断统计LEFT、RIGHT、MID截取函数FIND函数、LEN函数SUBSTITUTE函数ASC函数、WIDECHAR函数实战:如何获取到表中所有工作簿名称文本处理函数TEXT函数TEXTJOIN函数 日期函数…...
基于 Python 爬取 TikTok 搜索数据 Tiktok爬虫(2025.3.17)
1. 前言 在数据分析和网络爬虫的应用场景中,我们经常需要获取社交媒体平台的数据,例如 TikTok。本篇文章介绍如何使用 Python 爬取 TikTok 用户搜索数据,并解析其返回的数据。 结果截图 2. 项目环境准备 在正式运行代码之前,我…...
本专栏开栏通知相关申明
通知 本专栏主要介绍本人C开发过程中遇到的各种技术栈问题,开此栏用于整合自己所学习到的所有知识点,现在无偿分享给大伙。大伙有好的建议或者问题可以在评论直接留言,我不一定有时间看到,但是看到会回复的。 技术栈1 截止到202…...
数据库设计实验(3)—— 分离与附加、还原与备份
一、目的与要求 掌握SQL Server2012拷贝物理文件的方法;掌握SQL Server 2012附加数据库的方法;掌握SQL Server 2012备份和还原的方法;掌握SQL Server 2012定期自动备份的方法。开始简单的SQL查询 二、实验准备 了解数据库分离和附加的意义&…...
Swift 并发中的任务让步(Yielding)和防抖(Debouncing)
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...
hibernate 自动生成数据库表和java类 字段顺序不一致 这导致添加数据库数据时 异常
hibernate 自动生成的数据库表和java类 字段顺序不一致 这导致该书写方式添加数据库数据时 异常 User user new User( null, username, email, phone, passwordEncoder.encode(password) ); return userRepository.save(user);Hibernate 默认不会保证数据库表字段的顺序与 Ja…...
05 MP4解码AAC + 格式知识
AAC⾳频格式ADIF这种格式的特征是可以确定的找到这个⾳频数据的开始,不需进⾏在⾳频数据流中间开始的解码,即它的解码必须在明确定义的开始处进⾏。故这种格式常⽤在磁盘⽂件中 ADTS是AAC⾳频的传输流格式。AAC⾳频格式在MPEG-2(ISO-13318-7 2003)中有定义。AAC后来⼜被采⽤…...