【数据结构】常见八大排序算法总结

news/2024/2/25 20:49:10/文章来源:https://blog.csdn.net/m0_64538862/article/details/135534172

目录

前言

1.直接插入排序

2.希尔排序

3.选择排序

4.堆排序

5.冒泡排序

6.快速排序

6.1Hoare版本

6.2挖坑法

6.3前后指针法

6.4快速排序的递归实现 

6.5快速排序的非递归实现

7.归并排序

8.计数排序(非比较排序)

9.补充:基数排序

10.总结:排序算法的复杂度及稳定性分析


前言

排序 :排序就是使一串记录按照其中某个或某些关键字的大小,递增或者递减的排列起来的操作

内部排序:数据元素全部存放在内存中的排序

外部排序:数据元素太多而不能同时放在内存中,根据排序过程的要求不断在内外存之间移动数据的排序

常见的排序算法:

以上排序算法都是比较排序,还有计数排序这类非比较排序算法,一下我们对各个排序算法进行代码实现

1.直接插入排序

直接插入排序是一种简单的插入排序算法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列

过程:当插入第i(i>=1)个元素时,前面的array[0],...,array[i-1]已经有序,此时用array[i]的排序码与array[i-1],array[i-2],...的排序码依次比较,找到插入位置后将原来位置上的元素顺序后移,将array[i]插入

📖Note:

对于数组中的第一个数据,不需要进行比较,因此第一步操作的是a[1]处的数据,区间[0,0]上的数据即a[0]这一个数据是有序的,因此外层循环只需要对n-1次,对a[1]到a[n-1]共n-1个数据进行处理

对于要处理的a[i],依次与a[i-1],a[i-2]比较,如果大于a[i]则交换(升序排列的情况)

优化:备份i处的数据,依次与a[i-1],a[i-2]比较,大于a[i]则向后移动一个位置,否则在小于a[i]的数据元素的后一个位置插入a[i]

时间复杂度与空间复杂度:

插入排序是在存放原数据的数组上进行操作,所以直接插入排序算法的空间复杂度是O(1)

1️⃣当原数据的序列是逆序时,为最坏情况,此时直接插入排序算法的时间复杂度是O(N^2)

如上图,序列逆序时,数据的挪动次数为1+2+3+...+n-1 = n(n-1)/2

所以时间复杂度为O(N^2)

2️⃣当原数据的序列有序时,为最好情况,此时直接插入排序算法的时间复杂度是O(N)

如上图:序列顺序排列时,总共进行了n-1次比较,没有数据的挪动

因此时间复杂度为O(N)

总结:元素集合越接近有序,直接插入排序算法的时间效率越高

