数据结构:排序干货!(7大排序汇总+快速排序的优化+计数排序+基数排序+桶排序)

目录

概念

插入排序

直接插入排序

希尔排序

选择排序

直接选择排序

双向选择排序

堆排序

交换排序

冒泡排序

快速排序

Hoare法

挖坑法

前后指针法

快排的优化

三数取中法

非递归快排

归并排序

分治算法+二路归并

非递归归并

应用

排序总结

其他排序

计数排序

简单版本

复杂版本(稳定版本)

基数排序 

桶排序 


概念

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

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

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

外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。 (比如要放在磁盘,硬盘等来进行排序)

分类:


插入排序

直接插入排序

动图演示如下:在这里插入图片描述

我们可以设置两个指针i和j,i放在第二个元素的位置,j放在第一个元素的位置

每次把i位置的元素提取出来放到tmp中,和j位置的元素进行比较,如果tmp的元素较小,就与j位置元素进行交换

交换完之后j--,看看前面还有没有元素比交换后靠前的元素大,如果有就重复上述步骤,没有就把j和i挪到下一个元素

 

    public static void insertSort(int[] array) {for (int i = 1; i < array.length; i++) {int tmp = array[i];int j = i - 1;for (; j >= 0; j--) {if (array[j] > tmp) {array[j + 1] = array[j];} else {break;}}array[j + 1] = tmp;}}

时间复杂度?

最坏情况:

假设有n个数据,遍历第2个元素并进行交换,j要回退2-1 = 1次

遍历第3个元素并进行交换,j要回退3-1 = 2次

遍历第n个元素并进行交换,j还需要进行回退n-1次,那么需要n-1次操作,

总共就需要

1+2+3+...+n-1 ≈ n^2 -->O(n^2)

最好情况:

交换之后j不需要进行回退,那么直直遍历下去 --> O(n)

所以直插适用于:待排序序列基本趋于有序了

稳定性?

直接插入排序是稳定的,数据交换判断需要array[i] > tmp才有进行交换,如果原本序列有两个相同的数字,那直插是不会改变这两个数字的顺序的,所以是稳定的

⚠一个稳定的排序可以通过修改条件变成不稳定的排序,但是不稳定的排序一定不能变成稳定的排序


希尔排序

缩小增量排序,比如下面的排序

初始数据我们可以分成5组,此时的增量就是5,接着第1个元素与第6个元素,第2个元素与第7个元素等两两交换

接着降低增量(gap / 2),增加每组的数据,继续进行排序

其实前面的增量分组相当于一个预排序,真正的排序是最后一组

    //希尔排序public static void shellSort(int[] array){int gap = array.length;while(gap>1){gap /= 2;shell(array,gap);}}/*** 对每组进行排序* 这段代码其实跟插入排序差不多,就是i其实位置在gap上,j每次递减递增gap个单位* @param array* @param gap*/public static void shell(int[] array, int gap){for (int i = gap; i < array.length; i++) {int tmp = array[i];int j = i -gap;for (; j >= 0 ; j-=gap) {if (array[j] > tmp){array[j+gap] = array[j];}else{break;}}array[j+gap] = tmp;}}

时间复杂度?

稳定性?不稳定,因为分组交换之后会打乱相同的数字原本的前后顺序

编写个代码来测试一下两者的运行时间

import java.util.Arrays;public class Test {public static void testInsert(int[] array){int[] tmpArray = Arrays.copyOf(array, array.length);long startTime = System.currentTimeMillis();Sort.insertSort(tmpArray);long endTime = System.currentTimeMillis();System.out.println("直接插入排序时间:"+(endTime-startTime));}public static void testShell(int[] array){int[] tmpArray = Arrays.copyOf(array, array.length);long startTime = System.currentTimeMillis();Sort.shellSort(tmpArray);long endTime = System.currentTimeMillis();System.out.println("希尔排序时间:"+(endTime-startTime));}public static void initArray(int[] array){for (int i = 0; i < array.length; i++) {array[i] = array.length-i;}}public static void main(String[] args) {int[] array = new int[10_0000];initArray(array);testInsert(array);testShell(array);}
}


选择排序

直接选择排序

动图如下:
在这里插入图片描述

设置i和j,遍历当前i下标后面的元素(j++),找到一个最小的值与i下标的元素进行替换

