【八大排序算法】插入排序、希尔排序、选择排序、堆排序、冒泡排序、快速排序、归并排序、计数排序

文章目录

  • 一、排序的相关概念
  • 二、排序类型
  • 三、排序算法实现
    • 插入排序
      • 1.直接插入排序
      • 2.希尔排序
    • 选择排序
      • 3.简单选择排序
      • 4.堆排序
    • 交换排序
      • 5.冒泡排序
      • 6.快速排序
        • 递归实现
        • 非递归实现
    • 7.归并排序
      • 递归实现
      • 非递归实现
    • 8.计数排序
  • 四、总结

一、排序的相关概念

排序:根据数据中关键字的大小,来进行升序或者降序排列。比如按照英文字母顺序排序,按照商品价格或者销量来排序等。

稳定性:如果存在两个或多个相同的数据,若经过排序后,它们的相对次序保持不变,则称这种排序算法是稳定的;否则就是不稳定的。

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

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

本篇介绍的是内部排序

二、排序类型

在这里插入图片描述

三、排序算法实现

可用各种排序算法跑这个OJ—>排序OJ链接

插入排序

1.直接插入排序

基本思想:将待排序的元素逐个插入到一个已经排好序的有序序列中,直到所有元素插入完为止,得到一个新的有序序列 。

初始序列是无序的,怎么将待排元素插入有序序列呢?

第一个元素本身可以看做一个有序序列,所以从第二个元素开始,从后往前遍历比较,插入前面已经排好的有序序列中。将大于该元素的所有元素位置向后挪动一位,在比较的过程中边比较边挪动。

以升序为例
在这里插入图片描述

可以发现,假设待排序的序列长度为n,插入排序需要进行n-1趟。

时间复杂度:O(N2)趟数为n-1,每趟待排序元素需要在前面的有序序列中从后往前比较挪动数据。

最好情况:O(N);有序,判断一次直接break出来,总共n-1趟,每趟不用挪动数据,量级为。
最坏情况:O(N2);逆序,每趟都头插,次数1+2+3+…N-1,所以时间复杂度量级是。

元素集合越接近有序,直接插入排序算法的效率越高。

空间复杂度:O(1)。 没有使用额外空间。

稳定性:稳定。 如果是大于等于某个位置的元素,则在其后面插入,相对位置不变。

