快排/堆排/归并/冒泡/
常见的内排序算法
插入排序
直接插入排序
原理:相当于扑克牌变成有序,先拿第一张,把他调节成有序,再拿第二张,与第一张相比找到第二张的位置,再继续拿第三张,以此类推。
void InsertSort(int* arr, int n)
{for (int i = 1; i < n; i++){int end = i - 1;int tmp = arr[i];while (end >= 0){if (tmp < arr[end]){arr[end + 1] = arr[end];arr[end] = tmp;}else{break;}end--;}}
}//时间复杂度为O(N^2),逆序时间复杂度最坏
由于插入排序在有序的时候时间复杂度为O(N),在逆序时时间复杂度为O(N^2),所以如果我们想加快排序的速度,我们可以先对他进行一个预排序,然后再进行一个插入排序。
希尔排序
原理:间隔为gap的分为一组,假设下图的gap为3,总计gap组
也就是说{3,4,1,11}分为一组,{9,5,6,4}和{31,2,6,4}分为一组,依次往前排序,和插入排序很像,都是前面先排好再排下一个
void ShellSort(int* arr, int n)//先搞一个预排的雏形,gap假设为3
{int gap = 1;for (int k = 0; k < gap; k++){for (int j = k; j < n - gap; j += gap){int end = j;int tmp = arr[end + gap];while (end >= 0){if (tmp < arr[end]){arr[end + gap] = arr[end];end -= gap;}else{break;}}arr[end + gap] = tmp;}}
}
下面就可以确定gap的取值了
void ShellSort(int* arr, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;//这样gap最后一定是1,相当于一个插入排序for (int k = 0; k < gap; k++){for (int j = k; j < n - gap; j += gap){int end = j;int tmp = arr[end + gap];while (end >= 0){if (tmp < arr[end]){arr[end + gap] = arr[end];end -= gap;}else{break;}}arr[end + gap] = tmp;}}}
}
选择排序
选择排序
void SelectSort(int* arr, int n)
{int begin = 0, end = n - 1;while (begin < end){int maxi = begin;int mini = end;for (int i = begin; i <= end; i++){if (arr[i] > arr[maxi]){maxi = i;}if (arr[i] < arr[mini]){mini = i;}}swap(&arr[begin], &arr[mini]);if (begin == maxi){maxi = mini;}swap(&arr[end], &arr[maxi]);begin++;end--;}
}
堆排
typedef struct heap
{int* arr;int size;int capacity;
}heap;
//向下调整
void AdjustDown(int* arr, int begin, int n)
{int father = begin;int child = 2 * father + 1;while (child<n){if (child + 1 < n && arr[child] < arr[child + 1]){child++;}if (arr[father] < arr[child]){swap(&(arr[father]), &(arr[child]));father = child;child = 2 * father + 1;}else{break;}}
}
//向上调整
void AdjustUp(int* arr, int n, int end)
{int child = end - 1;while (child > 0){if (child + 1 < n && arr[child] < arr[child + 1]){child++;}int father = (child - 1) / 2;if (arr[child] > arr[father]){swap(&(arr[child]), &(arr[father]));}child = father;}
}
//堆初始化
void HeapInit(heap* obj)
{assert(obj);obj->arr = (int*)malloc(sizeof(int) * 4);if (obj->arr == NULL){perror("malloc fail");return;}obj->capacity = 4;obj->size = 0;
}//堆插入
void HeapPush(heap* obj, int val)
{assert(obj);if (obj->size == obj->capacity){int* tmp = (int*)realloc(obj->arr, obj->capacity * 2 * sizeof(int));if (tmp == NULL){perror("malloc fail");return;}obj->arr = tmp;obj->capacity *= 2;}obj->arr[obj->size] = val;obj->size++;AdjustUp(obj->arr, 0, obj->size);
}//堆排序
void HeapSort(int* arr, int n)
{//建大堆for (int i = 0; i < n; i++){AdjustUp(arr, n, i + 1);}for (int i = n - 1; i >= 0; i--){swap(&arr[0], &arr[i]);AdjustDown(arr, 0, i);}
}
交换排序
冒泡排序
void BubbleSort(int* arr, int n)
{for (int i = 0; i < n; i++){bool flag = true;for (int j = 0; j < n - i - 1; j++){if (arr[j] > arr[j + 1]){swap(&arr[j], &arr[j + 1]);flag = false;}}if (flag)break;}
}
由于希尔排序的预排序是一个变化的过程,所以希尔排序的时间复杂度极其复杂,我们记住一个结论,希尔排序的时间复杂度约为O(N^1.3),要注意的是,希尔排序在最后一次循环中gap必须为1
快速排序
霍尔排序
霍尔排序以数组中某一个数作为基准值,按照该排序把待排序集合分为两部分,这个数左边的值都比这个数小,这个数右边的值都比这个数的大,再用递归重复此过程,设置一个left指针,一个right指针,left指针从0位置开始,right指针从n-1的位置开始,left指针遇到比中间值key大的与right指针遇到比中间值key小的位置交换
int HoareSortPart(int* arr, int begin,int end)
{int left = begin+1, right = end, key = begin;while (left < right){while (left < right && arr[right] >= arr[key]){right--;}while (left < right && arr[left] <= arr[key]){left++;}swap(&arr[left], &arr[right]);}swap(&arr[key], &arr[left]);return left;
}//快速排序 Hoare版本
void HoareSort(int* arr, int begin,int end)
{if (begin >= end){return;}int mid = HoareSortPart(arr, begin, end);HoareSort(arr, begin, mid - 1);HoareSort(arr, mid + 1, end);
}
关于为什么要让right指针先走,归根结底是为了让left指针和right指针相遇的时候,得到的位置所在的值比中间值key要小,我们可以把left指针与right指针相遇分为两种情况,一种是left遇到right指针,另一种是right指针遇到left指针
一.left遇到right指针,因为一个循环是right先走,所以right指针已经遇到了比key小的值,并且还没有交换,所以left遇到right时遇到的就是比key小的数。
二.right指针遇到left指针,因为right指针在走,也就是上一个循环里的left指针已经走完了,并且已经交换了数字,所以left位置的值应该是小于或者等于key的,right再遇到left遇到的就是比key小的数,所以综上所述,无论是left遇到right还是right遇到left,最终得到的数都是小于key或者等于key的。
挖坑法
左右交替选择数,左边left指针选出比key大的值,右边right选出比key小的值,覆盖原来的坑,直到left指针与right指针相遇,再把key放入最后left和right相遇的坑
int HoleSortPart(int* arr, int begin, int end)
{int key = arr[begin];int left = begin, right = end;int hole = begin;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 HoleSort(int* arr, int begin, int end)
{if (begin >= end){return;}int mid = HoleSortPart(arr, begin, end);HoleSort(arr, mid + 1, end);HoleSort(arr, begin, mid - 1);
}
双指针法
cur找小,prev前面的数都比key小,翻滚的往后走
int QuickSortPart(int* arr, int begin, int end)
{int prev = begin, cur = begin + 1;int key = arr[begin];while (cur <= end){if (arr[cur] < key){++prev;swap(&arr[cur], &arr[prev]);}cur++;}swap(&arr[begin], &arr[prev]);return prev;
}void QuickSort(int* arr, int begin, int end)
{if (begin >= end){return;}int mid = QuickSortPart(arr, begin, end);QuickSort(arr, begin, mid - 1);QuickSort(arr, mid+1, end);
}
快排的劣势
快排若每次都取左边的那个数作为中间值时,如果数组有序,快排的时间复杂度会达到O(N^2),而若每次选取到的是数组的中位数的时候效率是最高的,为了改变这一劣势,我们引入三数取中算法。
三数取中算法
int GetMidIndex(int* arr, int left, int right)
{int mid = (left + right) / 2;if (arr[left] > arr[right]){if (arr[mid] >= arr[left])return left;else if (arr[mid] <= arr[right])return right;elsereturn mid;}else//arr[left]<=arr[right]{if (arr[mid] >= arr[right])return right;else if (arr[mid] <= arr[left])return left;elsereturn mid;}
}
三数取中后的三种快排算法如下,记得要取完值后和begin位置的值互换
int HoareSortPart(int* arr, int begin,int end)
{int left = begin, right = end;int tmp = GetMidIndex(arr, begin, end);swap(&arr[tmp], &arr[begin]);int key = begin;while (left < right){while (left < right && arr[right] >= arr[key]){right--;}while (left < right && arr[left] <= arr[key]){left++;}swap(&arr[left], &arr[right]);}swap(&arr[key], &arr[left]);return left;
}//快速排序 Hoare版本
void HoareSort(int* arr, int begin,int end)
{if (begin >= end){return;}int mid = HoareSortPart(arr, begin, end);HoareSort(arr, begin, mid - 1);HoareSort(arr, mid + 1, end);
}//快速排序 挖坑法版本
int HoleSortPart(int* arr, int begin, int end)
{int tmp = GetMidIndex(arr, begin, end);swap(&arr[tmp], &arr[begin]);int key = arr[begin];int left = begin, right = end;int hole = begin;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 HoleSort(int* arr, int begin, int end)
{if (begin >= end){return;}int mid = HoleSortPart(arr, begin, end);HoleSort(arr, mid + 1, end);HoleSort(arr, begin, mid - 1);
}int QuickSortPart(int* arr, int begin, int end)
{int tmp = GetMidIndex(arr, begin, end);swap(&arr[tmp], &arr[begin]);int prev = begin, cur = begin + 1;int key = arr[begin];while (cur <= end){if (arr[cur] < key){++prev;swap(&arr[cur], &arr[prev]);}cur++;}swap(&arr[begin], &arr[prev]);return prev;
}void QuickSort(int* arr, int begin, int end)
{if (begin >= end){return;}int mid = QuickSortPart(arr, begin, end);QuickSort(arr, begin, mid - 1);QuickSort(arr, mid+1, end);
}
https://leetcode.cn/problems/sort-an-array/
上面那个链接可以用来测排序的算法正不正确,如果你用我上面的代码去这个链接测的话,你会发现有一个数量庞大的都是同一个数字的数组跑不过去,时间复杂度太高了,三数取中可以解决数组有序的问题,但无法解决数组都是同一个数字的问题,所以我、我们还要对此进行改进,我们上面主要是用两路划分,因为我们只分了大于大于key和小于大于key两个部分,我们现在要采取的方法称作三路划分,也就是分为三部分左边那一部分是小于key,中间那部分是等于key的部分,右边那部分是大于key的部分,通过这种方法我们就可以很快的通过全是同一个数的样例,但不建议用递归,因为要传回来两个数,可能会用到数组传参
void ThreeRoadQuickSort(int* arr, int begin, int end)
{if (begin >= end)return;int cur = begin + 1, left = begin, right = end;int tmp = GetMidIndex(arr, begin, end);int key = arr[tmp];while (cur <= right){if (arr[cur] < key){swap(&arr[left], &arr[cur]);left++;}else if (arr[cur] > key){swap(&arr[right], &arr[cur]);right--;}else{cur++;}}ThreeRoadQuickSort(arr, begin, left - 1);ThreeRoadQuickSort(arr, right + 1, end);
}
快排的非递归形式
快排还存在一个风险,如果数字太多,递归层次太深,会有栈溢出的风险,所以我们还是要研究一下快排的非递归的形式
void QuickSortNoR(int* arr, int begin, int end)//1 9
{stack st;InitStack(&st);PushStack(&st, end);PushStack(&st, begin);while (!isemptyStack(&st)){int first = TopStack(&st);PopStack(&st);int last = TopStack(&st);PopStack(&st);int mid = HoareSortPart(arr, first, last);//三种快排part选哪一个都可以if (mid - 1 > first){PushStack(&st, mid - 1);PushStack(&st, first);}if (last > mid + 1){PushStack(&st, last);PushStack(&st, mid+1);}}
}
但大家拿上面那个代码去测试的时候会发现时间复杂度还是超时了,在这里把三数取中改成随机数即可
归并排序
归并排序
归并排序是将已经有序的子序列合并,也就是先让子序列间有序,再让子序列段间有序,最后将两个有序表合成一个有序表,称为二路归并。
归并排序递归版本
//归并排序 递归版本
void MergeSortPart(int* arr, int begin, int end,int* tmp)
{if (begin == end)//不会存在不存在的区间,所以不需要大于等于return;int mid = (begin + end) / 2;MergeSortPart(arr, begin, mid, tmp);MergeSortPart(arr, mid + 1, end, tmp);int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] < arr[begin2]){tmp[i++] = arr[begin1++];}else{tmp[i++] = arr[begin2++];}}while (begin1 <= end1){tmp[i++] = arr[begin1++];}while (begin2 <= end2){tmp[i++] = arr[begin2++];}memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
void MergeSort(int* arr, int begin, int end)
{if (begin >= end)return;int i = 0;int* tmp = (int*)malloc(sizeof(int) * (end - begin + 1));MergeSortPart(arr, begin, end, tmp);free(tmp);
}//时间复杂度为O(N*logN),空间复杂度为O(N)
归并有一个缺点,比如说我们要分1w个数,分为1250只需要三次,而剩下最后十个要递归要分四次,所以我们可以在这个地方用一个优化,称为小区间优化
void MergeSortPart2(int* arr, int begin, int end, int* tmp)
{if (begin == end)//不会存在不存在的区间,所以不需要大于等于return;if (end - begin + 1 < 10){InsertSort(arr + begin, end - begin + 1);//最好选插入排序而不是冒泡return;}int mid = (begin + end) / 2;MergeSortPart(arr, begin, mid, tmp);MergeSortPart(arr, mid + 1, end, tmp);int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] < arr[begin2]){tmp[i++] = arr[begin1++];}else{tmp[i++] = arr[begin2++];}}while (begin1 <= end1){tmp[i++] = arr[begin1++];}while (begin2 <= end2){tmp[i++] = arr[begin2++];}memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
上图就是对归并的part的优化,假设把归并排序的调用看做一个二叉树,设这棵树的递归调用次数为2^h-1,而最后一层的递归调用次数就有2 ^(h-1)次,基本上占了调用次数的一半,而倒二层调用2 ^(h-2)次递归调用,占总的递归调用次数的25%,第三层为12.5%,这样的三层最后一层调用下来所要占的递归调用次数达到了87.5%,如果继续扩大数据量去调用其他的排序已经意义不大了
归并排序的非递归版本
归并排序的非递归版本比递归版本复杂很多,是要先选一个一个数,再两组进行对比,再选两个两个数…四个四个数…以此类推,然后再继续两组进行对比,但边界情况的考虑会相对比较麻烦,只有2的次幂才能不考虑边界,如果数组数不是2的次幂则要进行修正,分别有三种情况,我们称第一组的开头和结尾为begin1和end1,第二组为begin2和end2,第一种情况是end1,begin2和end2都越界,第二种情况是begin2和end2越界,第三种情况是end2越界,对于第一种和第二种情况,因为第二组都是完全越界,我们只需要把第一组数据保留拷贝回去即可,所以下面对第二组数据的begin2和end2进行处理,使其无法进入第一个while循环和第三个while循环,第三种情况我们只需要对end2进行修正,因为归并排序是不需要对比的两组数据个数一样的,所以我们可以直接让end2=n-1,即可正常归并
void MergeSortNoR(int* arr, int begin, int end)
{int gap = 1;int n = end - begin + 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;int j = i;int sz = end2 - begin1 + 1;if (end1 >= n||begin2>=n)//对边界进行修正{end1 = n - 1;sz = end1 - begin1 + 1;begin2 = end2 + 1;}else if (end2 >= n){end2 = n - 1;sz = end2 - begin1 + 1;}while (begin1 <= end1 && begin2 <= end2){if (arr[begin1] > arr[begin2]){tmp[j++] = arr[begin2++];}else{tmp[j++] = arr[begin1++];}}while (begin1 <= end1){tmp[j++] = arr[begin1++];}while (begin2 <= end2){tmp[j++] = arr[begin2++];}memcpy(arr + i, tmp + i, sizeof(int) * sz);//归并一组,拷贝一组,这种方法可以用整体拷贝}gap *= 2;}free(tmp);
}
非比较排序 计数排序
//计数排序
void CountSort(int* arr, int n)
{int mintmp = arr[0], maxtmp = arr[0];for (int i = 0; i < n; i++){if (arr[i] < mintmp){mintmp = arr[i];}if (arr[i] > maxtmp){maxtmp = arr[i];}}int range = maxtmp - mintmp + 1;int* tmp = (int*)malloc(sizeof(int) * range);if (tmp == NULL){perror("malloc fail");return;}for (int i = 0; i < range; i++){tmp[i] = 0;}for (int i = 0; i < n; i++){tmp[arr[i]-mintmp]++;}int j = 0;for (int i = 0; i < range; i++){while (tmp[i]--){arr[j++] = i + mintmp;}}
}
这个排序的时间复杂度为O(N+range),当range很小的时候,它会很快,但range很大的时候就不一样了,这个排序有两个缺陷,一是这个排序依赖数据范围,二是只能用于整型
稳定性
最后讨论一下排序的稳定性,若有两个数,tmp1和tmp2,且这两个数相等,若排序之前tmp1就在tmp2前,排序后相对位置也不改变,这个排序的稳定性就好。
直接插入排序,冒泡排序,归并排序是稳定的排序。
希尔排序,选择排序(选数稳定,交换时不稳定),堆排序,快速排序是不稳定的排序。
内排序结语
上面所说的全部属于内排序,内排序和外排序最大的区别就是数据量,内排序的数据量较小,可以放在内存中直接排序,而外排序的数据量大,内存装不下,所以要放在磁盘里排序,所以我们接下来将介绍用归并排序对文件里的数据进行排序
外排序
归并排序既可以用作内排序,假设我们将要把40个G的数据进行排序,但内存只有1G,我们就可以把这个40G的大文件分为40个1G的小文件,然后两两排序,合成一个个2G的文件,以此类推,我们在对小文件排序的时候,要使用快排不能用归并,因为一个内存只有1G的空间的情况下,我们用归并会耗费更多的内存,下面是文件排序的代码,里面的n是可以修改的,决定你一个小文件可以放多少个数字
void _FileMergeSort(char* f1, char* f2, char* mf)
{int a1, a2;FILE* File1 = fopen(f1, "r");if (File1 == NULL){printf("open fail");exit(-1);}FILE* File2 = fopen(f2, "r");if (File2 == NULL){printf("open fail");exit(-1);}FILE* mFile = fopen(mf, "w");if (mFile == NULL){printf("open fail");exit(-1);}int flag1 = fscanf(File1, "%d ", &a1);int flag2 = fscanf(File2, "%d ", &a2);while (flag1 != EOF && flag2 != EOF){if (a1 > a2){fprintf(mFile, "%d ", a2);flag2 = fscanf(File2, "%d ", &a2);}else{fprintf(mFile, "%d ", a1);flag1 = fscanf(File1, "%d ", &a1);}}while (flag1 != EOF){fprintf(mFile, "%d ", a1);flag1 = fscanf(File1, "%d ", &a1);}while (flag2 != EOF){fprintf(mFile, "%d ", a2);flag2 = fscanf(File2, "%d ", &a2);}fclose(File1);fclose(File2);fclose(mFile);
}void FileMergeSort()
{FILE* fp;int a = 0;int n = 10;int arr[10];char filename[20];fp = fopen("Sort.txt", "r");int i = 0;int filenames = 0;while (fscanf(fp, "%d ", &a) != EOF){if (i < n - 1)//8{arr[i++] = a;}else{arr[i] = a;QuickSort(arr, 0, sizeof(arr) / sizeof(int) - 1);sprintf(filename, "Sort_%d.txt", filenames++);FILE* tmp = fopen(filename, "w");if (tmp == NULL){printf("error");exit(-1);}for (int j = 0; j < n; j++){fprintf(tmp, "%d ", arr[j]);}i = 0;fclose(tmp);}}//文件归并char mfile[100], file1[100], file2[100];sprintf(file1, "Sort_0.txt");sprintf(mfile, "Sort_sum.txt");for (int i = 1; i < n; i++){sprintf(file2, "Sort_%d.txt", i);_FileMergeSort(file1, file2, mfile);sprintf(file1, mfile);sprintf(mfile, "%d.txt", i);}fclose(fp);
}
相关文章:

快排/堆排/归并/冒泡/
常见的内排序算法 插入排序 直接插入排序 原理:相当于扑克牌变成有序,先拿第一张,把他调节成有序,再拿第二张,与第一张相比找到第二张的位置,再继续拿第三张,以此类推。 void InsertSort(in…...

React基础教程(08):state体验
文章目录 7、state再体验7.1 异步更新状态7.2 同步更新状态方式17.3 同步更新状态方式27.4 betterScroll7.5 列表案例7、state再体验 7.1 异步更新状态 完整代码 import React from "react";export default class App extends React.Component{state = {count:1,}…...

Win10 创建新的桌面2,并实现桌面切换
1. Win10 创建新的桌面2 Win - Tab 2. Win10 桌面切换 Ctrl - Win - ←/→ 我们下期见,拜拜!...

MySQL数据库介绍及基础操作
目录: 一.数据库介绍 二.数据库分类 三. 数据库的操作 四. 常用数据类型 五. 表的操作 一.数据库介绍 1.文件保存数据有以下几个缺点: 1.1文件的安全性问题 1.2文件不利于数据查询和管理 1.3文件不利于存储海量数据 1.4文件在程序中控制不方便 为了解决上述问题&…...

【C语言篇】C语言常考及易错题整理DAY2
文章目录 C语言常考及易错题整理选择题编程题至少是其他数字两倍的最大数两个数组的交集图片整理寻找数组的中心下标多数元素除自身以外数组的乘积不使用加减乘除求两个数的加法 C语言常考及易错题整理 选择题 下列 for 循环的次数为( ) for(int i 0…...

javase入门
最近在学习大数据,学到flume拦截器的时候发现自定义拦截器需要使用java编写,现在开始学一些java入门的东西. 一. java相关组成 path环境变量: 环境变量用于记住程序路径,方便在命令行窗口任意目录启动程序. 二 java中的变量 变量要先定义在使用. int age 15 定义变量要定义其…...

Wireshark显示过滤器大全:快速定位网络流量中的关键数据包
文章目录 一、简介二、wireshark中的逻辑运算符三、过滤示例集合3.1 过滤指定日期和时间3.2 过滤指定协议3.2.1 例:仅显示SMTP(端口 25)和ICMP流量:3.2.2 例如:Windows 客户端 - DC 交换 3.3 过滤指定网段(…...

OOP笔记4----抽象类、接口、枚举
抽象类 简介 父类可以封装不同子类的共同特征或者共同行为.而有的时候,父类中封装的方法无法具体完成子类中需要的逻辑,因此我们可以将此方法设计成抽象方法,即使用关键字abstract进行修饰。而有抽象方法的类,也必须使用abstract…...

MySQL面试题全解析:准备面试所需的关键知识点和实战经验
MySQL有哪几种数据存储引擎?有什么区别? MySQL支持多种数据存储引擎,其中最常见的是MyISAM和InnoDB引擎。可以通过使用"show engines"命令查看MySQL支持的存储引擎。 存储方式:MyISAM引擎将数据和索引分别存储在两个不…...

01_Electron 跨平台桌面应用开发介绍
Electron 跨平台桌面应用开发介绍 一、Electron 的介绍二、关于 NW.js 和 Electron 介绍三、搭建 Electron 的环境1、准备工作:2、安装 electron 环境3、查看 electron 的版本,electron -v 一、Electron 的介绍 Electron 是由 Github 开发的一个跨平台的…...

【C语言-扫雷游戏】mineweeper【未完成】
编程小白如何成为大神?大学新生的最佳入门攻略 编程已成为当代大学生的必备技能,但面对众多编程语言和学习资源,新生们常常感到迷茫。如何选择适合自己的编程语言?如何制定有效的学习计划?如何避免常见的学习陷阱&…...

psychopy stroop 实验设计
斯特鲁stroop实验就是色词一致/不一致实验。 设计步骤如下: 1. 先去设置中将Input改为PsychToolbox, 2. 然后左上角File-New新建一个 3. 右键trial,rename改名 改成自己想要的名字即可,比如欢迎界面welcome。 4. 接下来添加提示语…...

c++精品小游戏(无错畅玩版)
一、俄罗斯方块 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <windows.h>#ifdef _MSC_VER // M$的编译器要给予特殊照顾 #if _MSC_VER < 1200 // VC6及以下版本 #err…...

应急响应-主机安全之系统及进程排查相关命令(Linux操作系统-初级篇)
目录 概述lscpu-显示有关CPU架构的信息uname-查看系统信息lsmod-输出加载的所有模块lastb-输出最后登录失败的用户last-展示用户最近登录信息lastlog-展示所有用户最后的登录时间systemctl-系统服务,开机自启排查crontab-计划任务选项 history-查看历史命令选项常用…...

java中RSA分段加解密及Data must not be longer than异常处理
谈到RSA非对称加密,作为开发的我们第一想到的是安全,几乎不会被破解,以及公钥加密,私钥解密这些。在Java代码中,我们常使用一些现成的工具类如hutool中提供的工具类、网上在线的或者博客上的RSAUtils工具类来实现公钥私…...

MySQL数据分析进阶(十二)设计数据库——PART3
※食用指南:文章内容为‘CodeWithMosh’SQL进阶教程系列学习笔记,笔记整理比较粗糙,主要目的自存为主,记录完整的学习过程。(图片超级多,慎看!) 【中字】SQL进阶教程 | 史上最易懂S…...

Kubernetes-1.22.0 可视化部署
目录 Kubeadm方式部署3master,2work集群(Kubernetes-1.22.0)-CSDN博客 1. 官方Dashboard 2. Kuboard 部署 3. Rainbond 部署 4. Kubesphere 部署 1. 官方Dashboard kubectl apply -f https://kuboard.cn/install-script/k8s-dashboard/v2…...

在 vue3 中动态路由问题记录
第一种 如果这样子的话需要加上 /* vite-ignore / ,但是在这样用这行部署服务器上跳转会有问题 component: () > import(/ vite-ignore */ ../views/ e.component .vue) 第二种 // 解决跳转问题const modeules imporet.meta.glob(/views/**/**.vue)component: modules…...

进程编程及其函数的使用
1. 创建进程 创建进程的核心操作是使用 fork() 系统调用。 1.1 fork() 系统调用 fork() 创建一个新进程(子进程),新进程几乎是父进程的完整拷贝。fork() 返回两次: 在父进程中,返回子进程的 PID。在子进程中&#…...

为什么funnel图在邮件中不显示
在电子邮件中嵌入的Funnel图或其他图表可能不显示的原因有以下几种: 1. 邮件客户端对外部内容的限制 大多数邮件客户端为了安全,会阻止从外部服务器加载的内容,如图片、脚本或嵌入式图表。Funnel图通常是通过链接或外部脚本生成的ÿ…...

C语言 ——— 写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串
目录 题目要求 代码思路 代码实现 题目要求 写一个函数,判断一个字符串是否为另外一个字符串旋转之后的字符串 例如 s1 "AABCD" ;s2 "BCDAA" ,返回1 s1 "AABcd" ;s2 "BCDAA" …...

白骑士的Matlab教学实战项目篇 4.4 机器学习与AI
系列目录 上一篇:白骑士的Matlab教学实战项目篇 4.3 控制系统设计 机器学习与人工智能(AI)是当前技术发展的前沿领域,通过数据驱动的模型和算法,可以解决许多复杂的问题。MATLAB 提供了丰富的工具和函数,支…...

事件监控模块——Channel模块
这个模块就是 记录文件描述符 和 想要监控的事件,实际就绪的事件,以及事件发生之后要怎么做,判断有没有监控这个事件,获取事件。 class Poller; class EventLoop; class Channel {private:int _fd;EventLoop *_loop;uint32_t _ev…...

OCR调研
OCR调研 一、介绍 OCR(Optical Character Recognition,光学字符识别)是一种将图像中的文字转换为计算机可处理格式的技术。OCR技术经历了从传统OCR到基于深度学习的OCR的转变。深度学习OCR技术通过模拟人脑神经元结构处理文本和图像数据&am…...

数据结构(学习版)
考纲 (一)数据结构部分; 线性表栈、队列、数组查找和内部排序树和图 (二)计算机算法设计部分: 递归与分省策路、回溯法贪心算法、分支限界法、动态规划算法设计中的数据结构运用 (三)程序设计基础(C或C)部分: 基本数据类型、各种运算符和表达式、基本控制结构。数组的定义…...

除了知云文献翻译外,这几款翻译工具值得推荐!
近年来,市面上涌现出众多优秀的文献翻译工具,其中知云文献翻译凭借其强大的功能受到了广泛好评。然而,除了知云文献翻译外,还有几款翻译工具同样值得推荐。今天,就让我们一起来了解一下! Foxit在线翻译 链…...

Element UI动态实现面包屑导航~
思路:监听路由变化,在路由规则中添加meta然后在组件中渲染。 import Vue from "vue" import VueRouter from "vue-router" Vue.use(VueRouter) // 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题 const origin…...

安科瑞Acrel-2000ES储能能量管理系统在新型电力系统下分布式储能的研究
摘要:传统电力系统的结构和运行模式在以新能源为主体的新型电力系统中发生了巨大的变化,分布式储能作为电力系统中重要的能量调节器,也迎来了新的发展机遇。立足于储能技术发展现状,分析了分布式储能技术特点及在清洁可再生能源方…...

Git 逆转时光:版本回退操作详解
git 版本回退操作详解 一、Git的工作流程二、git clean尚未 commit 的修改三、已经 commit 尚未 push 到 remote 仓库四、已经提交到 remote 仓库五、回退建议六、总结 一、Git的工作流程 在讲这个版本回退之前,我们要温习一下Git的原理。下面这张图就是 Git 的整个…...

8.6.数据库基础技术-数据库的控制
并非控制 事务:由一系列DML操作组成,这些操作,要么全做,要么全不做,它从第一个DML操作开始,rollback、commit或者DDL结束,拥有以下四种特性,详解如下: (操作)…...