然后i++,进行下一个元素的交换

    /*** 选择排序* 时间复杂度O(n^2)* 空间复杂度O(1)* 稳定性:不稳定* @param array* @param i* @param j*/public static void swap(int[] array,int i,int j){int tmp = array[i];array[i] = array[j];array[j] = tmp;}public static void selectSort(int[] array){for (int i = 0; i < array.length; i++) {int minIndex = i;//j往后遍历,每次找到比minIndex下标元素小的就进行下标替换for (int j = i+1; j < array.length; j++) {if(array[j] < array[minIndex]){minIndex = j;}}swap(array,i,minIndex);}}

双向选择排序

设置最左边下标l和最右边下标r,设置i = l+1,往后遍历,找到最小值的下标和最大值的下标

接着把minIndex的元素与l交换,maxIndex的元素与r交换

接着再i++,l++,r--,重复上面的步骤

注意:如果l的位置就是最大值,经过与最小值交换之后不一定有序

所以我们要把minIndex和maxIndex换过来

    public static void selectSort2(int[] array){int left = 0;int right = array.length-1;while(left<right){int minIndex = left;int maxIndex = right;//找到最大值和最小值下标for (int i = left+1; i <= right; i++) {if(array[i] < array[minIndex]){minIndex = i;}if(array[i] > array[maxIndex]){maxIndex = i;}}swap(array,minIndex,left);if(maxIndex == left){maxIndex = minIndex;}swap(array,maxIndex,right);left++;right--;}}

堆排序

可以看着我这篇博客的思路数据结构:优先级队列(堆)-CSDN博客

代码如下:

    private static void createHeap(int[] array) {for (int parent = (array.length-1-1)/2; parent >= 0 ; parent--) {siftDown(array,parent,array.length);//alt+enter}}private static void siftDown(int[] array,int parent, int length) {int child = 2*parent + 1;while (child < length) {if(child+1 < length && array[child] < array[child+1]) {child++;}if(array[child] > array[parent]) {swap(array,child,parent);parent = child;child = 2*parent+1;}else {break;}}}/*** 时间复杂度:O(N*logN)* 空间复杂度:O(1)* 稳定性:不稳定的排序* @param array*/public static void heapSort(int[] array) {createHeap(array);int end = array.length-1;while (end > 0) {swap(array,0,end);siftDown(array,0,end);end--;}}

交换排序

冒泡排序

动图如下:
在这里插入图片描述

    /*** 时间复杂度:O(n^2)* 空间复杂度:O(1)* 稳定性:稳定* @param array*/public static void bubbleSort(int[] array){//i代表趟数for (int i = 0; i < array.length-1; i++) {//每一趟都比较上一趟有没有交换boolean flg = false;//j来比较每个数据的大小for (int j = 0; j < array.length-1-i; j++) {if(array[j]>array[j+1]){swap(array,j,j+1);flg = true;}}if(flg==false){break;}}}

快速排序

Hoare法

单趟动图如下:
在这里插入图片描述

第一轮交换之后,6在中间,6的左边都比6小,右边都比6大

第二轮和第一轮一样,接着不停地递归下去

这些数组可以拆分并组成一棵二叉树如下图,二叉树就是左边和右边分别递归 

   public static void quickSort(int[] array){quick(array,0,array.length-1);}private static void quick(int[] array, int start, int end){if(start >= end){return;}//找到中间的值int pivot = partitionHoare(array,start,end);//左右分别进行递归quick(array,start,pivot-1);quick(array,pivot+1,end);}

接下来我们要来搞定partition的方法,也就是要找到整个序列中间值

先确定第一个元素是pivot元素

right指针负责找到比array[right]小的数字,left指针负责找到比array[left]大的数字

找到了就进行交换,直到左右指针相遇

    private static int partitionHoare(int[] array, int left, int right){int tmp = array[left];int i = left;//整个的循环,要求left和right相遇之后能交换数字while(left<right){//单独的循环,因为如果right--一直找不到比tmp大的数,而right不能一直减到最左边的边界//所以需要再规定依次left<rightwhile(left<right && array[right] >= tmp){right--;}while (left<right && array[left] <= tmp){left++;}swap(array,left,right);}swap(array,i,left);return left;}

思考:

1.为什么这里要有一个等于号

如果不用=号可能会进入死循环

如果没有等于号,第一个循环因为6不大于6,right没办法--,同理left没办法++,走到后面right和left进行交换,只是相当于6和6这两个元素的下标进行交换而已,整个数组也没有进行排序

2.为什么从右边开始而不是从左边开始?

如果先走左边,有可能会出现相遇的时大的数据,最后把大的数据放在最前面

而先走右边的话可以先遇到小的,可以把小的放到前面


时间复杂度?

最好情况:

根据上方代码的递归分治思想,找到中间值,递归左边递归右边再出中间值,每次出一个中间值都是把一部分一分为二进行寻找(logn)

每次循环都有n个元素要进行遍历

最后总的时间复杂度O(n*logn)

最坏情况:

比如:1 2 3 4 5

递归时right每次找到比1小的值都要遍历n个元素,在循环中每次都要遍历n个元素检查是否进行交换

所以总的时间复杂度就是O(n^2)

⚠快排使用时,数据一般不是逆序或者有序的

⚠快排使用时,往往会有栈的溢出

这个错误跟我们递归的层次有关系,递归越多在栈上开辟的空间就越多,而IDEA默认给出的空间是256KB,这么小的空间容纳不了我们10万个数据进行栈空间的开辟

我们要对IDEA进行一个调整


挖坑法

单趟动图如下:
在这里插入图片描述

    private static int partitionHole(int[] array, int left, int right){int tmp = array[left];//整个的循环,要求left和right相遇之后能交换数字while(left<right){//单独的循环,因为如果right--一直找不到比tmp大的数,而right不能一直减到最左边的边界//所以需要再规定依次left<rightwhile(left<right && array[right] >= tmp){right--;}array[left] = array[right];while (left<right && array[left] <= tmp){left++;}array[right] = array[left];swap(array,left,right);}array[left] = tmp;return left;}

前后指针法

思路:
1、选出一个key,一般是最左边或是最右边的。
2、起始时,prev指针指向序列开头,cur指针指向prev+1。
3、若cur指向的内容小于key,则prev先向后移动一位,然后交换prev和cur指针指向的内容,然后cur指针++;若cur指向的内容大于key,则cur指针直接++。如此进行下去,直到cur到达end位置,此时将key和++prev指针指向的内容交换即可。

  /*** 前后指针法:*  总结:*  1. Hoare 优先级: 2*  2. 挖坑法 优先级:1*  3. 前后指针法 优先级:3*  这3种方式  每次划分之后的前后顺序 有可能是不一样的* @param array* @param left* @param right* @return*/private static int partition(int[] array, int left, int right) {int prev = left;int cur = left + 1;while (cur <= right) {if (array[cur] < array[left] && array[++prev] != array[cur]) {swap(array, cur, prev);}cur++;}swap(array, prev, left);return prev;}

选择题: 

对记录( 54,38,96,23,15,72,60,45,83 )进行从小到大的直接插入排序时,当把第 8 个记录 45 插入到有序表时,为找到插入位置需比较() 次?(采用从后往前比较)
A: 3 B: 4 C: 5 D: 6

这道题不要太死板地做,题目问我们第8个记录45,那么说明45之前的数字一定是有序的

那45就需要比较到比它小的数就行,很简单选C


快排的优化

上面我们提到了,快排一旦递归较多的时候容易出现栈溢出的情况

所以我们优化方向:1.减少递归次数;2.让每一次都能均匀地分割数组

三数取中法

上面提到当快排的hoare和挖坑法遇到有序数列时,l和r都跑到第一个元素去,右边有一大坨数字,无法实现取到中间数的效果

我们采用三数取中法

1.先找到数列中间下标(m)的数字

int mid = (left+right)/2;

定义大前提

 

2.找出l,m,r下标的三个数字排在最中间的那个数

array[left]<array[right]

array[left]>array[right]

 

        if(array[left] < array[right]){if(array[mid]<array[left]){return left;}else if(array[mid] > array[right]){return right;}else{return mid;}}else{//array[left] > array[right]if(array[mid]>array[left]){return left;}else if(array[mid] < array[right]){return right;}else{return mid;}}

3.把m坐标元素与l坐标元素交换

4.然后以4为基准,利用r--找到比4小的元素,把这个元素与4交换

这样就不会出现找不到左数或者右数的情况

5.接着左右子树进行遍历就行了

        if(start>=end){return;}//1 2 3 4 5 6 7int index = middleNum(array,start,end);swap(array,index,start);//4 2 3 1 5 6 7int pivot = partition(array,start,end);quick2(array,start,pivot-1);quick2(array,pivot+1,end);

6.排序的最终步骤一般集中在数组二叉树的最后两层,而当排序到这个地方的时候,整个数组已经偏向有序的状态了,所以我们没必要再让二叉树继续递归下去,我们可以采用插入排序,在一个很小的序列中进行排序。这样可以降低树的高度,减少递归的次数

整个的代码

    private static int middleNum(int[] array, int left,int right){int mid = (left+right)/2;//求中位数的下标if(array[left] < array[right]){if(array[mid]<array[left]){return left;}else if(array[mid] > array[right]){return right;}else{return mid;}}else{//array[left] > array[right]if(array[mid]>array[left]){return left;}else if(array[mid] < array[right]){return right;}else{return mid;}}}public static void insertSort(int[] array, int left,int right) {for (int i = left+1; i <= right; i++) {int tmp = array[i];int j = i - 1;for (; j >= left; j--) {if (array[j] > tmp) {array[j + 1] = array[j];} else {break;}}array[j + 1] = tmp;}}private static void quick2(int[] array, int start, int end){if(start>=end){return;}if(end-start+1<=15){insertSort(array,start,end);return;}//1 2 3 4 5 6 7int index = middleNum(array,start,end);swap(array,index,start);//4 2 3 1 5 6 7int pivot = partition(array,start,end);quick2(array,start,pivot-1);quick2(array,pivot+1,end);}

非递归快排

先利用挖坑法排好序

创建一个栈,把6左边第一个和最后一个元素(pivot-1)的位置放入栈中,右边同理

弹出一个9给r,弹出6给l

 再重复一次挖坑法partition方法

9右边的元素不需要递归,所以直接当成pivot 

把9左边的第一个元素下标(6)和最后一个元素(7)放入栈中

 

怎么判断pivot左边和右边有多少个元素呢?

当pivot+1 = e的时候,右边只有1个元素;当pivot+1<e的时候,右边有两个或两个以上的元素

相反当pivot-1>s,左边有两个或两个以上元素

总结步骤:

1.调用partition方法找出整个数组的中间数位置pivot

2.左边有没有两个元素,下标放到栈

3.右边一样

4.判断栈空不空-->不空的话就pop两个元素出来分别交给r和l(注意最先出来的给r,慢一点的给l)

整个代码:

    public static void quickSortNor(int[] array){int start = 0;int end = array.length-1;Stack<Integer> stack = new Stack<>();int pivot = partitionHoare(array,start,end);if(pivot>start+1){stack.push(start);stack.push(pivot-1);}if(pivot+1<end){stack.push(pivot+1);stack.push(end);}while(!stack.isEmpty()){end = stack.pop();start=stack.pop();pivot = partitionHoare(array,start,end);if(pivot>start+1){stack.push(start);stack.push(pivot-1);}if(pivot+1<end){stack.push(pivot+1);stack.push(end);}}}

归并排序

分治算法+二路归并

分解:

    public static void mergeSort(int[] array){mergeSortFun(array,0, array.length-1);}private static void mergeSortFun(int[] array,int start,int end){if(start>=end){return;}//分解int mid = (start+end)/2;mergeSortFun(array,start,mid);mergeSortFun(array,mid+1,end);//合并merge(array,start,mid,end);}

归并方法

创建一个tmpArr数组记录排序好的数字

先进行s1和s2两个元素的比较,s2的元素比较小先扔到tmpArr里面,s2++

 接着再比较s2和s1,发现s1更小,扔到tmpArr里面,s1++

后面的步骤差不多,比较s1和s2两个元素,谁小谁放进数组

    private static void merge(int[] array, int left, int mid,int right) {int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;int[] tmpArr = new int[right-left+1];int k = 0;//tmpArr的下标//同时满足两个归并段都有数据while(s1 <= e1 && s2 <= e2){if(array[s1] <= array[s2]){tmpArr[k++] = array[s1++];}else{tmpArr[k++] = array[s2++];}}while(s1 <= e1){tmpArr[k++] = array[s1++];}while(s2 <= e2){tmpArr[k++] = array[s2++];}//把排好的数据拷贝回原来的数组array中for (int i = 0; i < tmpArr.length; i++) {array[i+left] = tmpArr[i];}}

时间复杂度

每次都要遍历n个元素,而分解过程分治算法和二路归并的复杂度logn

总的复杂度O(N*logN)

稳定性:稳定


非递归归并

先让每组的两个数据进行排序,接着再让两个组的四个数据进行排序

每组一个数据进行排序

两组的数据排序

 

        int gap = 1;while(gap<array.length){for (int i = 0; i < array.length; i = i+gap*2) {int left = i;int mid = left+gap-1;int right = mid+gap;merge(array,left,mid,right);}gap*=2;}

mid和right的定义方式可能会有越界的风险

所以我们需要进行风险修正

                if(mid >= array.length){mid = array.length-1;}if(right>=array.length){right = array.length-1;}

整个代码:

    public static void mergeSortNor(int[] array){int gap = 1;while(gap<array.length){for (int i = 0; i < array.length; i = i+gap*2) {int left = i;int mid = left+gap-1;int right = mid+gap;if(mid >= array.length){mid = array.length-1;}if(right>=array.length){right = array.length-1;}merge(array,left,mid,right);}gap*=2;}}

应用

前提:内存只有 1G ,需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下,所以需要外部排序,而归并排序是最常用的外部排序

1.先把文件切割成200份,每个512M

2.分别对512M排序,任意排序都行,因为内存放的下

3.进行2路归并,同时对200份有序文件做归并过程,最终结果就是有序了


排序总结


其他排序

计数排序

简单版本

有这么一组数字,要求你进行排序,注意这组数组在0~9之间

1.先申请一个计数数组count,设置一个i,定义co把每个数字出现的次数记录下来。i遍历上面的数字,每次遍历到重复的数字就co++(count[array[i] - minVal]++)

⚠计数数组上面的数字代表数组里面出现的数字,不是下标

如果不一定是以0为最小值的呢?

那我们就需要定义数组最小值minVal和最大值maxVal了

        int minVal = array[0];int maxVal = array[0];for (int i = 0; i < array.length; i++) {if(array[i]<minVal){minVal = array[i];}if(array[i]>maxVal){maxVal=array[i];}}

数组长度?

        //确定计数数组的长度int len = maxVal-minVal+1;int[] count = new int[len];
        //遍历array数组 把数据出现的次数存储到计数数组中for (int i = 0; i < array.length; i++) {count[array[i]-minVal]++;}

2.设置一个i遍历这个计数数组,把每个数字重复(如果有)记录下来并写回原来的数组

 

        //遍历计数数组,把实际的数组写回array数组int index = 0;for (int i = 0; i < count.length; i++) {while(count[i]>0){//这里需要写回array,得从array的0位置开始写array[index] = i+minVal;index++;//每次写进array一个元素,计数数组的对应元素数量就得减少count[i]--;}}

整个代码:

    public static void countSort(int[] array){//求数组最大值和最小值  O(N)int minVal = array[0];int maxVal = array[0];for (int i = 0; i < array.length; i++) {if(array[i]<minVal){minVal = array[i];}if(array[i]>maxVal){maxVal=array[i];}}//确定计数数组的长度int len = maxVal-minVal+1;int[] count = new int[len];//遍历array数组 把数据出现的次数存储到计数数组中    O(N)for (int i = 0; i < array.length; i++) {count[array[i]-minVal]++;}//遍历计数数组,把实际的数组写回array数组 //跟最大值和最小值有关系,所以是O(范围)int index = 0;for (int i = 0; i < count.length; i++) {while(count[i]>0){//这里需要写回array,得从array的0位置开始写array[index] = i+minVal;index++;//每次写进array一个元素,计数数组的对应元素数量就得减少count[i]--;}}}

时间复杂度:O(MAX(N, 范围))

空间复杂度:O(范围)

稳定性:不稳定


复杂版本(稳定版本)

这里字数太多(主要是我懒~),大家可以去看这篇博客计数排序 - 知乎 (zhihu.com)


基数排序 

基数排序动图演示

从低位到高位数字,让每位数字依次有序

代码见下:

1.10 基数排序 | 菜鸟教程 (runoob.com) 


桶排序 

【排序】图解桶排序_桶排序图解-CSDN博客

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

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

相关文章

MySQL - 库的操作

目录 1.库的操作1.1创建数据库1.2创建数据库案例 2.字符集和校验规则3.操纵数据库4.备份和恢复5.查看连接情况 1.库的操作 1.1创建数据库 语法&#xff1a; CREATE DATABASE [IF NOT EXISTS] db_name [create_specification [, create_specification] ...] create_specifica…

C/C++笔试易错与高频题型图解知识点(三)——数据结构部分(持续更新中)

目录 1. 排序 1.1 冒泡排序的改进 2. 二叉树 2.1 二叉树的性质 3. 栈 & 队列 3.1 循环队列 3.2 链式队列 4. 平衡二叉搜索树——AVL树、红黑树 5 优先级队列&#xff08;堆&#xff09; 1. 排序 1.1 冒泡排序的改进 下面的排序方法中&#xff0c;关键字比较次数与记录的初…

3.18每日一题(奇偶性、奇偶性的平移、几何意义、配方、换元)

解法一&#xff1a;先配方&#xff0c;再用三角函数换元&#xff08;看见根号一般用三角函数&#xff09;&#xff0c;看见对称区间联想奇偶性&#xff0c;最后再用公式 解法二&#xff1a; 利用奇偶性的平移&#xff0c;令&#xff08;x-1&#xff09; t &#xff0c;对应的区…

关于GPT的一些使用场景

与传统的机器翻译或语音识别技术不同&#xff0c;GPT强调的是生成新文本的能力&#xff0c;这使得它在创作、摘要、问答等场景下具有独特的优势。下面是我日常生活中用到GPT的一些场景&#xff1a; 日常闲聊 在日常闲聊中&#xff08;尤其是和运营xjj聊天的时候&#xff09;&a…

1,2,3,4,5 专家正上路

早在20世纪70年代&#xff0c;德雷福斯兄弟(Hubert Dreyfus和Stuart Dreyfus)就开始研究人类如何获取和掌握技能&#xff0c;他们考察了日常生活中常见的各项技能活动&#xff0c;如开车、下棋、体育运动等&#xff0c;提出了德雷福斯模型。它是种构建理论&#xff0c;概括了从…

树莓派安装Ubuntu22.04LTS桌面版

工具&#xff1a;树莓派4B Raspberry Pi 自己下载的ubuntu22.04LTS img磁盘镜像文件 这里有一个小技巧&#xff1a;这个Raspberry Pi的选择镜像的时候在最后面一行可以选择自定义的镜像&#xff0c;哈哈哈哈&#xff0c;这就使得我们可以自己下载&#xff0c;而且知道那个文…

burp+fiddler联动抓包

流量走向 手机流量——fiddler——burp 解决问题&#xff1a; burp对app或小程序测试响应速度较慢&#xff0c;效率较低&#xff0c;而且经常抓不到包 fiddler设置 Preferences——Settings——Connections 设置监听端口为6666 Preferences——Settings——Gateway 设置代理…

基于QT的简易计算器(一)

目录 0 简介1.设计原理1.1界面设计1.1.1界面基本布局1.1.2 界面调整和美化1.1.2 控件重命名 1.2 连接信号和槽1.3 软件逻辑1.3.1四则运算1.3.2 连续运算&#xff08;不完全&#xff09;的原理1.3.3 清屏1.3.4 退格1.3.5 等于1.3.6 小数点 2.总结与拓展 0 简介 最近在学QT&…

Ubuntu MySQL客户端功能介绍(mysql-client)mysql命令(mysql客户端命令)数据库导出、数据库导入

文章目录 Ubuntu MySQL客户端(mysql-client)功能介绍MySQL客户端与服务端服务器端&#xff08;MySQL Server&#xff09;客户端&#xff08;MySQL Client&#xff09; 安装MySQL客户端连接到MySQL服务器&#xff08;mysql -h host -u user -p&#xff09;执行SQL查询批处理模式…

java 数据结构 ArrayList源码底层 LinkedList 底层源码 迭代器底层

文章目录 数据结构总结ArrayList源码底层LinkedList底层源码 迭代器底层 数据结构 对于数据结构我这边只告诉你右边框框里的 栈的特点:后进先出,先进后出,入栈也成为压栈,出栈也成为弹栈 栈就像一个弹夹 队列先进先出后进后出 队列像排队 链表查询满 但是增删快(相对于数组而…

EViews| 基础操作 备战下周机考

目录 一、创建工作文件 1、非时间序列数据 2、时间序列数据 二、导入数据 1、导入数据 2、保存数据组合或方程结果 三、估计回归模型 1、估计回归模型 2、回归结果名词解读 四、检验模型设定错误 1、检验是否遗漏变量 2-1、检验是否加入了不相干变量 2-2、惩罚新增…

springboot2.x使用@RestControllerAdvice实现通用异常捕获

文章目录 demo地址实现效果引入基础类准备1.通用枚举与错误状态枚举2.定义通用返回结果3.自定义业务异常 统一异常捕获测试 demo地址 demo工程地址 实现效果 当我们输入1时&#xff0c;正常的返回通用的响应结果当我们输入2时&#xff0c;抛出异常&#xff0c;被捕获然后返回…

Docker学习——①

文章目录 1、什么是虚拟化、容器化&#xff1f;2、为什么要虚拟化、容器化&#xff1f;3、虚拟化实现方式3.1 应用程序执行环境分层3.2 虚拟化常见类别3.3 常见虚拟化实现3.3.1 主机虚拟化(虚拟机)实现3.3.2 容器虚拟化实现3.3.3 空间隔离实战--基础知识3.3.4 PID 隔离3.3.5 Mo…

没有PDF密码,如何解密文件?

PDF文件有两种密码&#xff0c;一个打开密码、一个限制编辑密码&#xff0c;因为PDF文件设置了密码&#xff0c;那么打开、编辑PDF文件就会受到限制。想要解密&#xff0c;我们需要输入正确的密码&#xff0c;但是有时候我们可能会出现忘记密码的情况&#xff0c;或者网上下载P…

Linux-----nginx的简介,nginx搭载负载均衡以及nginx部署前后端分离项目

目录 nginx的简介 是什么 nginx的特点以及功能 Nginx负载均衡 下载 安装 负载均衡 nginx的简介 是什么 Nginx是一个高性能的开源Web服务器和反向代理服务器。它的设计目标是为了解决C10k问题&#xff0c;即在同一时间内支持上万个并发连接。 Nginx采用事件驱动的异…

听GPT 讲Rust源代码--library/std(12)

题图来自 Decoding Rust: Everything You Need to Know About the Programming Language[1] File: rust/library/std/src/os/watchos/mod.rs 该文件&#xff08;rust/library/std/src/os/watchos/mod.rs&#xff09;的作用是为Rust标准库提供支持WatchOS操作系统的特定功能。 W…

C语言实现俄罗斯方块游戏

文章目录 1 前言2 游戏截图3 源代码 1 前言 本文介绍的是我空闲时间用C语言写的一个俄罗斯方块游戏&#xff0c;整个程序只有一个文件&#xff0c;实现了基本的游戏功能&#xff0c;但还是有些缺陷&#xff0c;希望有心之士能够继续完善&#xff0c;感谢各位&#xff01; 2 游戏…

【大数据基础平台】星环TDH社区集群版本部署

&#x1f984; 个人主页——&#x1f390;开着拖拉机回家_大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341;&#x1fa81;&#x1f341; &#x1fa81;&#x1f341;&#x1fa81;&#x1f…

Spring-Spring 之底层架构核心概念解析

BeanDefinition BeanDefinition表示Bean定义&#xff0c;BeanDefinition中存在很多属性用来描述一个Bean的特点。比如&#xff1a; class&#xff0c;表示Bean类型scope&#xff0c;表示Bean作用域&#xff0c;单例或原型等lazyInit&#xff1a;表示Bean是否是懒加载initMeth…

【云备份|| 日志 day3】服务端配置信息模块

云备份day3 使用文件配置加载一些程序的运行关键信息可以让程序的运行更加灵活&#xff0c;且当需要修改部分内容时&#xff0c;不需要在代码上修改&#xff0c;只需要修改配置文件&#xff0c;然后重启服务器即可。 配置信息 热点判断时间文件下载URL前缀路径压缩包后缀名称…