//插入排序 稳定 时间复杂度O(N^2) 空间复杂度O(1)
void InsertSort(int* a, int n)
{for (int i = 1; i < n; i++){int end = i - 1;//有序序列的末尾位置int x = a[i];//待排序元素//将x插入到[0, end]区间中,并保持有序while (end >= 0){if (x < a[end]){a[end + 1] = a[end];//往后挪一个位置end--;}else{break;}}//while循环结束有两种情况://1.end = -1也即x比前面所有数都小;//2.x >= a[end] 这两种都是在end后面插入a[end + 1] = x;}
}

2.希尔排序

希尔排序法又称缩小增量法。是对插入排序的优化方案,效率比直接插入排序要高。

基本思想:将待排序列以间隔gap划分为gap个不同的组,对同组内的元素进行直接插入排序,然后缩小gap,重复上述分组和排序,直到gap=1,也就是直接插入排序,就会得到一个有序序列。

在这里插入图片描述

gap取多少合适?

gap初始值一般取n / 2,每趟排序完gap / 2,直到gap=1,即直接插入排序,此时序列接近有序,直接插入效率O(N)。gap也可以每次 ÷ 3,只要保证gap最后一次能取到1。

排升序,gap越大,大的数更快到后面,小的数更快到前面,但是越不接近有序;gap越小,越接近有序,gap=1时,就是直接插入排序。

时间复杂度:平均为O(N1.3)希尔排序的时间复杂度至今还没有精确的分析结果,经过大量的实验推出,n在某个特定范围内,希尔排序的比较和移动次数约为N1.3

空间复杂度:O(1)。 没有使用额外空间。

稳定性:不稳定。 希尔排序是分组排序的,且每个组内的数据不连续,无法保证相同数据的相对位置不被改变。比如上图中紫色4和橙色4在第一趟排序后,相对位置就发生了变化,所以希尔排序是不稳定排序。

//希尔排序 不稳定  效率比直接插入排序高 
void ShellSort(int* a, int n)
{//gap > 1 预排序//gap == 1 直接插入排序int gap = n;while (gap > 1){//gap = gap / 3 + 1;//也可以,除3后别忘了+1,否则gap为2时除3结果为0gap /= 2;for (int i = gap; i < n; i++){int end = i - gap;int tmp = a[i];//将x插入到[0, end]区间中,保持有序while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];//往后挪一个位置,方便x插入end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

选择排序

3.简单选择排序

基本思想:每次从剩下的待排序列中标记最小(最大)值的下标位置,遍历完后存放到未排序列的起始位置(也是已排好的序列的下一个位置),直到全部待排序的数据排完。

实际上,我们每趟可以选出两个值,一个最大值,一个最小值,然后分别与序列的起始和末尾元素交换。这样排序的趟数可以减少一半,但比较和交换的次数会×2,整体效率没有太大变化。
在这里插入图片描述
时间复杂度:O(N2)一共选择n趟,每趟与n-1个数进行比较;如果是每次同时选出最大值和最小值,一共需要n/2趟,每趟比较2×(n-1)次,量级都是O(N2)。

选择排序没有最好情况和最坏情况,不管有序还是逆序,都需要进行O(N2)次比较。所以选择排序的性能很差。因为不管是有序还是逆序,选择排序的效率都是最差的O(N2)。

空间复杂度:O(1)。 没有使用额外空间。

稳定性:不稳定。 因为每次是将待排序列的起始位置与序列中最小值(或最大值)进行交换,只保证了最小值的稳定性,但起始位置的稳定性可能会被破坏。(如果同时找出最大值并交换,例如图中一样,最小值表示的元素的稳定性也可能会被破坏,比如上图中第二趟排序4的相对位置就发生了变化)

//选择排序 不稳定 时间复杂度O(N^2) 空间复杂度O(1)
void SelectSort(int* a, int n)
{int l = 0, r = n - 1;while (l < r){int minPos = l, maxPos = l;//标记最小值和最大值的下标for (int i = l + 1; i <= r; i++){if (a[i] < a[minPos])minPos = i;if (a[i] > a[maxPos])maxPos = i;}//C语言没有库函数,交换函数需要自己写Swap(&a[l], &a[minPos]);//如果最大值maxPos与左边界l重合,在l与minPos交换后,最大值转移到了minPos位置if (l == maxPos)maxPos = minPos;Swap(&a[r], &a[maxPos]);l++;r--;}
}

4.堆排序

堆排序在数据结构——堆中已经详细讲过了,这里可能讲的没有那么细致。想详细了解堆的具体原理和使用可以看看这篇博客。

堆排序是利用数据结构堆(Heap)的特性所设计的一种算法,是选择排序的一种。它是通过堆来选择数据。

基本思想: 依次将将堆顶的数据与堆尾的数据交换,然后向下调整成堆,重复上述步骤直到数据完全有序。比如一个大根堆,我们取出堆顶元素(最大数)与最后一个数交换,交换后的最大数不看作在堆里面,那么堆顶元素的左右子树仍满足堆的性质,堆的结构并没有被破坏,然后堆顶元素向下调整成堆,即可选出第二大的数,以此类推到最后一个元素,就可以成功实现堆排序了。

升序:建大堆
降序:建小堆

时间复杂度:O(N*logN)向下调整建堆的时间复杂度为O(N)(过程在数据结构堆篇),堆顶元素一共进行n-1次交换,每次交换后向下调整为O(logN),所以最大量级是O(N*logN)。

堆排序也没有最好情况和最坏情况,堆排序不受初始序列顺序的影响,有序或者逆序时间复杂度都是O(N*logN)。

空间复杂度:O(1)。 没有使用额外空间。

稳定性:不稳定。 建堆时数据的相对顺序就可能被改变,在选数时堆顶与堆尾数据交换也可能导致稳定性被破坏。

//C语言没有库函数,交换函数需要自己写
void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}
//堆排序向下调整(排升序建大堆)
void AdjustDown(int* a, int n, int parent)
{int child = 2 * parent + 1;//先赋值左孩子while (child < n){//右孩子存在且右孩子比左孩子更大if (child + 1 < n && a[child + 1] > a[child]){child++;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}//堆排序 不稳定 时间复杂度O(N*logN)
void HeapSort(int* a, int n)
{//倒着调整,从最后一个非叶子结点开始向下调整建堆 效率O(N)for (int i = (n - 2) / 2; i >= 0; i--){AdjustDown(a, n, i);}//O(N*logN)int end = n - 1;//堆的有效长度while (end > 0){Swap(&a[0], &a[end]);//堆顶与堆尾元素交换AdjustDown(a, end, 0);//堆顶再向下调整,范围[1,end]end--;}
}

交换排序

5.冒泡排序

基本思想:从前往后遍历序列,每相邻两个数比较大小,前一个比后一个大就交换,直到将最大元素交换到末尾位置,继续从前往后遍历,重复上述操作,直到所有元素有序。

冒泡排序和选择排序一样都非常容易理解,也不上图演示了(画图太费时间),一切都在代码中。

时间复杂度:O(N2)一共n趟,每趟比较交换次数递减,总共比较1+2+3+…+n-1次,量级为O(N2)。

最好情况:O(N) ;有序情况下只用进行一趟比较(flag标记),就退出循环。
最坏情况:O(N2);每趟都进行交换。

空间复杂度:O(1)。 没有使用额外空间。

稳定性:稳定。 前后两个元素相同则不用交换,相对位置没有改变。

//冒泡(交换)排序 稳定 时间复杂度O(N^2)
void BubbleSort(int* a, int n)
{for (int i = 0; i < n; i++){bool flag = false;//判断是否交换过for (int j = 0; j < n - 1 - i; j++){if (a[j] > a[j + 1]){Swap(&a[j], &a[j + 1]);flag = true;}}if (flag == false)//一趟下来没有交换说明已经有序{break;}}
}

6.快速排序

快速排序整体的综合性能和使用场景都是比较好的,这也是大多数人使用快排的原因。
快速排序算法应该算是排序算法中的重点了。

快速排序是一种二叉树结构的交换排序方法。

基本思想:任取待排序的序列中的某元素作为key值,按照key值将待排序集合分割成两个子序列,左子序列中所有元素均小于key,右子序列中所有元素均大于key,然后最左右子序列重复该过程,直到所有元素有序。

快速排序的过程与二叉树的前序遍历相似,因此可以采用递归的方式。但在某些极端情况下可能会出现栈溢出,因此有时也会使用非递归的形式实现。

递归实现

快速排序的细节问题有很多,区间问题、key值的选取、交换细节等等,这些细节不注意很容易会造成超时(无限循环)、排序出错等问题。因此也衍生了很多版本:hoare版本、挖坑法、前后指针版本等,还有一些优化key值选取的方法例如“三数取中法”,这些代码有些地方不是那么容易理解,并且冗长,有的版本在排序OJ会跑不过。

上述所有版本这里不再总结,其他博主有更详细的介绍。下面介绍一种AcWing上大佬总结的快排模板,非常厉害,代码简洁易懂,在排序OJ也能跑过。

思路

我们选取一个key值,使用双指针ij分别从区间左右两边往中间走,将>=key的数换到右区间,将<=key的数换到左边界,当i>=j时,j(或i)的左边区间都<=key,右边区间都>=key,然后再递归左区间和右区间按照此方法排序。

void QuickSort(int* a, int l, int r)
{//递归的终止情况if (l >= r) return;//最好不选左右端点作key,否则有序或逆序情况下效率很差int key = a[(l + r) / 2];int i = l - 1, j = r + 1;while (i < j){while (a[++i] < key);//左边找大while (a[--j] > key);//右边找小if (i < j)Swap(&a[i], &a[j]);}QuickSort(a, l, j);QuickSort(a, j + 1 , r);
}

下面需要证明两个问题:无限循环和无限递归的边界问题。

在这里插入图片描述

key的取值会影响后面递归的区间,下面四种写法都是正确的。

上面代码是右边第一种写法。

在这里插入图片描述

我们先分析递归区间的取法

在这里插入图片描述

再来分析key的取法
虽然下面这两种区间划分都可以,但具体哪种要看key的取法:

在这里插入图片描述

这四种写法取一种即可

但建议写左边两种,因为key取到边界的话,有序或逆序情况下效率很差。
在这里插入图片描述总结

1.key取a[l]或者a[(l+r)/2]递归区间为QuickSort(a,l,j)QuickSort(a,j+1,r);
2.key取a[r]或者a[(l+r+1)/2]递归区间为QuickSort(a,l,i-1)QuickSort(a,i,r);
3.key不建议取边界,最好从中间选取,否则有序或者逆序情况下,效率很差。

在这里插入图片描述
时间复杂度:O(N*logN)时间复杂度=每层的操作次数×树的深度=nlogn

最好情况:O(N*logN) ;有序,只判断不进行交换。
最坏情况:O(N2);并非逆序,每次划分,key都是最小(最大)的。

空间复杂度:O(logN)。 递归的栈帧开销。

稳定性:不稳定。 快排前后交换数据会导致相对位置 发生改变。

非递归实现

快排的递归过程是将大区间划分为两个小区间,这两个小区间再分别划分成两个更小区间,直到递归到边界条件,结束然后回退到上一层。

所以快排的非递归可以借助队列或者的方式来实现。

队列的话可以参考二叉树的层序遍历。

思路:先取队头区间排序处理,再将队头的左右子区间入队,再取队头区间,再将左右区间入队,重复直到队列为空。

下面介绍快排非递归采用栈的实现方法。类似二叉树的前序遍历。

思路:每次取栈顶区间进行快排的单趟排序,然后将该区间的左右子区间入栈,再取栈顶区间处理,重复直到栈空。

//非递归快排
void QuickSortNonRe(int* a, int left, int right)
{ST st;STInit(&st);STPush(&st, left);//左端点入栈STPush(&st, right);//右端点入栈while (!STEmpty(&st)){//注意顺序,和入栈顺序相反int r = STTop(&st);STPop(&st);int l = STTop(&st);STPop(&st);//单趟排序int key = a[(l + r) / 2];int i = l - 1, j = r + 1;while (i < j){while (a[++i] < key);//左边找大while (a[--j] > key);//右边找小if (i < j)Swap(&a[i], &a[j]);}//分为[l, j]和[j + 1, r]区间if (l < j)//l == j 说明该区间只有一个值,无需入栈{STPush(&st, l);STPush(&st, j);}if (j + 1 < r){STPush(&st, j + 1);STPush(&st, r);}}STDestroy(&st);
}

7.归并排序

递归实现

归并排序的递归实现属于分治算法,分治算法都有三步:

1.分成子问题;
2.递归处理子问题;
3.子问题合并。

归并排序是不断将区间分解成子区间,一分二,二分四…,直到每个区间只有一个元素,然后开始向上合并有序区间,分而治之。实现过程与二叉树的后序遍历类似,先递归再合并处理元素。

在这里插入图片描述

时间复杂度:O(N*logN)与快排一样,时间复杂度=每层的操作次数×树的深度=nlogn

归并排序不受初始数据顺序的影响,不管有序还是无序,时间复杂度都是O(N*logN)。因为每次都递归到最小区间开始合并区间。

空间复杂度:O(N)。 需要额外开辟数组空间。

稳定性:稳定。 归并过程左右区间有两个数相同时,先从左区间取数据。

//归并排序 稳定 时间复杂度O(N*logN) 空间复杂度O(N)
void Merge(int* a, int l, int r, int* tmp)//tmp临时存放合并好的数据
{//递归的终止情况if (l >= r)return;//第一步:分成子问题int mid = (l + r) / 2;//第二步:递归处理子问题Merge(a, l, mid, tmp);Merge(a, mid + 1, r, tmp);//第三步:合并子问题;将[l, mid]和[mid + 1, r]区间归并int i = l, j = mid + 1;int k = 0;while (i <= mid && j <= r){if (a[i] <= a[j])//可见稳定性tmp[k++] = a[i++];elsetmp[k++] = a[j++];}//左区间剩余while (i <= mid)tmp[k++] = a[i++];//右区间剩余while (j <= r)tmp[k++] = a[j++];//将归并好的tmp数组的内容交给数组a的[l,r]区间memcpy(a + l, tmp, sizeof(int) * k);// k == r - l + 1//i = l, k = 0;//while (i <= r)//	a[i++] = tmp[k++];
}//归并排序
void MergeSort(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (NULL == tmp){perror("malloc");return;}Merge(a, 0, n - 1, tmp);free(tmp);
}

非递归实现

归并排序的非递归是可以直接从最小区间开始合并的,所以省去了递归划分子区间的过程,使用一个gap值来实现区间的跨度,gap从1开始每循环一次乘2,;区间的跨度从1到2,再到4…以2的指数增长。如果数据个数不满足2n个,则左右区间可能会发生越界,这就是需要处理的细节问题。

修正区间边界:(左区间的左端点一定不会越界,不用考虑)当左区间的右端点越界,或者右区间的左端点越界,则后面的元素(有序)不再合并,等待下一轮。
否则如果右区间的右端点越界,则使右端点=n-1,进行修正。
在这里插入图片描述

//非递归
void MergeSortNonRe(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (NULL == tmp){perror("malloc");return;}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2 * gap){int left1 = i, right1 = i + gap - 1;int left2 = i + gap, right2 = i + 2 * gap - 1;if (right1 >= n || left2 >= n)//不再归并{break;}if (right2 >= n)//第二区间右端点越界{right2 = n - 1;}//合并子区间int k = i;while (left1 <= right1 && left2 <= right2){if (a[left1] <= a[left2])tmp[k++] = a[left1++];elsetmp[k++] = a[left2++];}while (left1 <= right1)tmp[k++] = a[left1++];while (left2 <= right2)tmp[k++] = a[left2++];//合并一次,拷贝一次memcpy(a + i, tmp + i, sizeof(int) * (right2 - i));}gap *= 2;}free(tmp);
}

8.计数排序

前面七种排序算法都属于比较排序,而计数排序是一种非比较排序。并不是通过两个数相比来进行排序的。

计数排序本质就是用数组存储一个映射关系把它的位置保存起来,然后再遍历原先的数组从位置数组中把它拿出来进行排序。

基本思想:统计相同元素出现次数,然后根据统计的结果将序列回收到原来的序列中。

遍历一边序列,元素每出现一次,就将以该元素为下标的数组的值+1,类似哈希表。

但是,如果序列中只有几个数,但这几个数并不算很小,例如{100, 100,101};我们就需要开辟101个空间来存储,会造成空间的大量浪费。所以对此可以进行优化,利用序列中最大值和最小值的差值来开辟空间。这样只需开辟2个整型空间即可。

时间复杂度:O(N+range)只需要遍历几遍数组。

归并排序不受初始数据顺序的影响,不管有序还是无序,时间复杂度都是O(N*logN)。因为每次都递归到最小区间开始合并区间。

空间复杂度:O(range)。 需要额外开辟空间。range=最大值-最小值+1

稳定性:不稳定。 没有进行数据交换,本质上是修改了原始数据。

计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。

//计数排序 时间复杂度O(N+range) 空间复杂度O(range)
void CountSort(int* a, int n)
{//第一遍,找出最大值和最小值int maxVal = a[0], minVal = a[0];for (int i = 1; i < n; i++){if (a[i] > maxVal)maxVal = a[i];if (a[i] < minVal)minVal = a[i];}//开辟数组空间int range = maxVal - minVal + 1;//calloc自动初始化为0int* count = (int*)calloc(sizeof(int), range);if (NULL == count){perror("malloc");return;}//第二遍,计数for (int i = 0; i < n; i++)count[a[i] - minVal]++;//排序int i = 0;for (int x = minVal; x <= maxVal; x++){while (count[x - minVal]-- > 0)a[i++] = x;}free(count);
}

四、总结

对这八种算法进行性能测试,随机生成10万个数据,统计排序所消耗时间如下:

在这里插入图片描述可以看出,三种基本排序:插入排序、选择排序、冒泡排序所花费的时间明显更多。它们的时间效率都是O(N2),但是它们的效率却有明显差别。

插入排序最快;选择排序扫描一遍数组,只需要换两次位置;而冒泡排序需要不断交换相邻的元素。因此,选择排序在大型数据集中的性能比冒泡排序更好。

剩下五种排序算法跟它们不是一个量级,数据量太小看不出明显差别,我们单独用100万个数据来测试这五种排序算法的性能。

在这里插入图片描述
计数排序最快,但是计数排序的使用场景也有限,本质是拿空间换时间,而且当空间效率O(range)>O(nlog(n))的时候其效率反而不如基于比较的排序;所以计数排序不归在常见的排序算法中。

剩下四种常见算法中,希尔排序、堆排序、归并排序是相差不大的;快速排序是比较突出的,要比其余算法(除了计数排序)都快,快速排序整体的综合性能和使用场景都是比较好的。

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


排序方法时间复杂度空间复杂度稳定性
平均情况最好情况最坏情况
插入排序插入排序O(n²)O(n)O(n²)O(1)稳定
希尔排序平均 O(n1.3)O(1)不稳定
选择排序选择排序O(n²)O(n²)O(n²)O(1)不稳定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定
交换排序冒泡排序O(n²)O(n)O(n²)O(1)稳定
快速排序O(nlogn)O(nlogn)O(n²)O(nlogn)不稳定
归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定
计数排序O(n+range)O(n+range)O(n+range)O(range)不稳定

快速排序:一般情况时排序速度最块,但是不稳定,当有序时,反而不好;
归并排序:效率非常不错,在数据规模较大的情况下,比希尔排序和堆排序要好;
堆排序:适合Tok-K问题;例:找出一千万个数中最小的前一百个数;

算法的时间复杂度与初始序列初态无关的算法有:选择排序、堆排序、归并排序。

完整代码:八大排序算法

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

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

相关文章

【LAMMPS学习】八、基础知识(6.5)PyLammps 教程

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

[JAVASE] 类和对象(二)

目录 一. 封装 1.1 面向对象的三大法宝 1.2 封装的基本定义与实现 二. 包 2.1 包的定义 2.2 包的作用 2.3 包的使用 2.3.1 导入类 2.3.2 导入静态方法 三. static 关键字 (重要) 3.1 static 的使用 (代码例子) 3.1.1 3.1.2 3.1.3 3.1.4 四. 总结 一. 封装 1.1 面向对象…

推荐网站(9)pixabay免费可商用的图片、视频、插画、矢量图、音乐

今天推荐一款可以免费可商用的图片、视频、插画、矢量图、音乐的资源网站&#xff0c;这里面的所以东西都是免费的&#xff0c;并且可以商用。对那些做视频剪辑的人来说帮助非常大。它里面的资源非常的丰富&#xff0c;质量也高。 比如搜索下雨 链接直达&#xff1a;https://pi…

如何安装在系统中安装make命令

文章目录 WindowsMacUbuntuCentOS/Red Hat make是系统比较基础的命令&#xff0c;一般会自己携带&#xff0c;如果没有就手动安装一下吧。 Windows 从官网下载 make.exe Make for Windows 官网首页&#xff1a;https://www.gnu.org/software/make/ 下载地址&#xff1a;htt…

IT行业的革新力量:技术进步与未来展望

在当今时代&#xff0c;信息技术&#xff08;IT&#xff09;行业无疑是全球经济的重要推动力之一。随着数字化转型的不断深入&#xff0c;IT行业的边界正在扩大&#xff0c;它不仅包括传统的软硬件开发、网络建设和运维服务&#xff0c;还涵盖了云计算、大数据、人工智能&#…

我希望未来十年,Java可以变成这样的

ava&#xff0c;这位编程界的常青树&#xff0c;自1995年问世以来&#xff0c;一直是全球开发者的宠儿。随着技术的飞速发展&#xff0c;Java也在持续地自我革新。接下来&#xff0c;让我们来聊聊&#xff0c;未来十年Java可能会有哪些令人兴奋的变化。&#xff08;最重要的一点…

如何申请免费一年SSL证书

申请免费一年的SSL证书可以通过以下几个步骤进行&#xff0c;这里以JoySSL为例&#xff0c;因为它是目前提供此类服务的流行平台之一&#xff0c;同时也提到了宝塔面板中的TrustAsia SSL证书。请根据您的具体需求选择合适的方式&#xff1a; 申请免费一年SSL证书&#xff1a; …

2024年为什么很多电商商家,都想涌入视频号,究竟是什么原因?

大家好&#xff0c;我是电商糖果 对电商有了解的朋友&#xff0c;在今年肯定发现一个现象&#xff0c;那就是很多商家对视频号比较青睐。 视频号究竟有何魔力&#xff0c;让越来越多的商家都想要入驻。 其实很简单&#xff0c;它让商家看到了市场。 视频号背后是谁&#xf…

【Vue】Vue指令与生命周期以及组件化编码

目录 常用内置指令v-text与v-htmlv-text : 更新元素的 textContentv-html : 更新元素的 innerHTML注意&#xff1a;v-html有安全性问题&#xff01;&#xff01;&#xff01;&#xff01; v-once与v-prev-oncev-pre ref与v-cloakrefv-cloak 自定义指令案例定义语法配置对象中常…

两数相加 - (LeetCode)

前言 今天无意间看到LeetCode的一道“两数相加”的算法题&#xff0c;第一次接触链表ListNode&#xff0c;ListNode结构如下&#xff1a; public class ListNode {int val;ListNode next;ListNode() {}ListNode(int val) {this.val val;}ListNode(int val, ListNode next) {…

Sectigo SSL证书申请的流程是怎样的?

在当今数字化时代&#xff0c;网络安全成为了一个不可忽视的问题。为了保护网站和用户数据的安全&#xff0c;SSL证书成为了网站运营的重要组成部分。Sectigo作为全球领先的数字证书颁发机构之一&#xff0c;提供了一系列的证书解决方案来满足不同类型网站的需求。以下是对Sect…

2024年算法建模与计算机通信国际学术会议(ICAMCC 2024)

2024年算法建模与计算机通信国际学术会议(ICAMCC 2024) 2024 International Conference on Algorithm Modeling and Computer Communication(ICAMCC 2024) 会议简介&#xff1a; 2024年算法建模与计算机通信国际学术会议(ICAMCC 2024)将于中国南昌市盛大开幕。这次会议的目的是…

IP应用场景查询API接口

IP应用场景查询API接口指的是输入IP地址&#xff0c;查询IP应用场景信息。那么IP地址应用场景查询接口如何对接呢&#xff1f; 首先我们找到一家有IP地址应用场景查询API的服务商数脉API,然后注册账号&#xff0c;购买免费套餐 接下来就需要技术同学把IP应用场景查询接口对接到…

CentOS7中如何docker-compose

在 CentOS 7 上安装 docker-compose 需要几个步骤 步骤 1: 安装 Docker 首先&#xff0c;确保你已经安装了 Docker。如果没有安装&#xff0c;可以通过以下命令安装&#xff1a; sudo yum update -y sudo yum install -y yum-utils sudo yum-config-manager --add-repo http…

攻防世界(CTF)~web-supersqli(详细解题思路)

题目介绍 题目描述“随便注” 先看一下是否存在注入 判断闭合方式 输入1’ and 11-- -正常回显 输入1and 12-- -无回显,确认是单引号闭合 看一下列数 输入1 order by 2-- - 有回显 输入1 order by 3-- - 报错&#xff0c;由此判断两列 使用union联合注入发现select被过滤了&a…

WMS仓储管理系统如何让仓库管理有过程

在当今竞争激烈的商业环境中&#xff0c;WMS仓储管理系统的智能化与过程化管理显得尤为重要。一个具有过程管理的WMS仓储管理系统不仅能够帮助企业实时监控、分析和调度仓库作业&#xff0c;还能显著提升作业效率和成本控制能力。下面&#xff0c;我们就来深入探讨一下这种“有…

IT Tools

vs & vscode工具 Vs Extensions & Remote Development Vs Extensions Remote-SSH VSCode远程连接到Linux并实现免密码登录 Git Graph C cppreference.com cplusplus 镜像站点 用于下载 QT, Ubuntu, 清华镜像站点 CMake Download Documents Cmake 构建QT …

IO系列(三) - 文件读写操作介绍

一、摘要 在之前的文章中&#xff0c;我们了解到在 Java I/O 体系中&#xff0c;File 类是唯一代表磁盘文件本身的对象。 File 类定义了一些与平台无关的方法来操作文件&#xff0c;包括检查一个文件是否存在、创建、删除文件、重命名文件、判断文件的读写权限是否存在、设置…

揿针在医保上叫什么?

点击文末领取揿针的视频教程跟直播讲解 创新型皮内针&#xff08;揿针&#xff09;——医保甲类产品 皮内针&#xff08;揿针&#xff09;技术属于重点推广的中医适宜技术&#xff0c;是将特制的小型针具固定于腧穴部位的皮内或皮下做较长时间留针的一种方法&#xff0c;称“…

2024年 C++音视频开发学习路线(ffmpeg/rtsp/srs/webrtc/hls)

在音视频工作领域&#xff0c;很多人可能会陷入徘徊和迷茫的境地。音视频的知识纷繁复杂&#xff0c;自己学习非常困难&#xff0c;既需要非常扎实的基础知识&#xff0c;又需要有很多的工程经验&#xff1b;不知道如何学&#xff0c;怎样才能查漏补缺自己的技术短板。 对于音…