常见排序算法

  • 排序简介
  • 常见排序算法
    • 插入排序
      • 直接插入排序
      • 希尔排序
    • 选择排序
      • 选择排序
      • 堆排序
    • 交换排序
      • 冒泡排序
      • 快速排序
        • 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.mzph.cn/news/75107.shtml

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

相关文章

常用消息中间件有哪些

RocketMQ 阿里开源&#xff0c;阿里参照kafka设计的&#xff0c;Java实现 能够保证严格的消息顺序 提供针对消息的过滤功能 提供丰富的消息拉取模式 高效的订阅者水平扩展能力 实时的消息订阅机制 亿级消息堆积能力 RabbitMQ Erlang实现&#xff0c;非常重量级&#xff0c;更适…

一百七十三、Flume——Flume写入HDFS后的诸多小文件问题

一、目的 在用Flume采集Kafka中的数据写入HDFS后&#xff0c;发现写入HDFS的不是每天一个文件&#xff0c;而是一个文件夹&#xff0c;里面有很多小文件&#xff0c;浪费namenode的宝贵资源 二、Flume的配置文件优化&#xff08;参考了其他博文&#xff09; &#xff08;一&a…

OpenCV(二十四):可分离滤波

目录 1.可分离滤波的原理 2.可分离滤波函数sepFilter2D() 3.示例代码 1.可分离滤波的原理 可分离滤波的原理基于滤波器的可分离性。对于一个二维滤波器&#xff0c;如果它可以表示为水平方向和垂直方向两个一维滤波器的卷积&#xff0c;那么它就是可分离的。也就是说&#x…

无涯教程-JavaScript - DDB函数

描述 DDB函数使用双倍余额递减法或您指定的某些其他方法返回指定期间内资产的折旧。 语法 DDB (cost, salvage, life, period, [factor])争论 Argument描述Required/OptionalCostThe initial cost of the asset.RequiredSalvage 折旧结束时的价值(有时称为资产的残值)。 该…

Druid LogFilter输出可执行的SQL

配置 测试代码&#xff1a; DruidDataSource dataSource new DruidDataSource(); dataSource.setUrl("xxx"); dataSource.setUsername("xxx"); dataSource.setPassword("xxx"); dataSource.setFilters("slf4j"); dataSource.setVal…

RTSP/Onvif安防视频云平台EasyNVR视频监控汇聚平台显示视频流却无法播放,是什么原因?

EasyNVR是基于RTSP/Onvif协议的视频平台&#xff0c;拥有视频监控直播、录像、云存储、检索与回看、国标级联等视频能力&#xff0c;可支持将接入的视频流进行全平台、全终端的分发&#xff0c;分发的视频流包括RTSP、RTMP、HTTP-FLV、WS-FLV、HLS、WebRTC等格式。 有用户反馈…

LLMs之Baichuan 2:《Baichuan 2: Open Large-scale Language Models》翻译与解读

LLMs之Baichuan 2&#xff1a;《Baichuan 2: Open Large-scale Language Models》翻译与解读 导读&#xff1a;2023年9月6日&#xff0c;百川智能重磅发布Baichuan 2。科技论文主要介绍了Baichuan 2&#xff0c;一个开源的大规模语言模型&#xff0c;以及其在多个领域的性能表现…

基于云计算的区域LIS系统系统源码

在医疗机构内部&#xff0c;院内实验室主要负责本院临床科室的检验&#xff0c;院内LIS系统必须满足实验室日常的标本处理入库、仪器联机、检验结果处理、报告打印、报告发布、检验信息统计、检验信息报告发布、标本流程、外部医疗机构检验报告调阅等工作。 在医疗机构间&#…

快速排序详解

前言 快排是不稳定的排序&#xff0c;快排的适用场景是无序的序列&#xff0c;例如此时有一个数组是有序的 / 逆序的&#xff0c;此时的快排效率是最慢的。 过程&#xff1a; 找一个基准值&#xff0c;找的过程就以挖坑法的方式填坑&#xff0c;第一次排序以挖坑发填完坑之后&a…

【聚类】K-Means聚类