//直接插入排序
void InsertSort(int* a, int n)
{for (int i = 0; i < n - 1; ++i){// [0,end]有序,end+1处的数据找到正确位置后,[0, end+1]有序int end = i;int tmp = a[end + 1];while (end >= 0){//升序排列if (a[end] > tmp){a[end + 1] = a[end];--end;}else{break;}}//此时,a[end]<=tmpa[end + 1] = tmp;}
}

2.希尔排序

希尔排序又称为缩小增量排序,希尔排序的基本思想:先选定一个整数gap,把待排序文件中的所有记录分成n/gap个组,每一组内的记录进行排序,然后更新(缩小)gap,重复上述分组和排序的操作,当gap=1时,所有记录在同一组内排序,即使所有记录有序

以下以初始增量为3为例

第一次分组如下图

每一组内的记录进行排序,使用直接插入排序算法

缩小gap=1,即对序列:5 1 2 5 6 3 8 7 4 9进行排序

每一组记录使用直接插入排序算法,当gap不为1时,每组记录的数据元素并不是连续排列的,而是间隔gap,因此需要对直接插入排序算法进行改造

for (int i = 0; i < n - gap; ++i)
{int end = i;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;
}

优化:for循环调整部分为i++时,每次直接插入排序排一组记录,当改为i+=gap时,可以实现多组记录同时排序

📖Note:

希尔排序是对直接插入排序的优化,当gap>1时都是预排序,目的是使数据集合接近有序,当数据集合接近有序时,直接插入排序的时间效率较高

gap的选择:

gap的取法有多种,最初Shell提出取gap = n/2,gap = gap/2,直到gap = 1;后来Knuth提出取gap = gap/3 + 1。我们采用Knuth提出的方式取值。

gap越大,大数可以越快的跳到后面;gap越小,跳的越慢,但数据集合越接近有序

时间复杂度和空间复杂度:

希尔排序算法不额外开辟空间,其空间复杂度为O(1)

对希尔排序的时间复杂度分析很困难,在特定情况下可以准确估算关键码的比较次数和对象移动次数,但想要弄清楚关键码的比较次数和对象移动次数与增量选择之间的依赖关系,目前还没有较完整的数学分析,Knuth在《计算机程序设计技巧》中的结论是:在n很大时,关键码的平均比较次数和对象平均移动次数大约在n^1.25到1.6*n^1.25范围内,这是在利用直接插入排序作为子序列排序方法的情况下得到的。

//希尔排序
void ShellSort(int* a, int n)
{int gap = n;while (gap > 1){gap = gap / 3 + 1;//更新增量//for (int i = 0; i < n - gap; ++i)for (int i = 0; i < n - gap; i += gap){int end = i;int tmp = a[end + gap];while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

3.选择排序

选择排序的基本思想:每一次从待排的数据元素中选出最小或最大的一个元素,存放在序列的起始位置,直到所有待排序的数据元素排完

直接选择排序的步骤

1️⃣在元素集合array[i]到array[n-1]中选择关键码最大(小)的数据元素

2️⃣若它不是这组元素中的最后一个或第一个元素,则将它与这组元素中的最后一个或第一个元素交换

3️⃣在剩余的array[i]到array[n-2](array[i+1]到array[n-1])集合中,重复上述步骤,直到集合剩余一个元素

简单来说直接选择排序将数据集合分成两部分,有序部分和无序部分

以排升序为例,每次选取待排数据集合即无序部分中的最大数放到无序部分的第一个位置即有序部分之后的第一个位置,就完成了一个数据元素的排序

优化:选择元素时选取最大元素和最小元素的操作同时进行,一趟比较选出最大的元素放在a[end]位置,选出最小的元素放在a[begin]位置,begin++,end--,重复上述操作

优化之后数组的两端有序部分,中间为无序部分

时间复杂度和空间复杂度:

直接选择排序算法不额外开辟空间,其空间复杂度为O(1)

1️⃣当原数据的序列是逆序时,为最坏情况,此时选择排序算法的时间复杂度是O(N^2)

遍历待排数据元素集合,共n个数据,选出最大值和最小值,需要比较n-1次

遍历待排数据元素集合,共n-2个数据,选出最大值和最小值,需要比较n-3次

综上所述,当原序列的数据元素逆序时,总共比较的次数为

(n-1)+(n-3)+...+1 = (n/2) *n  / 2

所以直接选择排序的时间复杂度为O(N^2)

2️⃣当原数据的序列有序时,为最好情况,此时直接插入排序算法的时间复杂度是O(N^2)

对于直接选择排序算法来说,逆序和顺序的时间复杂度相同,因为进行数据选择的操作是相同的,都是进行遍历选数,因此效率不高】

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
//选择排序
void SelectSort(int* a, int n)
{int begin = 0, end = n - 1;while (begin < end){// 选出最小的放begin位置// 选出最大的放end位置int mini = begin, maxi = begin;for (int i = begin + 1; i <= end; ++i){if (a[i] > a[maxi]){maxi = i;}if (a[i] < a[mini]){mini = i;}}Swap(&a[begin], &a[mini]);// 修正maxi:特殊情况begin和maxi重叠时,执行一次交换,maxi记录的是最小值if (maxi == begin)maxi = mini;Swap(&a[end], &a[maxi]);++begin;--end;}
}

4.堆排序

冒泡排序详解可以参考:CSDN

5.冒泡排序

冒泡排序详解可以参考:CSDN

6.快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,快速排序的基本思想为:任取待排元素序列中的某个元素作为基准值,按照该排序码将待排序集合分割成两个子序列,左子序列中的所有元素均小于基准值,右子序列中的所有元素均大于基准值,然后左右序列重复该过程,直到所有元素都排列在相应的位置上为止

快速排序递归实现与二叉树的前序遍历规则类似,需要注意的是如何按照基准值来对区间中数据进行划分,常见的方式有以下几种:

6.1Hoare版本

单趟排序:选定一个基准值key,一般情况下为第一个或最后一个元素,设置两个变量left和right分别指向数据元素集合的头和尾,left向后找大数,right向前找小数,找到则交换,直到二者相遇,将相遇位置的数与key交换。

单趟排序结束后,数据元素的排列为:小数  key  大数,其中小(大)数是指小(大)于key的数。key的位置已经确定,不需要再更改,分割出了两个子区间,若这两个子区间有序,则整体有序,因此递归对两个子区间进行排序即可使整体有序。

以下为单趟排序的参考代码:

int keyi = left;//选取第一个数作为关键值while (left < right){//right找小数while (left < right && a[right] >= a[keyi]){--right;}//left找大数while(left < right && a[left] <= a[keyi]){++left;}//判断left和right的关系,防止错过if (left < right){Swap(&a[left], &a[right]);}}//left和right相遇,交换相遇位置的值和关键值Swap(&a[left], &a[keyi]);

📖Note:

1️⃣与关键值比较大小时,需要注意与关键值相等的特殊情况

对left,找大数,遇到小于key的值时继续向后走;遇到等于key的值时,也应该向后继续寻找,如果不过滤等于key的值,则会产生死循环

当数据元素集合中为单值时,如果不过滤等于的情况,right找小数的循环将会是一个死循环;或者当key == a[right]时,也会陷入死循环

2️⃣当选取第一个数据元素作为key,left与right相遇时,交换相遇位置的数据与key,如何保证相遇的位置比key小?(key是第一个数据元素,属于小数区间)

left和right相遇有两种情况:

  1. right停下来,left撞到right相遇,相遇位置比key小:right找小数,所以right停下来的位置为小于key的数,即相遇位置为小于key的数,属于小数区间。因此若选取第一个数据元素做key,则right先走
  2. left停下来,right撞到left相遇,相遇位置比key大:left找大数,所以left停下来的位置为大于key的数,即相遇位置为大于key的数,属于大数区间。因此若选取最后一个数据元素做key,则left先走
// Hoare
int PartSort1(int* a, int left, int right)
{//取第一个数据元素为关键值int keyi = left;while (left < right){// R找小while (left < right && a[right] >= a[keyi]){--right;}// L找大while (left < right && a[left] <= a[keyi]){++left;}if (left < right)Swap(&a[left], &a[right]);}//相遇位置为meetiint meeti = left;Swap(&a[meeti], &a[keyi]);return meeti;
}

快速排序的优化:主要是对关键值key选取的优化

key的选择有三种方法:

  1. 随机选key
  2. 针对有序序列,先key为最中间位置的数据
  3. 三数取中:即第一个元素,中间位置元素,最后一个位置元素三数取中位数

三数取中的函数接口如下:

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

对key的选择优化之后,可以减少递归的层数,有效避免栈溢出

关键值key的选择优化之后,Hoare版本的单趟排序可以优化:通过三数取中的方法确定关键值key后,将key与第一个数据交换,此时关键值key仍为第一个数据,因此其他地方不需要修改

// Hoare
int PartSort1(int* a, int left, int right)
{// 三数取中int mid = GetMidIndex(a, left, right);Swap(&a[left], &a[mid]);int keyi = left;while (left < right){// R找小while (left < right && a[right] >= a[keyi]){--right;}// L找大while (left < right && a[left] <= a[keyi]){++left;}if (left < right)Swap(&a[left], &a[right]);}//相遇位置为meetiint meeti = left;Swap(&a[meeti], &a[keyi]);return meeti;
}

6.2挖坑法

挖坑法是对Hoare版本的改进,确定关键值key之后,将其备份,并将其作为一个坑位(数据集合中的第一个元素),right先走找小数,找到则将该小数填到坑位中,并更新该小数的位置为新的坑位,left再走找大数,找到后将该大数填到坑位中,并更新该大数的位置为新的坑位,重复上述操作,直到left和right相遇,相遇位置为一个坑位,填入关键值key

具体过程如下图所示;

// 挖坑法
int PartSort2(int* a, int left, int right)
{// 三数取中int mid = GetMidIndex(a, left, right);Swap(&a[left], &a[mid]);int key = a[left];int hole = left;while (left < right){// 右边找小,填到左边坑while (left < right && a[right] >= key){--right;}a[hole] = a[right];hole = right;// 左边找大,填到右边坑while (left < right && a[left] <= key){++left;}a[hole] = a[left];hole = left;}a[hole] = key;return hole;
}

6.3前后指针法

前后指针法也是对Hoare版本的改进,确定关键值key(数据元素集合的第一个元素)并备份,设置两个指针,prev和cur,prev初始化为第一个数据元素,cur初始化为prev的下一个数据元素,当cur没有越界时,cur向后找小数,找到则交换prev指向的数据和cur指向的元素,prev++,cur++,重复上述操作,直到cur越界时,交换prev指向的数据元素和关键值key

📖Note:prev++的操作在交换操作之前,cur++的操作在交换操作之后

在cur找到小数时,prev指向的也为小数,其下一个位置为大数,所以prev需要先加1再交换

具体过程如下图所示:

特殊情况:++prev == cur时,会产生自己和自己交换的情况,因此需要过滤

// 前后指针法
int PartSort3(int* a, int left, int right)
{// 三数取中int mid = GetMidIndex(a, left, right);Swap(&a[left], &a[mid]);int keyi = left;int prev = left;int cur = left + 1;while (cur <= right){// cur找小if (a[cur] < a[keyi] && ++prev != cur)Swap(&a[cur], &a[prev]);++cur;}Swap(&a[keyi], &a[prev]);return prev;
}

6.4快速排序的递归实现 

快速排序的递归实现:

单趟排序结束后,数据元素的排列为:小数  key  大数

小数区间为[begin ,keyi -1],大数区间为[keyi+1,end]

按照单趟排序的方法递归对这两个区间排序即可

递归结束的条件:区间中只有一个值时递归调用结束,begin==end;或者begin>end,区间无效时递归调用结束

//快速排序
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}//每趟排序区间的划分:Hoare,挖坑法,前后指针法//调用相应接口即可int keyi = PartSort1(a, begin, end);QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}

6.5快速排序的非递归实现

函数的调用需要在开辟栈帧,如果递归调用的层数太深,可能会造成栈溢出

我们可以借助数据结构中的栈来优化快速排序,数据结构中的栈是在堆区开辟空间,堆区的空间要远远大于栈区空间

实际上,快速排序的非递归是借助数据结构中的栈模拟递归的过程

非递归实现思路:每次将区间的左右区间压栈,当栈不为空时,取栈顶两个元素分别作为一趟排序的区间的左右端点进行排序

📖Note:

如果先定义right,则需要区间左端点begin要先入栈,区间右端点end后入栈,这样才能保证right被区间右端点赋值,left被区间左端点赋值

//快速排序的非递归实现
void QuickSortNonR(int* a, int begin, int end)
{ST st;StackInit(&st);StackPush(&st, begin);StackPush(&st, end);while (!StackEmpty(&st)){//区间右端点int right = StackTop(&st);StackPop(&st);//区间左端点int left = StackTop(&st);StackPop(&st);//区间划分,单趟排序int keyi = PartSort3(a, left, right);//右区间if (keyi + 1 < right){StackPush(&st, keyi + 1);StackPush(&st, right);}//左区间if (left < keyi - 1){StackPush(&st, left);StackPush(&st, keyi - 1);}}StackDestroy(&st);
}

7.归并排序

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的典型应用。将已经有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序,若将两个有序表合并成一个有序表,称为二路归并。

二路归并排序的步骤如下图:

由如下动态图,可以更好的理解二路归并排序的过程

归并排序的递归实现类似于二叉树的后续遍历,采用二叉树的后续遍历框架,递归结束的条件是begin>=end;区间的划分为 [begin, mid] 和 [mid+1, end],mid为中间位置

归并排序的时间复杂度和空间复杂度:

归并排序需要额外开辟一个长度为N的数组,因此其空间复杂度为O(N)

归并排序的时间复杂度为O(N*logN)

void _MergeSort(int* a, int begin, int end, int* tmp)
{if (begin >= end)return;int mid = (end + begin) / 2;_MergeSort(a, begin, mid, tmp);_MergeSort(a, mid + 1, end, tmp);// 两两归并成有序序列:取小的尾插// [begin, mid] [mid+1, end]int begin1 = begin, end1 = mid;int begin2 = mid + 1, end2 = end;int i = begin;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++];}// 拷贝回原数组:归并哪部分就拷贝哪部分回去memcpy(a + begin, tmp + begin, (end - begin + 1) * sizeof(int));
}void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}_MergeSort(a, 0, n - 1, tmp);free(tmp);tmp = NULL;
}

8.计数排序(非比较排序)

计数排序又称为鸽巢原理,是对哈希定址法的直接应用

计数排序的操作步骤:

  1. 统计相同元素出现的次数
  2. 根据统计的结果将序列回收到原来的序列中

📖Note:

计数排序中的相对映射

1.统计个数,得到个数记录数组C

2.将数组C转换成C[i]中存放的是值小于等于i的数据的个数

3.为A数组从前向后的每个元素找到对应的B中的位置,每次从A中复制一个元素到B中,C中相应的计数减一

4.当A中的所有数据都复制到B之后,B中存放的就是有序的数据

总结:计数排序在数据范围集中时,效率很高,但其适用范围有限

void CountSort(int* a, int n)
{int max = a[0], min = a[0];for (int i = 1; i < n; i++){if (a[i] > max){max = a[i];}if (a[i] < min){min = a[i];}}int range = max - min + 1;//统计计数int* countA = (int*)malloc(sizeof(int) * range);if (countA == NULL){perror("malloc fail");return;}memset(countA, 0, sizeof(int) * range);for (int i = 0; i < n; i++){countA[a[i] - min]++;//映射的相对位置}//排序int j = 0;for (int i = 0; i < range; i++){while (countA[i]--){a[j] = i + min;j++;}}
}

9.补充:基数排序

基数排序也属于非比较排序

基数排序的操作步骤:

  1. 分发数据
  2. 回收数据

多关键字排序有两种方式:MSD(最高位优先)和LSD(最低位优先)

基数排序的步骤如下图:

10.总结:排序算法的复杂度及稳定性分析

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,a[i] = a[j],且a[i] 在 a[j]之前,而在排序后的序列中,a[i] 仍在 a[j]之前,则称这种排序算法是稳定的,否则称之为不稳定的

1️⃣直接插入排序:稳定

关键码相同则不调整,继续向后排序

2️⃣希尔排序:不稳定

预排序时,相同的数据可能分到不同的组,不能保证稳定性

3️⃣选择排序:不稳定

4️⃣堆排序不稳定

当一个堆为单值时,向下调整会影响该值的稳定性,因此堆排序不稳定

5️⃣冒泡排序:稳定

关键码相同则不调整,继续向后排序

6️⃣快速排序:不稳定

7️⃣归并排序:稳定

关键码相同则不调整,继续向后排序

时间复杂度与空间复杂度总结:

算法平均情况最好情况最坏情况辅助空间稳定性
冒泡排序O(N^2)O(N)O(N^2)O(1)稳定
简单选择排序O(N^2)O(N^2)O(N^2)O(1)不稳定
直接插入排序O(N^2)O(N)O(N^2)O(1)稳定
希尔排序O(N*logN)~O(N^2)O(N^1.3)O(N^2)O(1)不稳定
堆排序O(N*logN)O(N*logN)O(N*logN)O(1)不稳定
归并排序O(N*logN)O(N*logN)O(N*logN)O(N)稳定
快速排序O(N*logN)O(N*logN)O(N^2)O(logN)~O(N)不稳定

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

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

相关文章

Jmeter 性能-监控服务器

Jmeter监控Linux需要三个文件 JMeterPlugins-Extras.jar (包&#xff1a;JMeterPlugins-Extras-1.4.0.zip) JMeterPlugins-Standard.jar (包&#xff1a;JMeterPlugins-Standard-1.4.0.zip) ServerAgent-2.2.3.zip 1、Jemter 安装插件 在插件管理中心的搜索Servers Perform…

散列函数,哈希表hash table

附上一句话&#xff1a;我知道大家可能曾经了解过这个散列表了&#xff0c;我发现&#xff0c;如果多看几个相关的视频&#xff0c;从不同的表述方式和不同的理解角度来理解这个问题&#xff0c;我会明白的更透彻&#xff0c;也有更多新的收获&#xff0c;尤其是对这个算法的应…

宁夏银行关键系统基于OceanBase的创新实践

宁夏银行成立于 1998 年&#xff0c;是宁夏第一家“宁”字号地方商业银行&#xff0c;西部地区第一家以省级行政区命名的地方商业银行。2016 年&#xff0c;被中国人民银行评为宁夏地区系统性重要银行。目前&#xff0c;全行设分支机构 97 家&#xff0c;其中总行营业部 1 家&a…

制造工厂ERP系统:从数字销售-生产到财务管理,掌握企业数字化十大核心!

在快速发展的数字化时代&#xff0c;企业&#xff08;尤其是传统生产制造行业&#xff09;面临着诸多挑战与机遇。无论是客户体验、供应链管理还是内部流程优化&#xff0c;数字化都在发挥着关键作用。为了更好地应对数字化带来的挑战和机遇为了更好地应对市场变化和提高竞争力…

打造高品质家具的必选!数控开料机为何备受推崇?

随着科技的不断进步&#xff0c;数控开料机已经成为了木材加工行业中的首选设备。 一、数控开料机在木材加工行业中的优势 高效、精准的加工效果 数控开料机采用高精度的数控技术和高功率的机械传动系统&#xff0c;可以实现对木材的精确开料和高效加工。与传统的手工操作相…

【RabbitMQ】RabbitMQ高级:死信队列和延迟队列

目录 设置TTL&#xff08;过期时间&#xff09;概述RabbitMQ使用TTL原生API案例springboot案例 死信队列概述原生API案例springboot案例 延迟队列概述插件实现延迟队列安装插件代码 TTL实现延迟队列实现延迟队列优化 设置TTL&#xff08;过期时间&#xff09; 概述 在电商平台…

51单片机-电子密码锁

实物演示效果&#xff1a; https://www.bilibili.com/video/BV1xh4y1K7uV/?vd_source6ff7cd03af95cd504b60511ef9373a1d 电子密码锁的主要功能 1.按键设置6位密码&#xff0c;输入密码若密码正确&#xff0c;则锁打开。显示open&#xff01; 2.密码可以自己修改&#xff0…

Ubuntu 22.04安装使用easyconnect

EasyConnect 百度百科&#xff0c;EasyConnect能够帮助您在办公室之外使用公司内网的所有系统及应用。在您的公司部署深信服远程应用发布解决方案后&#xff0c;您的公司所有业务系统及应用都可以轻松迁移至移动互联网上。您可以通过手机、PAD等智能移动终端随时随地开展您的业…

【Leetcode】82. 删除排序链表中的重复元素 II

文章目录 题目思路代码 题目 82. 删除排序链表中的重复元素 II 题目&#xff1a;给定一个已排序的链表的头 head &#xff0c; 删除原始链表中所有重复数字的节点&#xff0c;只留下不同的数字 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,3,4,…

带你解析git的基础功能(二)

文章目录 一.前言二.什么是git的分支管理三.git的分支管理的相关操作3.1 创建分支3.2 切换分支3.3 合并分支 和合并冲突3.4 删除分支 四.分支管理策略第一种分支策略第二种分支策略 总结 一.前言 掌握 Git 分⽀管理&#xff0c;从分⽀创建&#xff0c;切换&#xff0c;合并&am…

Visual Studio 2019 ctrl+f 呼出查找和替换窗口

有时候 ctrlshiftf 呼出查找和替换窗口不起作用&#xff0c;可能和其它程序的快捷键冲突&#xff0c;解决方案&#xff1a; ------------英文版本------------ 依次点击VS菜单栏中的 Tools - Options - Environment - Keyboard: 1. 在右侧的 Show commands containing: 文本框输…

【深度学习】RTX2060 2080如何安装CUDA,如何使用onnx runtime

文章目录 如何在Python环境下配置RTX 2060与CUDA 101. 安装最新的NVIDIA显卡驱动2. 使用conda安装CUDA Toolkit3. 验证onnxruntime与CUDA版本4. 验证ONNX需求版本5. 安装ONNX与onnxruntime6. 编写ONNX推理代码 如何在Python环境下配置RTX 2060与CUDA 10 RTX 2060虽然是一款较早…

Android PendingIntent 闪退

先来给大家推荐一个我日常会使用到的图片高清处理在线工具&#xff0c;主要是免费&#xff0c;直接白嫖 。 有时候我看到一张图片感觉很不错&#xff0c;但是图片清晰度不合我意&#xff0c;就想有没有什么工具可以处理让其更清晰&#xff0c; 网上随便搜下就能找到&#xff…

activiti流程图+动态表单

使用技术 jeecg-bootactivitivue3form-create 简单效果展示 流程图绘制 审批人配置 动态表单配置 流程审批 流程审批记录 填写表单信息 源码地址 后台&#xff1a;https://gitee.com/houshixin/jmg-boot前端&#xff1a;https://gitee.com/houshixin/jmg-ui

Pandas加载大数据集

Scaling to large datasets — pandas 2.1.4 documentationhttps://pandas.pydata.org/docs/user_guide/scale.html#use-efficient-datatypes官方文档提供了4种方法&#xff1a;只加载需要的列、转化数据类型、使用chunking&#xff08;转化文件存储格式&#xff09;、使用Dask…

计算机导论06-人机交互

文章目录 人机交互基础人机交互概述人机交互及其发展人机交互方式人机界面 新型人机交互技术显示屏技术跟踪与识别&#xff08;技术&#xff09;脑-机接口 多媒体技术多媒体技术基础多媒体的概念多媒体技术及其特性多媒体技术的应用多媒体技术发展趋势 多媒体应用技术文字&…

DataXCloud部署与配置[智数通]

静态IP设置 # 修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33# 修改文件内容 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic IPADDR192.168.18.130 NETMASK255.255.255.0 GATEWAY192.168.18.2 DEFROUTEyes IPV4_FAILURE_FATALno IPV6INIT…

bash shell基础命令(一)

1.shell启动 shell提供了对Linux系统的交互式访问&#xff0c;通常在用户登录终端时启动。系统启动的shell程序取决于用户账户的配置。 /etc/passwd/文件包含了所有用户的基本信息配置&#xff0c; $ cat /etc/passwd root:x:0:0:root:/root:/bin/bash ...例如上述root账户信…

多级缓存架构(二)Caffeine进程缓存

文章目录 一、引入依赖二、实现进程缓存1. 配置Config类2. 修改controller 三、运行四、测试 通过本文章&#xff0c;可以完成多级缓存架构中的进程缓存。 一、引入依赖 在item-service中引入caffeine依赖 <dependency><groupId>com.github.ben-manes.caffeine…

热门护眼台灯深度测评,飞利浦、米家、书客护眼灯哪家强?

或许大家已经留意到了&#xff0c;如今佩戴眼镜的儿童越来越多&#xff0c;近视的发生呈现出越来越低龄化的趋势。这一现象与电子设备的广泛应用密切相关。除了天生的近视倾向和频繁使用电子设备外&#xff0c;我们还可能忽略了光照问题对视力的潜在影响&#xff0c;护眼台灯的…