【数据结构--排序】

目录

  • 一、排序概述
    • 1.1、排序的相关定义
    • 1.2、排序用到的结构与函数
  • 二、常见排序算法
    • 2.1、冒泡算法(交换顺序)
      • (1)算法
      • (2)性能分析
    • 2.2、简单选择排序
      • (1)算法
      • (2)性能分析
    • 2.3、直接插入排序
      • (1)算法
      • (2)性能分析
    • 2.4、折半插入排序
      • (1)算法
      • (2)性能分析
    • 2.5、希尔排序
      • (1)算法
      • (2)性能分析
    • 2.6、堆排序
      • (1)算法
      • (2)性能分析
    • 2.7、归并排序
      • (1)算法
      • (2)性能分析
    • 2.8、快速排序
      • (1)算法
      • (2)性能分析
  • 三、各种排序算法的比较

一、排序概述

在这里插入图片描述

1.1、排序的相关定义

  1. 排序: 就是重新排列表中的元素,使表中的元素满足按关键字有序的过程。为了查找方便,通常希望计算机中的表是按关键字有序的。排序的确切定义如下:
    输入:n个记录 R 1 , R 2 , . . . , R n R_{1},R_{2},...,R_{n} R1,R2,...,Rn,对应的关键字为 K 1 , K 2 , . . . , K n K_{1},K_{2},...,K_{n} K1,K2,...,Kn
    输出:输入序列的一个重排 R 1 ′ , R 2 ′ , . . . , R n ′ R_{1}^{'},R_{2}^{'},...,R_{n}^{'} R1,R2,...,Rn,使得 K 1 ′ < = K 2 ′ < = K 3 ′ < = . . . K n ′ K_{1}^{'}<=K_{2}^{'}<=K_{3}^{'}<=...K_{n}^{'} K1<=K2<=K3<=...Kn其中“<=”可换成其他比较大小的符号。
  2. 排序的稳定性: 假设 k i = k j ( 1 < = i < = n , 1 < = j < = n , i ! = j ) k_{i}=k_{j}(1<=i<=n,1<=j<=n,i != j) ki=kj(1<=i<=n,1<=j<=n,i!=j),且在排序前的序列中 R i R_{i} Ri领先于 R j R_{j} Rj,如果在排序后, R i R_{i} Ri仍然领先于 R j R_{j} Rj,则所用的排序方法是稳定的,反之不稳定。
  3. 内部排序和外部排序: 内部排序是在排序整个过程中,待排序的所有记录全部被放置在内存中。外部排序是由于排序的记录数量太多,不能同时放置在内存,整个排序过程需要在内外存之间多次交换数据才能进行。

内部排序算法的性能取决于算法的时间复杂的和空间复杂度,时间复杂度一般是由比较时间和移动次数决定的。

1.2、排序用到的结构与函数

  1. 排序常用的顺序表结构
#define MaxSize 10  //用于要排序的数组中元素个数最大值,可根据需求进行修改
typedef struct{int R[MaxSize];//用于存储待排序的数组int length;//用于记录顺序表的长度
}SqList;
  1. 排序常用的数组中两数交换,将其写为函数,方便调用
void swap(SqList *L, int i, int j){int temp = L->R[i];L->R[i] = L->R[j];L->R[j] = temp;
}
//或不借助temp
void swap(SqList *L, int i, int j){L->R[i] = L->R[i] + L->R[j];L->R[j] = L->R[i] - L->R[j];L->R[i] = L->R[i] - L->R[j];
}

二、常见排序算法

2.1、冒泡算法(交换顺序)

(1)算法

冒泡排序的基本思想是: 从后往前(或从前往后)两两比较相邻元素的值,若为逆序(小的在前为证序,大的在前为逆序),则进行交换,直到序列比较完。第一趟冒泡,结果是将最小的元素交换到待排序列的第一个位置(或将最大的元素交换到待排序列的最后一个位置),关键字最小的元素就像气泡一样逐渐向上漂浮,直至水面(或关键字最大的元素就像石头一样下沉,直至水底)。下一趟冒泡时,前一趟确定的最小元素不再参与比较,每趟冒泡的结果是把序列中的最小元素(或最大元素)放到序列的最终位置,这样最多做n-1(n为序列中的元素个数)趟冒泡就能把所有元素排好序。

void BubbleSort(SqList *L){int i, j;bool flag = true;//表示本趟冒泡是否发生的标志for(i = 0; i < L->length-1; i++){flag = false;//一趟冒泡过程for(j = L->length-1; j > i; j--)//从后往前,若为逆序,则进行交换if(L->R[j-1] > L->R[j]){swap(&L,j,j-1);flag = true;}}if(flag == false){return;//本趟遍历后没有修改flag的值,说明序列已经有序,不需要再进行冒泡}
}

(2)性能分析

  • 稳定性:稳定
  • 空间效率:空间复杂度为 O ( 1 ) O(1) O(1)
  • 时间效率:当初始序列有序时,比较次数为n-1,元素移动次数为0,最好情况下的时间复杂度就为 O ( n ) O(n) O(n);当初始序列为逆序时,需要进行n-1趟排序,每趟排序要进行n-i次比较,每次比较后都必须进行n-i次移动,则: 比较次数 = 交换次数 = ( n − 1 ) + ( n − 2 ) + ( n − 3 ) + . . . + 1 = n ( n − 1 ) 2 比较次数=交换次数=(n-1)+(n-2)+(n-3)+...+1=\frac{n(n-1)}{2} 比较次数=交换次数=(n1)+(n2)+(n3)+...+1=2n(n1),所以最坏时间复杂度为 O ( n 2 ) O(n^{2}) O(n2),平均时间复杂度为 O ( n 2 ) O(n^{2}) O(n2)

2.2、简单选择排序

(1)算法

简单选择排序(Simple Selection Sort)就是通过n-i次关键字的比较,从n-i+1个记录中选出关键字最小的记录,并和第i(1<i<n)个记录进行交换。

void SelectSort(SqList *L){for(int i=0; i < L->length-1; i++){int min = i;//记录最小元素所在位置for(int j = i+1; j < L->length; j++){if(L->R[j] < L->R[min]){min = j;//更新最小元素的位置}}if(min != i){swap(&L, i,min);}}
}

(2)性能分析

  • 稳定性:不稳定
  • 空间效率:空间复杂度为 O ( 1 ) O(1) O(1)
  • 时间效率:从代码不难看出,在简单选择排序过程中,元素比较次数为 比较次数 = ( n − 1 ) + ( n − 2 ) + . . . + 1 = n ( n − 1 ) 2 比较次数=(n-1)+(n-2)+...+1=\frac{n(n-1)}{2} 比较次数=(n1)+(n2)+...+1=2n(n1)交换次数满足 交换次数 < n − 1 交换次数<n-1 交换次数<n1则时间复杂度为 O ( n 2 ) O(n^{2}) O(n2)

2.3、直接插入排序

(1)算法

直接插入排序(Staright Insertion Sort)的基本操作是将一个待排序的记录按其关键字大小插入到前面已经排好的子序列中,直到全部记录插入完成。

//不带哨兵的直接插入排序
void InsertionSort(SqList *L){int temp;for(int i = 1; i <L->length; i++){if(L->R[i] < L->R[i-1]){//若记录关键字小于前驱temp = L->R[i];for(int j = i-1; j >= 0 && L->R[j] > temp; --j){L->R[j+1] = L->R[j];}L->R[j+1] = temp;}}
}
//带哨兵的直接插入排序
void InsertionSort(SqList *L){for(int i = 2; i < L->length; i++){if(L->R[i] < L->R[i-1]){L->R[0] = L-<R[i];//下标为0处设置哨兵,免去后续对越界的判断for(int j = i-1; L->R[j] > L->R[0]; --j){L->R[j+1] = L->R[j];}L->R[j+1] = L->R[0];}}
}

示例分析:
初始序列为 { 49 , 38 , 65 , 97 , 76 , 13 , 27 , 49 } \{49,38,65,97,76,13,27,49\} {49,38,65,97,76,13,27,49}
在这里插入图片描述

(2)性能分析

  • 稳定性:稳定
  • 空间效率:空间复杂度为 O ( 1 ) O(1) O(1)
  • 时间效率:在排序过程中,向有序子表中逐个插入元素的操作进行了n-1趟,每趟操作都分为比较和移动元素,最好情况下,每趟比较1次,移动0次,时间复杂度为 O ( n ) O(n) O(n),最坏情况为逆序,时间复杂度为 O ( n 2 ) O(n^{2}) O(n2)

2.4、折半插入排序

(1)算法

折半插入排序是在直接插入排序的基础上做的优化,针对的是在有序子表中查找插入位置时的操作,利用折半查找来进行。

void BinaryInsertSort(SqList *L){int left, right, mid;for(int i=2; i <= L->length; i++){L->R[0] = L->R[i];left = 1;right = i - 1;while(left <= right){mid = (left + right)/2;if(L->R[mid] > L->R[0]){right = mid- 1;}else{left = mid + 1;}for(int j = i-1; j >= right+1; --j){L->R[j+1] = L->R[j];//统一后移元素,空出位置}L->R[right+1] = L->R[0];}}
}

(2)性能分析

  • 稳定性:稳定
  • 空间效率:空间复杂度为 O ( 1 ) O(1) O(1)
  • 时间效率:时间复杂度为 O ( n 2 ) O(n^{2}) O(n2)

2.5、希尔排序

(1)算法

希尔排序是对直接插入排序进行改进得到的,又称缩小增量排序。其基本思想是:先将待排序列分割成若干形如 L [ i , i + d , i + 2 d , . . . , i + k d ] L[i,i+d,i+2d,...,i+kd] L[i,i+d,i+2d,...,i+kd]的“特殊”子表,即把相隔某个增量的记录组成一个子表,对各个子表分别进行直接插入排序,缩小增量d,重复上述过程,直到d=1为止。

仅适用于顺序表存储。

示例分析:
初始序列为 { 49 , 38 , 65 , 97 , 76 , 13 , 27 , 49 } \{49,38,65,97,76,13,27,49\} {49,38,65,97,76,13,27,49} n = 8 n=8 n=8
①第一次: d 1 = n 2 = 4 d_{1}=\frac{n}{2}=4 d1=2n=4
在这里插入图片描述
各个子表进行插入排序
在这里插入图片描述
第一次排序的结果为:
在这里插入图片描述
②第二次: d 2 = d 1 2 = 2 d_{2}=\frac{d_{1}}{2}=2 d2=2d1=2
在这里插入图片描述

各个子表进行插入排序
在这里插入图片描述
第二次排序的结果为:
在这里插入图片描述
③第三次: d 3 = d 2 2 = 1 d_{3}=\frac{d_{2}}{2}=1 d3=2d2=1
在这里插入图片描述
进行直接插入排序,结果为:
在这里插入图片描述

void ShellSort(SqList *L){int step;//增量for(step = n/2; step > 0; step = step / 2){for(int i = 0; i < step; i++)//i是子表的编号for(int j = i + step; j < n; j = j + stap){if(L->R[j] < L->R[j-step]){int temp = L->R[j];}for(int k = j - step; K>=0 && L->R[K] > temp; k = k - step){L->R[k+step] = L->R[k];}L->R[k+step] = temp;}}
}

(2)性能分析

  • 稳定性:不稳定
  • 空间效率:空间复杂度为 O ( 1 ) O(1) O(1)
  • 时间效率:无法确切计算具体时间复杂度

2.6、堆排序

(1)算法

堆排序(Heap Sort)是对简单选择排序的一种改进。
1. 堆的定义
是具有下列性质的完全二叉树
每个结点的值都大于或等于其左右孩子结点的值,称为大根堆;
每个结点的值都小于等于其左右孩子结点的值,称为小根堆。
在这里插入图片描述
2. 堆排序
堆排序的思路很简单:首先将存放在 L [ 1... n ] L[1...n] L[1...n]中的n个元素建成初始堆,由于堆本身的特点(以大根堆为例),堆顶元素就是最大值。输出堆顶元素后,通常将堆底元素送入堆顶,此时根结点已不满足大根堆的性质,堆被破坏,将堆顶元素向下调整使其继续保持大根堆的性质,在输出堆顶元素,如此重复,直到堆中只剩一个元素为止。可见堆排序需要解决两个问题:①如何将无序的序列构造成初始堆(关键)②输出对顶元素后,如何将剩余元素调整为新的堆。

以大根堆为例,每一次将堆顶元素加入有序子序列,即把堆顶元素放入序列最右侧。再将前面所有的元素进行堆调整,经过调整之后,剩余元素中最大的元素又会到堆顶,再将堆顶元素与当前序列的堆底元素互换,重复上述操作,直至前面元素只有1个,因为只有一个,不用再进行调整,它就是最小的,这样,经过大根堆排序的序列呈现非递减趋势。

//建大根堆
void BuildMaxHeap(int A[], int len){//从后往前调整所有非叶子结点for(int i = len/2; i > 0; i--){Headadjust(A,i,len);}
}
//大根堆堆调整
void Headadjust(int A[], int k, int len){A[0] = A[K];//A[0]暂存以k为根结点时的值for(int i = 2*k; i <= len; i *= 2;){if(i < len && A[i] < A[i+1])//比较根结点k的左右孩子大小i++;//若右孩子大于左孩子,则将i更新为右孩子得到下标if(A[0] >= A[i])    break;//根结点的值大于等于孩子中最大的值,说明符合大根堆性质else{A[K] = A[i];//孩子的值大于根结点的话,就把大值给根结点k = i;//更新根结点的位置为原本孩子的位置,以便向下继续遍历}}A[k] = A[0];//把之前暂存进A[0]的根结点值给孩子,以实现根结点与孩子值的互换
}
//大根堆排序
void HeapSort(A[], int len){//首先建立大根堆BuildMaxHeap(A, len);//len-1趟交换和建堆过程for(int i = len; i > 1; i--){swap(A[i],A[1]);//把堆顶元素加入序列Headadjust(A,1,i-1);//将剩余元素整理成大根堆}
}

(2)性能分析

  • 稳定性:不稳定
  • 空间效率:空间复杂度为 O ( 1 ) O(1) O(1)
  • 时间效率:建堆时间复杂度为 O ( n ) O(n) O(n),排序时间复杂度为 O ( l o g 2 n ) O(log_{2}n) O(log2n),因此总的时间复杂度为 O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n)

2.7、归并排序

(1)算法

归并排序(Merge Sort)与上述基于交换、选择等排序的思想不一样,“归并”的含义是将两个或多个以上的有序表组成一个新的有序表。假定排序表含有n个记录,则可将其视为n个有序的子表,每个子表的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序表;继续两两归并,如此重复,直至合并成一个长度为n的有序表为止,这种排序叫做2路归并排序。
示例:
在这里插入图片描述
Merge()的功能是将前后相邻的两个有序表归并为一个有序表。设两段有序表A[low…mid],A[mid+1…high]存放在同一顺序表的相邻位置,先将它们复制到辅助数组B中。每次从对应数组B中的两段取出一个记录进行关键字的比较,将较小者放入A中,当数组B中有一段的下标超过其对应的表长(即该段所有元素都已复制到A中)时,将另一段中的剩余部分直接复制到A中。算法如下:

int *B = (int *)malloc(n*sizeof(int));//构造辅助数组Bvoid Merge(intA[], int low, int mid, int high){int i;int j;int k;for(k = low; k <= high; k++){B[K] = A[K];//将A中所有元素复制到B中}for(i = low, j = mid + 1, k = i;i <= mid && j <= high; k++){if(B[i] <= B[j])A[K] = B[i++];//将较小值复制到A中elseA[k] = B[j++];}while(i <= mid)    A[k++] = B[i++];//若第一个表未检测完,则直接将剩余部分复制进Awhile(j <= high)    A[k++] = B[j++];//若第二个表未检测完,则直接将剩余部分复制进A
}
//
void MergeSort(A[], int low, int high){if(low < high)int mid = (low + high)/2;//从中间划分为两部分MergeSort(A,low,mid);//对左半部分进行归并排序MergeSort(A,mid+1,high);//对右半部分进行归并排序Merge(A,low,mid,high);//归并
}

(2)性能分析

  • 稳定性:稳定
  • 空间效率:空间复杂度为 O ( n ) O(n) O(n)
  • 时间效率:每趟归并的时间复杂度为 O ( n ) O(n) O(n),共需进行 l o g 2 n log_{2}n log2n次归并,所以算法总的时间复杂度为 O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n)

2.8、快速排序

(1)算法

快速排序(Quick Sort)是对冒泡排序的优化。冒泡排序通过不断比较和交换来实现排序,不过其相比于冒泡排序,增大了比较和交换的距离,将关键字较大的记录从前面直接移动到后面,关键字较小的记录从后面直接移动到前面,从而减少了总的比较次数和交换次数。
基本思想为:在待排序表L[1…n]中任取一个元素pivot作为枢轴(或基准,通常取首元素),通过一趟排序将待排记录分割成独立的两部分L[1…k-1]和L[k+1…n],使得L[k+1…n]中所有元素均大于等于pivot,L[1…k-1]中的所有元素均小于等于pivot,则pivot放在了其最终位置上L(k),这个过程称为一次划分。然后分别递归地对两个子表重复上述过程,直至每部分中只有一个元素或者为空为止,即所有的元素放在了其最终位置上。
示例:
初始序列为: { 49 , 38 , 65 , 97 , 76 , 13 , 27 , 49 } \{49,38,65,97,76,13,27,49\} {49,38,65,97,76,13,27,49}
设两个指针i和j,初值分别为low和high;
①选择第一个元素49作为枢轴
在这里插入图片描述
j从后往前搜索比49小的元素,并移动到左边,即i指的位置。搜索到的第一个比49小的元素为27,将其放到i指向的位置。
在这里插入图片描述
此时原本27的位置就空出来了,i从前往后搜索大于等于49的元素,第一个搜索到的元素为65,则将65放到j指向的位置(即原本27空出来的位置)。
在这里插入图片描述
j继续从后往前搜索,找到了13,将13放到拿走65后留下的空位处。
在这里插入图片描述
i继续从前往后搜索,找到了97,将97放到拿走13后留下的空位处。
在这里插入图片描述
现在i == j了,将枢轴49放到i 指向的位置,而此处即49最终的位置。
经过一趟划分,序列变成了两个部分:
在这里插入图片描述
按照同样的方法对各子序列进行排序,直至待排序列中的元素小于等于1,整体排序就完成。
在这里插入图片描述

//划分,确定枢轴位置
void Partiion(int A[], int low, int high){int pivot = A[low];//用第一个元素作枢轴while(low < high){while(low < high && A[high] >= pivot){--high;}A[low] = A[high];//比枢轴小的元素放到左边while(low < high && A[low] < pivot){++low;}A[high] = A[low];//比枢轴大的元素放到右边}A[low] = pivot;//枢轴元素放到最终位置return low;//返回枢轴的最终位置
}
//快速排序
void QuickSort(int A[], int low, int high){if(low < high){int pivotpos = Partition(A,low,high);//划分QuickSort(A,low,pivotpos-1);//对左半部分进行递归操作QuickSort(A,pivotpos+1,high);}
}

(2)性能分析

  • 稳定:不稳定
  • 空间效率:由于快速排序是递归的,需要借助一个递归工作栈来保存每层递归调用的必要信息,其容量与递归调用深度一致,最好情况下为: O ( l o g 2 n ) O(log_{2}n) O(log2n),最坏情况下为 O ( n ) O(n) O(n),平均空间复杂度为: O ( l o g 2 n ) O(log_{2}n) O(log2n)
  • 时间效率:最坏情况下的时间复杂度为: O ( n 2 ) O(n^{2}) O(n2),最好情况下,时间复杂度为: O ( n l o g 2 n ) O(nlog_{2}n) O(nlog2n)

三、各种排序算法的比较

在这里插入图片描述

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

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

相关文章

FastAPI(七十一)实战开发《在线课程学习系统》接口开发-- 查看留言

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 之前FastAPI&#xff08;七十&#xff09;实战开发《在线课程学习系统》接口开发--留言功能开发分享了留言开发&#xff0c;这次我们分享查看留言 梳…

网络服务与应用

一、 文件传输 FTP 1、FTP采用典型的C/S架构&#xff08;即服务器端和客户端模型&#xff09;&#xff0c;客户端与服务器端建立TCP连接之后即可实现文件的上传、下载。 2、FTP传输过程 1&#xff09;、主动模式&#xff08;POST&#xff09;&#xff1a;入站连接 2&#x…

SqlSugar删除没有定义主键的实体类对应的数据库表数据

一般而言&#xff0c;使用SqlSugar的DbFirst功能创建数据库表实体类时&#xff0c;如果数据库表有主键&#xff0c;生成的实体类对应属性也会标识为主键&#xff0c;如下图所示。   但有时候生成的实体类没有自动配置主键&#xff0c;这时可以通过以下方式进行删除操作&…

【计算机网络】HTTP协议实验

一&#xff1a;实验目的 1&#xff1a;理解HTTP协议的基本工作原理。 2&#xff1a;使用Wireshark或其他抓包工具捕获并分析HTTP数据包&#xff0c;理解HTTP通信的具体过程。 3&#xff1a;通过分析抓包数据&#xff0c;识别常见的HTTP状态码及其含义。 二&#xff1a;实验仪…

光伏电站的运维经验

选择逆变器一是要看产品本身的效率和品质&#xff1b;二是要看系统的架构&#xff0c;怎么做的更简单&#xff0c;更可靠&#xff1b;三是要看场景的适应性&#xff1b;四是看服务。箱式逆变房后期运维无需协调多个厂家&#xff0c;大大提升了运维效率。相比自制土建房&#xf…

02集成开发工具配置VScode SSH连接Ubuntu20.04 - 输入密码连接

文章目录 1. running the VScode in Admin mode2. Install the plugin3. New Remote4. Enther the command at the top blanket column in VS Code5. Setup the ssh config file6. Restart VScode7. Connect to the Server8. Open the remote folder 1. running the VScode in …

Python 函数对象和函数调用

Python 函数对象和函数调用 在 Python 中&#xff0c;函数是第一类对象&#xff08;first-class objects&#xff09;。这意味着函数可以像其他对象&#xff08;如整数、字符串、列表等&#xff09;一样被传递、赋值和操作。理解函数对象和函数调用的区别是学习 Python 的关键…

简单了解反射

反射 文章目录 反射获取class对象的三种方式利用反射获取构造方法利用反射获取字段&#xff08;成员变量&#xff09;利用反射获取成员方法反射的作用 获取class对象的三种方式 ①Class.forName(“全类名”);&#xff08;源代码阶段使用&#xff09; ②类名.class&#xff08…

学习C语言之 深入了解指针1

深入了解指针 前面已了解到 1&#xff09;指针就是个变量&#xff0c;用来存放地址&#xff0c;地址是唯一的&#xff0c;可以标识一块内存空间。 2&#xff09;指针的大小是固定的4/8个字节&#xff08;32位平台/64位平台&#xff09;。 3&#xff09;指针是有类型的&#xf…

Linux中如何用ida调试fork后的子进程

原文链接 > https://redqx.github.io/linux/2024/07/24/linux-debugfork.html 本文的一些图片引用可能有一些问题, 比如数据不对劲,但无伤大雅 自己懒得粘贴图片了 环境: wsl-kali-2024 ida-7.7 插件: Lazy_ida, 还有一个什么插件不知道什么名字, 可以把汇编转字节码 …

mac安装Whisper

Whisper 官方git https://github.com/openai/whisper?tabreadme-ov-file 基本上参考官方的安装流程 pip3 install -U openai-whisper pip3 install githttps://github.com/openai/whisper.git pip3 install --upgrade --no-deps --force-reinstall githttps://github.com/…

牛客周赛52--E小红的图上加边(联通块)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 \,\,\,\,\,\,\,\,\,\,小红有一张 nnn 个点 mmm 条边的无向图&#xff0c;每个节点的权值是 aia_iai​。           \,\,\,\,\,\,\,\,\,\,现在小红希望加边把这个图连成连通…

Elasticsearch概念及ELK安装

1、Elasticsearch是什么 它是elastic技术栈中的一部分。完整的技术栈包括&#xff1a; Elasticsearch&#xff1a;用于数据存储、计算和搜索 Logstash/Beats&#xff1a;用于数据收集 Kibana&#xff1a;用于数据可视化 整套技术栈被称为ELK&#xff0c;经常用来做日志收集…

ansible的role目录结构及用法

目录 目录结构介绍案例 目录结构介绍 可以通可以通过使用 ansible-galaxy 命令再当前目录自动生成 role 的基本目录结构。 myrole为文件名&#xff08;角色名&#xff09; ansible-galaxy init myrole如果没有安装Ansible Galaxy&#xff0c;你可以使用以下命令安装&#xff…

Python 函数的参数形式

Python 函数的参数形式 Python 函数的参数有多种形式&#xff0c;每种形式在不同的场景下使用。我们主要介绍以下几种&#xff1a; 位置参数关键字参数默认参数可变位置参数&#xff08;*args&#xff09;可变关键字参数&#xff08;**kwargs&#xff09; 1. 位置参数 位置…

python题解

宽度与对齐 输出455、-123、987654&#xff0c;宽度为5&#xff0c;分别左对齐和右对齐 格式 输入格式&#xff1a; 无 输出格式&#xff1a; 输出为整型&#xff0c;空格分隔。每个数的输出占一行 样例 1 输入&#xff1a; 无 复制 输出&#xff1a; 455 455 -123 -123 98…

Vue的SSR和预渲染:提升首屏加载速度与SEO效果

引言 在现代Web应用开发中,首屏加载速度和搜索引擎优化(SEO)是衡量应用性能的重要指标。Vue.js 作为流行的前端框架,提供了服务器端渲染(SSR)和预渲染(prerendering)两种技术来提升这些指标。本文将深入探讨如何使用 Vue 的 SSR 和预渲染技术,提供详细的代码示例和最…

FFmpeg源码:av_probe_input_format3函数分析

一、av_probe_input_format3函数的声明 av_probe_input_format3函数声明在FFmpeg源码&#xff08;本文演示用的FFmpeg源码版本为5.0.3&#xff09;的头文件libavformat/avformat.h中&#xff1a; /*** Guess the file format.** param is_opened Whether the file is already…

Go语言的数据结构

数据结构 数组 支持多维数组&#xff0c;属于值类型&#xff0c;支持range遍历 例子&#xff1a;随机生成长度为10整数数组 package main import ("fmt""math/rand" ) // 赋值 随机获取100以内的整数 func RandomArrays() {var array [10]int //声明var…

【MySQL进阶篇】锁:全局锁、表级锁以及行级锁

一、锁的概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中除传统的计算资源&#xff08;CPU、RAM、I/O&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须要解决的一个问题&am…