cluster&#xff1a;簇 原理&#xff1a; 这边暂时没有时间具体介绍kmeans聚类的原理。简单来说&#xff0c;就是首先初始化k个簇心&#xff1b;然后计算所有点到簇心的欧式距离&#xff0c;对一个点来说&#xff0c;距离最短就属于那个簇&#xff1b;然后更新不同簇的簇心&a…

[Linux]文件系统

[Linux]文件系统 文件系统是操作系统的一部分&#xff0c;负责组织、存储和管理存储在外部设备上的文件和目录&#xff0c;也就是操作系统管理外设中的文件的策略。本文讲解的是Ext2文件系统。Linux操作系统使用的就是Ext系列的文件系统。 文章目录 [Linux]文件系统了解磁盘结构…

如何选择合适的HTTP代理服务器

HTTP代理服务器是一种常见的网络代理方式&#xff0c;它可以帮助用户隐藏自己的IP地址&#xff0c;保护个人隐私和安全。然而&#xff0c;选择合适的HTTP代理服务器并不容易&#xff0c;需要考虑多个因素。本文将介绍如何选择合适的HTTP代理服务器。 了解代理服务器的类型 HTT…

Web Components详解-Shadow DOM插槽

前言 插槽实际上也属于组件通信的一种方式&#xff0c;但是由于其强大的api和实用性&#xff0c;我将其单独拆开来介绍。 定义 Slot&#xff08;插槽&#xff09;是Web Components中一个重要的特性&#xff0c;它允许在组件内部定义占位符&#xff0c;以便父组件可以向其中插…

【Java并发】聊聊ReentrantReadWriteLock锁降级和StampedLock邮戳锁

面试题 1.你说你用过读写锁&#xff0c;锁饥饿问题是什么&#xff1f; 2.有没有比读写锁更快的锁&#xff1f; 3.StampedLock知道吗?(邮戳锁/票据锁) 4.ReentrantReadWriteLock有锁降级机制策略你知道吗&#xff1f; 在并发编程领域&#xff0c;有多线程进行提升整体性能&…

流程图 and/or/xor 讲解

and表示后续2个活动同时触发&#xff0c; or表示后续2个活动可触发其中的1个或2个&#xff0c;无排他性&#xff0c;也就是每个活动的触发不影响其他活动&#xff1b; xor表示后续2个活动只触发一个&#xff0c;有排他性&#xff0c;也就是只能触发其中一个。 示例演示“OR”…

云原生Kubernetes:Yaml文件编写

目录 一、理论 1.Kubernetes与yaml文件 二、实验 1.Kubernetes与yaml文件 三、问题 1.kubectl create 和 kubectl apply区别 四、总结 一、理论 1.Kubernetes与yaml文件 &#xff08;1&#xff09;Kubernetes支持管理资源对象的文件格式 Kubernetes支持YAML 和JSON 格…

基于微信小程序的智能垃圾分类回收系统,附源码、教程

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 1 简介 视频演示地址&#xff1a; 基于微信小程序的智能垃圾分类回收系统&#xff0c;可作为毕业设计 小…

PDF文件太大怎么办?三招教会你PDF文件压缩

PDF文件太大怎么办&#xff1f;这是许多人在处理PDF文件时遇到的问题。为了帮助大家解决这个问题&#xff0c;下面总结了三个可以解决PDF文件过大问题的方法&#xff0c;需要的朋友抓紧来看看吧~ 方法一&#xff1a;使用嗨格式压缩大师 嗨格式压缩大师是一款功能强大的PDF压缩…

无涯教程-JavaScript - IMSECH函数

描述 IMSECH函数以x yi或x yj文本格式返回复数的双曲正割。复数的双曲正割被定义为双曲余弦的倒数,即 六(z) 1/cosh(z) 语法 IMSECH (inumber)争论 Argument描述Required/OptionalInumberA complex number for which you want the hyperbolic secant.Required Notes Ex…

手机usb连接电脑上网怎么做?掌握2个方法即可!

“我的电脑不知道怎么就连不上网络了&#xff0c;之前好像听说可以使用手机usb连接网络上网&#xff0c;但是不知道具体应该怎么操作。有没有知道详细操作步骤的朋友可以分享一下呀&#xff01;” 在需要临时共享手机网络连接或电脑无法连接Wi-Fi的情况下&#xff0c;将手机通过…