常见排序算法

  • 排序简介
  • 常见排序算法
    • 插入排序
      • 直接插入排序
      • 希尔排序
    • 选择排序
      • 选择排序
      • 堆排序
    • 交换排序
      • 冒泡排序
      • 快速排序
        • hoare版
        • 挖坑法
        • 前后指针法
        • 非递归实现
        • 快排优化
    • 归并排序
      • 非递归实现归并排序
      • 海量数据排序问题
    • 基数排序(不用比较就能够排序)
    • 桶排序
    • 计数排序(场景在数据指定范围内,范围小,数据集中的情况下)
    • 总结

排序简介

排序:如果没有特殊说明;我们目前是按从小到大的排序
稳定排序:假设A(3)、B(2)、C(3)、D(4)排序后的结果是BACD。A和C值相同;它们排序前后的顺序是不变的。
概念:稳定排序是指对于待排序序列中相等元素的相对位置保持不变的排序算法。换句话说,如果一个排序算法在排序过程中能保持两个相等元素的相对顺序不变,那么这个算法就可称为稳定排序算法。这个算法能实现;相等的时候不交互位置;那么就是稳定排序。(一个本身就稳定的排序,可以实现为不稳定的排序。但是一个本身就不稳定的排序 ;不能实现为稳定的排序)

内部排序:数据元素全部放在内存中的排序
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序
在这里插入图片描述

常见排序算法

插入排序

直接插入排序

在这里插入图片描述

1:开始只有一个5,然后定义i下标为1(第一个位置已经有序)
然后我们要插入4这个元素,定义j下标为0 (第一次是5一个元素有序,第2次就把4拉进来排序,第三次把3也拉进来排序,一次拉一个,跟插入元素排序一样)54321 逆序的情况是很头疼的,每一个都要交换
2:前面和后面比较,如果前面大于后面(交换位置,然后再往前比较,直到前面小于这个要插入的值就把他放进去)
如果前面小于后面则不做什么,i和j往后走(也不需要往前走,因为前面已经有序了)
代码实现:

import java.lang.reflect.Array;
import java.util.Arrays;public class Sort {public static void main(String[] args) {int []arr={3,5,1,4,2};System.out.println(Arrays.toString(insertSort(arr)));}//插入排序public static int[] insertSort(int [] array){int i=1;for (; i <=array.length-1 ; i++) {int tmp=array[i];int j=i-1;while (j>=0){if(array[j]>tmp){//进行交换位置array[j+1]=array[j];//这里一定得是j+1;不能是i。因为j是会往前走的array[j]=tmp;}else {break;}j--;}//            array[j+1]=tmp; 这行代码和前面if里的array[j]=tmp;可以选其1即可。前面的写法是每比较一个就把tmp放进去交换一个次。后面的写法是最后交互完成了才把这个tmp放进去}return array;}}}

接下来的排序都得分析这三个东西
时间复杂度(最坏情况下)O(N^2) 公式:1+2+…+(n-1)=n*(n-1)/2 .最好情况O(n)顺序情况
空间复杂度 O(1) 没开辟额外新空间浪费;用完一次循环就回收
稳定性 非常稳定 {if(array[j] > tmp)就是我们这里不能加等号,如果等了就不稳定;但是稳定的排序也是可以实现为不稳定的形式

希尔排序

比较适用于比较逆序的插入排序;也是插入排序一种。比如:中间间隔5个步数分一组;(处理逆序的极端情况有特殊作用)。每一次gap都是一个插入排序;当gap=1时就是全体的直接插入排序
在这里插入图片描述
问题在于:但是这是一个复杂的过程,不知道改分几组,几次结束。所以我们实现一下:gap=5,然后等于2,最后到1
j=i-gap;这样子就一组数据包含着gap个元素;i每次+1;而不是+2;这样子能够一遍走完就完事。
j要从0开始;那么就得i下标从gap开始,j=i-gap
排序过程如果后面的大,tmp=array [ j ]; array [ j+gap]=tmp
交换; array [ j+gap]=array [ j ],array [ j ]=tmp

在这里插入图片描述

 //希尔排序public static void  shellSort(int [] array){int gap=array.length;while (gap>1){gap=gap/2;System.out.println(Arrays.toString(shell(array, gap)));}}public static int[] shell(int[] array, int gap) {//关键在于i不再是1;而是gapint i=gap;for (; i <=array.length-1 ; i++) {int tmp=array[i];int j=i-1;while (j>=0){if(array[j]>tmp){//进行交换位置array[j+gap]=array[j];//这里注意隔gpa个位置交换array[j]=tmp;}else {break;}j--;}//            array[j+gap]=tmp; 这行代码}return array;}

(希尔和插入在逆序的情况下差距还是很大的)
时间复杂度是真不确定;你不知道要进行几次隔空交换;gap=1就是普通的插入排序。但是这一次的插入排序是比较有序的;
最坏情况下它的时间复杂度为O(n2),记一个O(n1.3)。
空间复杂度:O(1)
不稳定排序:跳跃式分组;两个相同的数;位置会改变

选择排序

选择排序

每次从待排序的元素中挑选一个最小(或者最大)的放起始位置;直到全部元素有序

逻辑:用i下标遍历数组;mindex储存最小值的下标。j从i的后一个开始遍历;遇到比mindex就更新这个值;最后遍历完交换i和mindex下标的值

时间复杂度:O(n^2)
空间复杂度:O(1)
稳定性:不稳定

  //选择排序public static void selectSort(int []array){for (int i = 0; i < array.length; i++) {int  min=array[i];int minIndex=i;int j=i+1;for (j=i+1; j <array.length; j++) {if(array[j]<array[minIndex]){min=array[j];minIndex=j;}}array[minIndex]=array[i];array[i]=min;    //不管你改变改变,反正我这个位置都是放最小值和下标}}

优化思路:定义left往后走;right后往前走;第一次过去就记录下最小和最大值。随后交换位置;直到它们相遇就结束循环
(注意细节:1:最小和最大值在下一次循环得重置;2:如果最大值在开头呢(和left相等);这种情况特殊针对一下;不然你把最大值换走了我去哪找最大值。

    //优化选择排序public static void selectSort1(int []array){int left=0;int right=array.length-1;while (left<right){int minIndex=0;int maxIndex=0;for (int j =left+1; j <right ; j++) {//找到最大、最小值下标if(array[j]<array[minIndex]){minIndex=j;}if(array[j]>array[maxIndex]){maxIndex=j;}}//交换位置swap(array,minIndex,left);//需要注意;当最大值是第一个下标的时候;你得记录一下;不然不知道换哪去了if(maxIndex==left){maxIndex=minIndex;//之所以等于minIndex;因为最大已经被上面的交换过来了}swap(array,maxIndex,right);left++;right--;}}public static void swap(int[]array,int maxIndex,int index){int max=array[maxIndex];array[maxIndex]=array[index];array[index]=max;}

堆排序

如果要排序一组数,从小到大(让下标有序):
使用小堆:这是不可能实现的;每次弹出最小的没有问题;但是放到哪去;如果放别的地方;空间复杂度就变大了;但是小堆,你也不一定就有序,左右谁大谁小不知道。
使用大堆:每次堆顶和最后一个交换。然后它再自动的排序好大堆。然后我们就不能包含这个最后的元素。交换位置由最后一个元素往前走一步(反之排序建立小堆)我都不用弹出处理交换,直接在原来数组交换。换完排序就好了。所以这才叫堆排序。
代码:
建堆这部分知识;在文章优先级队列会有详细的介绍

//建堆public class TestHeap {public int[] elem;public int usedSize;//有效的数据个数public static final int DEFAULT_SIZE = 10;public TestHeap() {elem = new int[DEFAULT_SIZE];}public void initElem(int[] array) {for (int i = 0; i < array.length; i++) {elem[i] = array[i];usedSize++;}}/*** 时间复杂度:O(n)*/public void createHeap() {for (int parent = (usedSize - 1 - 1) / 2; parent >= 0; parent--) {//统一的调整方案shiftDown(parent, usedSize);}}private void shiftDown(int parent, int len) {int child = 2 * parent + 1;//1. 必须保证有左孩子while (child < len) {//child+1 < len && 保证有右孩子if (child + 1 < len && elem[child] < elem[child + 1]) {child++;}//child下标 一定是左右孩子 最大值的下标/* if(elem[child] < elem[child+1] && child+1 < len ) {child++;}*/if (elem[child] > elem[parent]) {int tmp = elem[child];elem[child] = elem[parent];elem[parent] = tmp;parent = child;child = 2 * parent + 1;} else {break;}}}//堆排序public void heapSort(int []array){int usedSize=array.length;//usedSize是有效元素个数int end=usedSize-1;while (end>0){//交换0位置和最后的位置;最后的位置放最大值;每次往前走int tmp=elem[0];elem[0]=elem[end];elem[end]=tmp;shiftDown(0,end);end--;//end传的是数组元素下标,10个元素,我减1。,是不是只调整9个元素。每次结束就少一个元素调整(end--)}}

时间复杂度:建立堆的复杂度O(n)
O(n) +O(nlogn)约等于O(nlogn)
空间复杂度O(1);没有浪费,创建额外的空间

交换排序

冒泡排序

外循环遍历一遍;内循环遍历两两之间;如果前一个元素比后一个元素大就交互位置。这样子每一轮下来就把最大值放到最后面。而后面放好的最大值元素就无需在下一次继续比较。所以循环条件是 j <array.length-1-i

    //冒泡排序public static void bubbleSort(int []array){for (int i = 0; i <array.length-1 ; i++) {for (int j = 0; j <array.length-1-i ; j++) {//之所以要减i;因为遍历了i次;后面的i个元素已经是最大的排好序if(array[j]>array[j+1]){swap(array,j,j+1);}}}}

时间复杂度:O(n^2) 优化后最好O(n)
空间复杂度:O(1)
稳定性:稳定

快速排序

hoare版

逻辑:先定义一个pivot ,把最开头的6放到里面。。然后从后面往前出发找到比pivor小的数,这时候前面往后走,找到比pivot大的数。两个交换。 换完之后继续从后面那个往前找比6小,找到就前面继续往后找比6大的,然后交换。。直到相遇,把相遇的东西值放到第一个位置,再把这个6放到这个相遇的位置。看图说话
在这里插入图片描述
代码实现:
代码框架:
在这里插入图片描述
partition实现:
在这里插入图片描述

//快排private static void quick(int[] array,int start,int end) {if(start >= end) {//问题1:这里能不能不写大于号呢?预防没有左边或者右边情况//假设第一次就是有序的情况下;start和end都直到最开始的位置相遇;再往下走的 quick(array,start,pivot-1);就数组越界了return;}int pivot = partition(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}public static void quickSort(int []array){quick(array,0,array.lemgth-1);	}private static int partition(int[] array, int left, int right) {int i=left;int pivot=array[left];whlie(left<right){while(left<right&&pivot<=array[right]){ //这里的条件就是跳过比基准大的//问题2:为什么要从右边先开始找//问题3:为什么这里要取等呢?right--;}while(left<right&&pivot>=array[left]){//跳过比基准小的left++;}			swap(array,left,right);}swap(array,left,i);return left;}

针对问题2:为什么从右边开始移动;为了保证当left和right相遇时,left指向的元素是小于pivot的。因为我们最后是要将pivot和这个相遇的交换位置

针对问题3:结合代码分析就会发现;这种情况是两个循环都进不去;外部循环却是left一直小于right;死循环
在这里插入图片描述
在这里插入图片描述

时间复杂度:O(N*logN)找基准一步一步分割,向一颗二叉树。每一层总和都是N的大小在找大小,遍历范围是N。然后一共有logn层(树的高度)
空间复杂度:O(logn)左边结束回收,右边一样创建一样大小
稳定性:不稳定
在这里插入图片描述

挖坑法

逻辑:后面R往前找比6小的(5)放第一个坑位,然后前面往后走找到比6大,放后面多出来坑位。相遇自己把自己放进去。最后出来把这个基准丢进去
在这里插入图片描述

    //快排private static void quick(int[] array,int start,int end) {if(start >= end) {return;}int pivot = partition(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}public static void quickSort(int []array){quick(array,0,array.lemgth-1);	}public static int partition1(int[] arr,int left,int right) {int pivot = arr[left];while(left < right) {while(left < right && arr[right] >= pivot) {right--;}arr[left]=arr[right];//画个图走一遍就好理解while (left < right && arr[left] <= pivot) {left++;}arr[right]=arr[left];}arr[left]=pivot;return left;}

两种不同的方式实现,下来第一次的结果不一样,一般情况用挖坑法。还是挖坑法比较好理解和实现。

前后指针法

在这里插入图片描述

逻辑:prev在0位置,cur在1位置开始:以第一个为基准。用cur的值去和基准的值比较;
如果cur下的值比较小;那就prev先走一步。在这时候cur和prev就相遇了(这有什么好处呢?这样子我们就可以通过判断cur和prev是不是在同一个位置;如果在同一个位置就说明当前遇到的值是小的不需要交换。判断需不需要交换的条件)
如果遇到cur当前比较大的值;prev就先不要动(prev是在大于基准值的前一个位置);这时候两个if条件都不会进去的;cur继续往后走;找到一个小于基准的值。然后if条件进去;prev往后走一步;并且 arr[prev] != arr[cur];进行交换。

最后prev和头的基准交换(当cur走完的时候,prev所在的位置就是基准,但是你返回前得把开始的基准值跟这个基准位所在的值换一下)

 //快排private static void quick(int[] array,int start,int end) {if(start >= end) {return;}int pivot = partition(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}public static void quickSort(int []array){quick(array,0,array.lemgth-1);	}
public static int partition2(int[] arr,int left,int right) {//前后指针法int prev = left;int cur = left + 1;int pivot = arr[left];while(cur <= right) {if(arr[cur]<arr[left]){prev=prev++;}if(arr[cur] <arr[left] && arr[prev] != arr[cur]) {swap(arr,prev,cur);}cur++;}swap(arr,left,prev);return prev;}

只能说设计的非常巧妙;但是代码非常不好理解;自己在画图板进行走一遍比较好理解。
举例:开始prev先走一步;cur和prev在值为1的位置相遇。我们判断一下他们位置是不是一样;一样就不交换。cur往后走。反复这个过程。
直到两个人在2的位置相遇;现在cur要走到7的位置;判断发现比6大;prev就停下来;不走。cur往后走;遇到比6大的还是继续往后在;直到遇到比6小的3;prev就可以往后走一步到7的位置;然后他们两个位置不相等;就进行交换。
在这里插入图片描述

非递归实现

模拟递归的流程去走:申请一个栈;先获取一下基准是在哪里。然后就按基准划分;分而治之;把两边的left和right加入栈里。判断栈为空吗;不为空取出两个去走partition。注意左边和右边只有一个元素时就不需要入栈和出栈;存的顺序是先左后右;取的话就先赋值给右再赋值给左

public static void quickSort1(int[] arr) {Stack<Integer> stack = new Stack<>();int left = 0;int right = arr.length - 1;int pivot = partition(arr,left,right);//如果只有一个元素;那就直接有序;没必要再走这些流程//判断左边是不是有两个元素if(left < pivot - 1) {stack.push(left);stack.push(pivot - 1);}//判断右边是否有两个元素if(right > pivot + 1) {stack.push(pivot + 1);stack.push(right);}while (!stack.isEmpty()) {right = stack.pop();left = stack.pop();pivot = partition(arr,left,right);//判断左边是不是有两个元素if(left < pivot - 1) {stack.push(left);stack.push(pivot - 1);}//判断右边是否有两个元素if(right > pivot + 1) {stack.push(pivot + 1);stack.push(right);}}}

快排优化

优化:当数据趋于有序,我们都使用插排。当快速排序在最后几层时,数组已经趋于有序。因为递归到小的区间;这时候的递归量是非常多的;而且数据也是比较有序;建议使用快排。犹如一颗满二叉树;越到下面;节点个数越多。
三数取中法:
三个数(头尾中间)找中位值,把这个位置换到0位置,然后再开始我们的快速排序。三个数,一个都不知道,怎么求中位值大小?
(问题是怎么找到这三个数中中间大小的数;而且它们是一直在变化的;那就只能分情况处理)

public static int findMidValueOfIndex(int[] arr,int start,int end) {int mid = (end + start) / 2;if(arr[start] < arr[end]) {if(arr[mid] < arr[start]) {return start;}else if(arr[mid] > arr[end]) {return end;}else {return mid;}}else {if(arr[mid] < arr[end]) {return end;}else if(arr[mid] > arr[start]) {return start;}else {return mid;}}}
public static void quick(int[] arr,int start,int end) {if(start >= end) {return;}//因为随着排序次数增多;基准就把元素分组的更多;这时候使用插排更快if((end - start + 1) <= 15) {insert(arr,start,end);}//在进行partition尽量去解决不均匀问题int mid = findMidValueOfIndex(arr,start,end);swap(arr,mid,start);int pivot = partition2(arr,start,end);quick(arr,start,pivot - 1);quick(arr,pivot + 1,end);}public static void insert(int[] arr,int left,int right) {for (int i = left + 1; i <= right; i++) {int j = i + 1;for (; j >= 0; j--) {if(arr[j] > arr[i]) {arr[j + 1] = arr[j];}else {break;}}arr[j + 1] = arr[i];}}private 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 {//array[j+1] = tmp;break;}}array[j+1] = tmp;}}

在这里插入图片描述

归并排序

分而治之:针对一个数组,取中间下标的值,然后把数组分成以下[start,mid],[mid+1,right]两个区间,接着,把左边部分的数组继续取中间值,然后不断递归下去。右边数组,同样的方式,继续递归下去。直到左下标与右下标相等。
在这里插入图片描述
如何分解:(也是一个二叉树递归过程)分解成一个一个元素后,返回合并。
代码框架:
在这里插入图片描述
在这里插入图片描述
整体代码:

  public static void mergeSort1(int[] array) {mergeSortChild(array,0,array.length-1);}private static void mergeSortChild(int[] array,int left,int right) {if(left == right) {return;}int mid = (left+right) / 2;mergeSortChild(array,left,mid);mergeSortChild(array,mid+1,right);//合并merge(array,left,mid,right);}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++];}//tmpArr当中 的数据 是right  left 之间有序的数据for (int i = 0; i < k; i++) {array[i+left] = tmpArr[i];}}

每一层都有N个元素,在不断分解数组的过程当中,分解的层数为log以2为底n的对数,由于每层都有N个元素,因此分解过程的时间复杂度为O(Nlog以2为底N的对数);即:O(Nlog(N))。空间复杂度:每一层都开辟了一个大小为[end-start+1]的数组,因此空间复杂度为O(N)。

1.归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。
2.时间复杂度:O(N*logN)
3.空间复杂度:O(N)
4.稳定性:稳定

非递归实现归并排序

一个有序,变两个有序;然后变4个有序;再变八个有序。gap先是一个一个有序;然后两个;四个;直到gap<array.length就结束

 public static void mergeSort(int[] array) {int gap = 1;while (gap < array.length) {for (int i = 0; i < array.length; 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 份,每个 512 M
2:分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以
3:进行 2路归并,同时对 200 份有序文件做归并过程,最终结果就有序了

基数排序(不用比较就能够排序)

空间换取时间,入的次数和出的次数取决于数据里面的最大值。先把个位的排序好;这样子然后有相同数字的数;或者后面它们十位是相同的那就也是有序的。
在这里插入图片描述

桶排序

在这里插入图片描述

计数排序(场景在数据指定范围内,范围小,数据集中的情况下)

比如范围0-n;创建n大小的数组,每一个下面都放0;然后遍历我的这组数;遇到这个数一次就在这个下标放个1;再遇到一次就这个下标放的值再加1;然后打印这个数组,值为0不打印;值为1打印下标一次,值为2打印下标两次。

实现:怎么找n;遍历一遍数组,找到最大值与最小值的差值。比如90-99.这时候就是90放0下标

  //计数排序
public static void countSort(int[] arr) {int min = arr[0];int max = arr[0];//找最大值 最小值for (int i = 0; i < arr.length; i++) {if(arr[i] < min) {min = arr[i];}if(arr[i] > max) {max = arr[i];}}//创建一个计数数组,数组大小为数组值的取值范围int len=max - min + 1;int[] countArr = new int[len];//统计每个数字出现的次数for (int i = 0; i < arr.length; i++) {int val = arr[i];countArr[val-min] ++;}int index = 0;//遍历计数数组,看每个下标的值是几,就按顺序给原数组赋值;记得加上minfor (int i = 0; i < countArr.length; i++) {while (countArr[i] > 0) {arr[index] = i+min;//index得在循环外面定义赋值;这样才能保证是连续往上增加的index++;countArr[i]--;//countArr[i]是统计了;一个数出现的次数;出现几次我们就按顺序赋值几次}}//经过上述操作;arr就有序了
}

时间复杂度:O(n+数值范围)
空间复杂度:O(范围)
稳定的排序

总结

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

Zoom正式发布类ChatGPT产品—AI Companion

9月6日&#xff0c;全球视频会议领导者Zoom在官网宣布&#xff0c;正式发布生成式AI助手——AI Companion。 AI Companion提供了与ChatGPT类似的功能&#xff0c;包括根据文本对话起草各种内容&#xff0c;自动生成会议摘要&#xff0c;自动回答会议相关问题等&#xff0c;以帮…

Windows下安装配置Nginx

nginx安装 官网下载地址 https://nginx.org/en/download.html 推荐使用稳定版本 截止时间2023年9月5日稳定版本为 1.24.0 百度网盘 链接&#xff1a;https://pan.baidu.com/s/1cXm-jN2fMzKdVMRhbG72Fg 提取码&#xff1a;9hcq 下载完成以后,得到nginx压缩包; 双击启动nginx.…

3D目标检测数据集 KITTI(标签格式解析、点云转图像、点云转BEV)

本文介绍在3D目标检测中&#xff0c;理解和使用KITTI 数据集&#xff0c;包括KITTI 的基本情况、下载数据集、标签格式解析、点云转图像、点云转BEV。 目录 1、KITTI数据集中3D框可视化的效果 2、先看个视频&#xff0c;了解KITTI 的基本情况 3、来到KITTI官网&#xff0c;下…

电脑提示“系统找不到指定的文件”怎么办?

“系统找不到指定的文件”对于Windows用户来说是一个很常见的错误&#xff0c;尤其是Win10用户&#xff0c;经常会遇到Win10提示找不到指定文件。在此错误后面有时还会出现错误代码&#xff1a;0x80070002&#xff0c;但是&#xff0c;故障类型或代码在不同的操作系统规范上是不…

文本生成模型如何解码

文章目录 解码方法Greedy SearchBeam SearchsamplingTemperature Samplingtop-k samplingTop-p (nucleus) samplingContrastive search 总结相关资源 语言模型如何对于一个给定输入生成相应的输出呢&#xff1f;答案是使用解码策略(decoding strategy)。这里对现有的解码策略做…

用python实现基本数据结构【02/4】

*说明 如果需要用到这些知识却没有掌握&#xff0c;则会让人感到沮丧&#xff0c;也可能导致面试被拒。无论是花几天时间“突击”&#xff0c;还是利用零碎的时间持续学习&#xff0c;在数据结构上下点功夫都是值得的。那么Python 中有哪些数据结构呢&#xff1f;列表、字典、集…

【白话机器学习系列】白话梯度下降

白话梯度下降 梯度下降是机器学习中最常见的优化算法之一。理解它的基本实现是理解所有基于它构建的高级优化算法的基础。 文章目录 优化算法一维梯度下降均方误差梯度下降什么是均方误差单权重双权重三权重三个以上权重 矩阵求导结论 优化算法 在机器学习中&#xff0c;优化是…

ChatGPT实战与私有化大模型落地

文章目录 大模型现状baseline底座选择数据构造迁移方法评价思考 领域大模型训练技巧Tokenizer分布式深度学习数据并行管道并行向量并行分布式框架——Megatron-LM分布式深度学习框架——Colossal-AI分布式深度学习框架——DeepSpeedP-tuning 微调 资源消耗模型推理加速模型推理…

Python批处理(一)提取txt中数据存入excel

Python批处理&#xff08;一&#xff09;提取txt中数据存入excel 问题描述 现从冠层分析软件中保存了叶面积指数分析的结果&#xff0c;然而软件保存格式为txt&#xff0c;且在不同的文件夹中&#xff0c;每个文件夹的txt文件数量不固定&#xff0c;但是txt文件格式固定。现需…

C#__多线程之任务和连续任务

/// <summary> /// /// 任务&#xff1a;System.Threading.Tasks&#xff08;异步编程的一种实现方式&#xff09; /// 表应完成某个单元工作。这个工作可以在单独的线程中运行&#xff0c;也可以以同步方式启动一个任务。 /// /// 连续任务&#…

thinkphp6-简简单单地开发接口

目录 1.前言TP6简介 2.项目目录3.运行项目运行命令访问规则 4.model db使用db连接配置model编写及调用调用接口 5.返回json格式 1.前言 基于上篇文章环境搭建后&#xff0c;便开始简单学习上手开发接口…记录重要的过程&#xff01; Windows-试用phpthink发现原来可这样快速搭…

如何使用SQL SERVER的OpenQuery

如何使用SQL SERVER的OpenQuery 一、OpenQuery使用说明二、 OpenQuery语法2.1 参数说明2.2注解 三、示例3.1 执行 SELECT 传递查询3.2 执行 UPDATE 传递查询3.3 执行 INSERT传递查询3.4 执行 DELETE 传递查询 一、OpenQuery使用说明 在指定的链接服务器上执行指定的传递查询。 …

电工什么是电动势

什么是电动势&#xff1f;及电源电动势计算公式与方向确定 前面我们讲到在基本电路中的电流和电压的基础知识&#xff0c;而本文要讲的电动势和电压是一个很类似的概念。那么什么是电动势&#xff1f;电源电动势的计算公式是什么&#xff1f;它的方向如何确定及与电压有什么区…

轻量容器引擎Docker基础使用

轻量容器引擎Docker Docker是什么 Docker 是一个开源项目&#xff0c;诞生于 2013 年初&#xff0c;最初是 dotCloud 公司内部的一个业余项目。 它基于 Google 公司推出的 Go 语言实现&#xff0c;项目后来加入了 Linux 基金会&#xff0c;遵从了 Apache 2.0 协议&#xff0c;…

【Redis】深入探索 Redis 的数据类型 —— 哈希表 hash

文章目录 前言一、hash 类型相关命令1.1 HSET 和 HSETNX1.2 HGET 和 HMGET1.3 HKEYS、HVALS 和 HGETALL1.4 HEXISTS 和 HDEL1.5 HLEN1.6 HINCRBY 和 HINCRBYFLOAT1.7 哈希相关命令总结 二、hash 类型内部编码三、hash 类型的应用场景四、原生&#xff0c;序列化&#xff0c;哈希…

Android相机-架构3

目录 引言 1. Android相机的整体架构 2. 相机 HAL 2.1 AIDL相机HAL 2.2 相机 HAL3 功能 3. HAL子系统 3.1 请求 3.2 HAL和相机子系统 3.2.1 相机的管道 3.2.2 使用 Android Camera API 的步骤 3.2.3 HAL 操作摘要 3.3 启动和预期操作顺序 3.3.1 枚举、打开相机设备…

C语言课程作业

本科期间c语言课程作业代码整理&#xff1a; Josephus链表实现 Josephus 层序遍历树 二叉树的恢复 哈夫曼树 链表的合并 中缀表达式 链接&#xff1a;https://pan.baidu.com/s/1Q7d-LONauNLi7nJS_h0jtw?pwdswit 提取码&#xff1a;swit

《TCP/IP网络编程》阅读笔记--进程间通信

目录 1--进程间通信 2--pipe()函数 3--代码实例 3-1--pipe1.c 3-2--pipe2.c 3-3--pipe3.c 3-4--保存信息的回声服务器端 1--进程间通信 为了实现进程间通信&#xff0c;使得两个不同的进程间可以交换数据&#xff0c;操作系统必须提供两个进程可以同时访问的内存空间&am…

MySQL之MHA高可用配置及故障切换

目录 一、MHA概念 1、MHA的组成 2、MHA的特点 3、主从复制有多少种复制方法 二、搭建MySqlMHA部署 1&#xff0e;Master、Slave1、Slave2 节点上安装 mysql 2&#xff0e;修改 Master、Slave1、Slave2 节点的 Mysql主配置文件/etc/my.cnf 3. 配置 mysql 一主两从 4、安…

关于el-input和el-select宽度不一致问题解决

1. 情景一 单列布局 对于上图这种情况&#xff0c;只需要给el-select加上style"width: 100%"即可&#xff0c;如下&#xff1a; <el-select v-model"fjForm.region" placeholder"请选择阀门类型" style"width: 100%"><el-o…