【数据结构】七大排序算法详解
目录
♫什么是排序
♪排序的概念
♪排序的稳定性
♪排序的分类
♪常见的排序算法
♫直接插入排序
♪基本思想
♪算法实现
♪算法稳定性
♪时间复杂度
♪空间复杂度
♫希尔排序
♪基本思想
♪算法实现
♪算法稳定性
♪时间复杂度
♪空间复杂度
♫直接选择排序
♪基本思想
♪算法实现
♪算法稳定性
♪时间复杂度
♪空间复杂度
♫堆排序
♪基本思想
♪算法实现
♪算法稳定性
♪时间复杂度
♪空间复杂度
♫冒泡排序
♪基本思想
♪算法实现
♪算法稳定性
♪时间复杂度
♪空间复杂度
♫快速排序
♪基本思想
♪算法实现
♪算法的优化
♪算法稳定性
♪时间复杂度
♪空间复杂度
♫归并排序
♪基本思想
♪算法实现
♪算法的稳定性
♪时间复杂度
♪空间复杂度
♫排序算法的比较
♫什么是排序
♪排序的概念
排序是将一组数据,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
♪排序的稳定性
将一组数据进行排序后,如果原数据与排序后的数据中相同元素的相对位置仍然保持不变,那么该排序就是一个稳定的排序,否则就不是一个稳定的排序。
注:一个本身稳定的排序可以通过不稳定的算法实现,而一个不稳定的排序是不能通过稳定的算法实现的。
♪排序的分类
排序分为内部排序和外部排序两种:
1. 内部排序:数据元素全部放在内存中的排序。2. 外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序♪常见的排序算法
常见的排序算法有插入排序(直接插入排序、希尔排序),选择排序(直接选择排序、堆排序),交换排序(冒泡排序、快速排序),归并排序等,这些排序算法也是我们接下来(以从小到大排序为例)重点要了解的东西。
♫直接插入排序
♪基本思想
直接插入排序是一种简单的插入排序算法,它的基本思想是:从第二个元素开始,每个元素都往前找合适的位置插入,直到所有的记录插入完为止,就能得到一个有序序列。
♪算法实现
//直接插入排序(从小到大)public void insertSort(int[] arr) {//空数组,不用排if (arr == null) {return;}//从第二个数开始到最后一个数for (int i = 1; i < arr.length; i++) {//将待插入的数拿出来int tmp = arr[i];int j = 0;//从后往前找合适的插入位置(待插入值比j位置的值大的位置的后面)for (j = i - 1; j >= 0; j--) {//判断待插入值是否比j位置的值小if (tmp < arr[j]) {//小,位置不对,将该位置的值往后挪,继续找arr[j + 1] = arr[j];} else {//大,找到合适位置,退出循环arr[j + 1] = tmp;break;}}//当待插入值最小时,将待插入值插入到第一个位置;当找到合适位置,将待插入值插入合适位置arr[j + 1] = tmp;}}
♪算法稳定性
当相邻的元素比较大小时,若相等,直接插入排序不会改变它们的位置,因此保证了排序前后相等元素的相对位置不变,故直接插入排序是稳定的排序。
♪时间复杂度
♩最好情况(排序一组有序序列):对n-1个元素进行插入操作,由于每个元素都不需要移动,故时间复杂度为O(n)。
♩最坏情况(排序一组逆序序列):对n-1个元素进行插入操作,每个元素对应的移动次数依次为:1、2、3、....、n-1,等差数列求和得(n-1)(1+n-1)/2=n(n-1)/2=(n^2-n)/2,故算法时间复杂度为O(n^2)。注:数组越稳定,使用直接插入排序时效率越高
♪空间复杂度
只需要一个额外的空间存放待插入值,故空间复杂度为O(1)。
♫希尔排序
♪基本思想
我们知道序列越有序,直接插入排序的效率越高,而希尔排序就是先通过局部的直接插入排序将序列变得相对有序后再进行整体的直接插入排序的排序算法,希尔排序也叫作缩小增量排序。希尔排序法的基本思想是:① 先取gap作为第一个增量,把序列根据gap分组。② 所有距离为gap的倍数的记录放在同一个组中,在各组内进行直接插入排序。③ 取第二个缩小的增量gap2,重复上述的分组和排序,直至所取的增量gap=1,即所有记录放在同一组中进行直接插入排序为止。
以gap为元素个数的一半,每次gap的值缩小一半为例:
当 gap > 1 时都是预排序,目的是让数组更接近于有序。当 gap == 1 时,数组已经接近有序的了,这样整体的直接插入排序就会很快。♪算法实现
这里依然以gap为元素个数的一半,每次gap的值缩小一半为例:
//希尔排序(从小到大)public void shellSort(int[] arr) {//可数组,不用排if (arr == null) {return;}//增量的大小取数组元素的个数的一半int gap = arr.length / 2;//增量每次缩小一半,直至为减为1for (; gap > 0; gap /= 2) {//对数组进行指定增量的直接插入排序shell(arr, gap);}}//指定增量的直接插入排序public void shell(int[] arr, int gap) {//从第一组的第二个元素开始直到整个数组的最后一个元素for (int i = gap; i < arr.length; i++) {//取出待插入的元素int tmp = arr[i];int j = 0;//从每组待插入元素的位置到该组的第一个元素for (j = i - gap; j >= 0; j -= gap) {//判断待插入值是否比j位置的值小if (tmp < arr[j]) {//小,位置不对,将该位置的值往后挪,继续找arr[j + gap] = arr[j];} else {//大,找到合适位置,退出循环arr[j + gap] = tmp;break;}}//当待插入值最小时,将待插入值插入到第一个位置;当找到合适位置,将待插入值插入合适位置arr[j + gap] = tmp;}}
♪算法稳定性
因为希尔排序的是缩小增量的插入排序(无法保证每次分组相同元素都在同一组),故希尔排序是不稳定的排序。
♪时间复杂度
希尔排序的时间复杂度根据gap取法的不同而不同,上述取法的时间复杂度约为O(n^1.25)~O(1.6*n^1.25)之间,其中n为数组中元素的个数。
♪空间复杂度
希尔排序的空间复杂度和直接插入排序一样都是O(1)。
♫直接选择排序
♪基本思想
直接选择排序的基本思想是:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。♪算法实现
//选择排序(从小到大)public void selectSort(int[] arr) {//空数组,不用排if (arr == null) {return;}//从第一个元素开始到倒二个元素for (int i = 0; i < arr.length-1; i++) {//记录i及其i后面元素的最小值int minIndex = i;//找出i及其后面最小元素的下标for (int j = i + 1; j < arr.length; j++) {if (arr[minIndex] > arr[j]) {minIndex = j;}}//将最小元素的位置移到i位置if (i != minIndex) {int tmp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = tmp;}}}
♪算法稳定性
在选择排序中,如果数组中有两个相等的元素,在选择排序的过程中,可能会先选中后面的元素,导致它们的原始位置交换,这样就破坏了它们在原数组中的相对顺序,故直接选择排序是不稳定的排序。
♪时间复杂度
对n-1个元素进行操作,每个元素对应的比较次数依次为:n-1,n-2,n-3,...,1,等差数列求和得(n-1)(1+n-1)/2=n(n-1)/2=(n^2-n)/2,故算法时间复杂度为O(n^2)。
♪空间复杂度
直接选择排序只需要一个额外的常数级别的空间来交换元素,因此直接选择排序的空间复杂度为O(1)。
♫堆排序
♪基本思想
堆排序是指利用堆这种数据结构所设计的一种排序算法,它是通过堆来进行选择数据(排升序要建大堆,排降序建小堆),是选择排序的一种。堆排序的基本思想是:①.将待排序序列构造成一个大/小根堆。②.将其与末尾元素进行交换, 此时末尾就为最大值。③.然后将剩余的个元素重新调整成一个大/小根堆,反复执行上述操作, 便能得到一个有序序列了。
♪算法实现
//堆排序(从小到大)public void heapSort(int[] arr) {//空数组,不用排if (arr == null) {return;}//创建大根堆createBigHeap(arr);int end = arr.length - 1;while (end > 0) {//将堆顶元素和堆的最后一个元素交换int tmp = arr[0];arr[0] = arr[end];arr[end] = tmp;//将剩余元素重新调整为大根堆shiftDown(arr, 0, end);//堆的个数减一end--;}}//创建大根堆private void createBigHeap(int[] arr) {//从最右边的叶子节点开始for (int parent = (arr.length - 1 - 1) / 2; parent >= 0; parent--) {//向下调整shiftDown(arr, parent, arr.length);}}//向下调整private void shiftDown(int[] arr, int parent, int len) {//child为parent的左孩子(右孩子可能不存在)int child = 2 * parent + 1;while (child < len) {//child为parent的左右孩子节点中的最小节点if (child + 1 < len && arr[child] < arr[child + 1]) {child = child + 1;}//大根堆:parent节点应该是parent节点和child节点中最大的那个节点if (arr[parent] < arr[child]) {int tmp = 0;arr[parent] = tmp;arr[parent] = arr[child];arr[child] = tmp;//继续向下调整parent = child;child = 2 * parent + 1;} else {//已经是大根堆了,退出循环break;}}}
♪算法稳定性
因为在调整堆的过程中,会进行多次元素的交换,这样可能会打破原本相等元素之间的相对位置关系,故堆排序是不稳定的排序。
♪时间复杂度
初始化堆的时间复杂度为O(n),删除操作的时间复杂度为O(logn),每删除一个元素,总元素减一,n-1次的删除操作的时间应该为:log(n)+log(n-1)+…+log(3)+log(2) = log(n!),
又因(n/2)^(n/2) ≤ n ≤ n^n,即 1/4*nlog(n) ≤ n! ≤ nlogn,去掉常数后时间复杂度为O(nlogn),故堆排序的时间复杂度为O(nlogn)。♪空间复杂度
堆排序是一种原地排序算法,所有操作都在原始的数组中进行,故堆排序的空间复杂度为O(1)。
♫冒泡排序
♪基本思想
冒泡排序可以看成冒泡的过程,每次排序都会让一个“泡泡”(指一个元素)浮到数组的正确位置。冒泡排序的基本思想是:①从数组的第一个元素开始,比较相邻的两个元素。②如果相邻的两个元素顺序不符合要求(比如升序排序时,前一个数大于后一个数),则交换这两个元素的位置。③继续比较下一个相邻的两个元素,直到数组的末尾。④重复以上步骤,每次比较时都从数组的第一个元素开始,直到数组完全有序为止。
♪算法实现
//冒泡排序(从小到大)public void bubbleSort(int[] arr) {//空数组,不用排if (arr == null) {return;}//总共需要对对n-1个元素进行比较for (int i = 0; i < arr.length - 1; i++) {boolean flg = false;//每个元素和n-1-i个元素进行比较(i为序列后面已经有序的元素)for (int j = 0; j < arr.length - 1 - i; j++) {//比较相邻两个元素,大的往后移if (arr[j] < arr[j + 1]) {int tmp = arr[j + 1];arr[j + 1] = arr[j];arr[j] = tmp;//进行过交换操作,当前序列仍未有序flg = true;}}//不需要进行交换操作,当前序列已经有序了if (flg == false) {break;}}}
♪算法稳定性
在冒泡排序中只有前后元素比较大小并进行交换,而相同元素之间是不会交换的,故冒泡排序是一种稳定的排序。
♪时间复杂度
在最坏的情况下,即序列本来就是逆序的情况下,需要进行n-1次遍历,每次遍历需要比较和交换n-i次,因此总的比较和交换次数是n(n-1)/2,故冒泡排序的时间复杂度是O(n^2)。
♪空间复杂度
因为冒泡排序只需要一个常量级别的额外空间来交换相邻的元素,故冒泡排序的空间复杂度为O(1)。
♫快速排序
♪基本思想
快速排序(Quicksort)是一种高效的排序算法,基于分治的思想,通过不断地将待排序序列划分为独立的两部分,然后对每一部分递归地进行快速排序,最终得到有序序列。 快速排序的基本思想是: 任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。♪算法实现
//快速排序(从小到大)public void quickSort(int[] arr) {//空数组,不用排if (arr == null) {return;}//对整个数组进行快速排序quick(arr, 0, arr.length - 1);}private void quick(int[] arr, int start, int end) {//递归结束条件if (end <= start) {return;}//获取基准数的位置int pivot = partition(arr, start, end);//对基准数的左边进行快速排序quick(arr, start, pivot - 1);//对基准数的右边进行快速排序quick(arr, pivot + 1, end);}
其中找基准数的代码根据基准值划分区间的方式不同,算法的实现也就不同,常见的划分区间的方式有:♩. Hoare法Hoare法的具体步骤如下:①.首先选择一个pivot元素,将待排序数组分成左右两部分;
②.然后将左右两部分分别用一个指针来遍历数组;
③.左指针指向左部分的第一个元素,右指针指向右部分的最后一个元素;
④.左指针向右移动,直到找到第一个大于等于pivot的元素;
⑤.右指针向左移动,直到找到第一个小于等于pivot的元素;
⑥.如果左指针和右指针还没有相遇,则将它们所指的元素交换;
⑦.重复步骤4-6,直到左指针和右指针相遇;
⑧.最后将pivot元素放到相遇点的位置上,使得左部分的元素都小于等于pivot,右部分的元素都大于等于pivot;
⑨.递归地对左右两部分进行排序,直到整个数组有序。
代码实现://Hoare法找基准数private int partition(int[] arr, int left, int right) {int n = left;//初始基准int pivot = arr[left];while (left < right) {//从右边开始找比基准数大的while (left < right && arr[right] >= pivot) {right--;}//从左边找比基准数小的while (left < right && arr[left] <= pivot) {left++;}//左边小的和右边打的交换int tmp = arr[left];arr[left] = arr[right];arr[right] = tmp;}//left和right相遇了,将left和初始基准数交换int tmp = arr[n];arr[n] = arr[left];arr[left] = tmp;//返回新基准数:leftreturn left;}
注:只能先从右边找比基准数大的数,如果先从左边找比基准数小的数的话最后和基准数交换的时候会把比基准数大的数换到基准数前面。♩挖坑法挖坑法的具体步骤如下:①.选定一个基准元素,通常选择第一个元素或最后一个元素。
②.将序列分为两部分,一部分为小于基准元素的部分,一部分为大于等于基准元素的部分。
③.在小于基准元素的部分中,从右到左寻找第一个大于等于基准元素的元素,将该元素赋值到基准元素的位置。
④.在大于等于基准元素的部分中,从左到右寻找第一个小于基准元素的元素,将该元素赋值到第3步所挖的坑中。
⑤.重复3、4步,直到左右两部分扫描相遇,然后将基准元素放回该位置。
⑥.递归地对左右两部分进行快速排序
代码实现:
//挖坑法找基准数 private int partition(int[] arr, int left, int right) {//记录初始基准数int pivot = arr[left];while (left < right) {//从右边开始找比基准数大的while (left < right && arr[right] >= pivot) {right--;}//将右边大的放到left位置arr[left] = arr[right];//从右边开始找比基准数大的while (left < right && arr[left] <= pivot) {left++;}//将左边小的放到left位置arr[right] = arr[left];}//left和right相遇,将初始基准数放到left位置arr[left] = pivot;//返回新基准数:leftreturn left; }
♩前后指针法前后指针法的步骤为:①.选取一个基准数,一般选择第一个数或最后一个数;
②.定义前后指针i和j,分别指向数列的开头和结尾;
③.从后往前找到第一个比基准数小的数,记录其坐标j;
④.从前往后找到第一个比基准数大的数,记录其坐标i;
⑤.如果i < j,则交换i和j的位置,使得比基准数大的数在右侧,比基准数小的数在左侧;
⑥.重复③、④、⑤步骤,直到i >= j,此时前后指针相遇;
⑦.交换基准数和前后指针相遇的位置,即将基准数放入正确的位置;
⑧.将数列分成两个部分,分别对左边和右边的部分重复以上步骤,直到整个数列有序。
代码实现:
//前后指针法找基准数private int partition(int[] arr, int left, int right) {int prev = left, cur = left+1;while (cur <= right) {while (arr[cur] < arr[left] && arr[++prev] != arr[cur]) {int tmp = arr[cur];arr[cur] = arr[prev];arr[prev] = tmp;}cur++;}int tmp = arr[left];arr[left] = arr[prev];arr[prev] = tmp;return prev;}
♪算法的优化
♩三数取中
当取到的基准数为最大或最小时,快速排序的效率是比较低的,故我们可以通过选取最左边,中间,最右边三个数的中间值降低取到的基准数最大或最小的情况。
private void quick(int[] arr, int start, int end) {//递归结束条件if (end <= start) {return;}//找到下标为start、end、(start+end)/2中的数中第二大的数的小标int MidIndex = findMidValOfIndex(arr, start, end);//确保三个数中第二大的在start位置if (MidIndex != start) {int tmp = arr[start];arr[start] = arr[MidIndex];arr[MidIndex] = tmp;}//获取下一个基准数的位置int pivot = partition(arr, start, end);//对基准数的左边进行快速排序quick(arr, start, pivot - 1);//对基准数的右边进行快速排序quick(arr, pivot + 1, end);}//找到下标为start、end、(start+end)/2中的数中第二大的数的小标private int findMidValOfIndex(int[] array, int start, int end) {int midIndex = (start+end) / 2;if(array[start] < array[end]) {if(array[midIndex] < array[start]) {return start;}else if(array[midIndex] > array[end]) {return end;}else {return midIndex;}}else {if(array[midIndex] > array[start]) {return start;}else if(array[midIndex] < array[end]) {return end;}else {return midIndex;}}}
♩小区间快排
快速排序越排是越有序的,故当待排序序列长度较小时,插入排序的性能可能比快速排序更优。因此可以在递归深度达到一定阈值时,使用插入排序来处理子序列。
private void quick(int[] arr, int start, int end) {//递归结束条件if (end <= start) {return;}//递归到小区间时,用直接插入排序if (end - start + 1 <= 15) {insertSort(arr, start, end);return;}//找到下标为start、end、(start+end)/2中的数中第二大的数的小标int MidIndex = findMidValOfIndex(arr, start, end);//确保三个数中第二大的在start位置if (MidIndex != start) {int tmp = arr[start];arr[start] = arr[MidIndex];arr[MidIndex] = tmp;}//获取下一个基准数的位置int pivot = partition(arr, start, end);//对基准数的左边进行快速排序quick(arr, start, pivot - 1);//对基准数的右边进行快速排序quick(arr, pivot + 1, end);}//直接插入排序private void insertSort(int[] arr, int left, int right) {for (int i = left+1; i <= right; i++) {int tmp = arr[i];int j = 0;for (j = i-1; j >= left; j--) {if (arr[j] > tmp) {arr[j+1] = arr[j];} else {break;}}arr[j+1] = tmp;}}
♪算法稳定性
在快速排序中,如果两个元素的值相同,它们在排序后可能会交换位置,因此快速排序是不稳定的排序。
♪时间复杂度
快速排序的时间复杂度取决于分割点选择的方法,如果每次选择中位数作为分割点,则最坏时间复杂度为O(n^2),平均时间复杂度为O(n log n);如果分割点随机选择,则最坏时间复杂度为O(n^2)的概率很小,平均时间复杂度为O(n log n)。因此,快速排序的平均时间复杂度为O(n log n),最坏时间复杂度为O(n^2)。
♪空间复杂度
快速排序的空间复杂度为 O(nlogn),其中 n 为排序的元素个数。这是因为快速排序是一种原地排序算法,它只需要将排序过程中所需的一些暂存空间复用,不会额外占用大量的内存空间。而在最坏情况下,快速排序的空间复杂度可能会退化为 O(n),但这种情况非常罕见。
♫归并排序
♪基本思想
归并排序是一种分治算法,是将一个大的问题分解成若干个小问题来解决,然后将这些小问题的解合并起来,得到原始问题的解。归并排序的基本思想是:先将待排序的序列分成两个部分,直到每个部分只有一个元素为止,再将两个单元素部分归并成一个有序序列,直到所有序列都合并成一个有序序列为止。
♪算法实现
//归并排序(从小到大)public void mergeSort(int[] arr) {mergeSortChild(arr, 0, arr.length-1);}public void mergeSortChild(int[] arr, int left, int right) {if (left <= right) {return;}int mid = (left+right) / 2;mergeSortChild(arr, left, mid);mergeSortChild(arr, mid+1, right);merge(arr,left,mid,right);}private static void merge(int[] arr,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(arr[s1] <= arr[s2]) {tmpArr[k++] = arr[s1++];}else{tmpArr[k++] = arr[s2++];}}while (s1 <= e1) {tmpArr[k++] = arr[s1++];}while (s2 <= e2) {tmpArr[k++] = arr[s2++];}//tmpArr当中 的数据 是right left 之间有序的数据for (int i = 0; i < k; i++) {arr[i+left] = tmpArr[i];}}
♪算法的稳定性
归并排序在合并两个有序子序列的时候,如果两个元素的大小相同,那么在归并的结果中,左边的元素肯定会先被放入序列中,也就是说它们的相对顺序没有改变。故归并排序是一种稳定的排序。
♪时间复杂度
归并排序在排序过程中,先将待排序的序列递归地拆分为两个子序列,每次拆分会将序列长度缩小一半。然后将两个子序列合并成一个有序的序列,合并操作的时间复杂度为O(n)。整个排序过程中,序列被拆分成了logn级别的子序列,每个子序列都要进行一次合并操作,所以时间复杂度为O(nlogn)。
♪空间复杂度
在归并排序中,需要创建一个额外的数组来保存排序的结果,在归并过程中,需要不断地合并两个有序数组,因此需要创建一个长度为n的数组来保存排序后的结果。另外,在归并排序的递归过程中,需要创建一个长度为n的临时数组来保存每次递归的中间结果,所以归并排序的空间复杂度为O(n)。
♫排序算法的比较
排序算法 最好时间复杂度 最坏时间复杂度 平均时间复杂度 空间复杂度 稳定性 冒泡排序 O(n) O(n^2) O(n^2) O(1) 稳定 插入排序 O(n) O(n^2) O(n^2) O(1) 稳定 选择排序 O(n^2) O(n^2) O(n^2) O(1) 不稳定 希尔排序 O(n) O(n^2) O(n^1.3) O(1) 不稳定 堆排序 O(n*logn) O(n*logn) O(n*logn) O(1) 不稳定 快速排序 O(n*logn) O(n^2) O(n*logn) O(logn)~O(n) 不稳定 归并排序 O(n*logn) O(n*logn) O(n*logn) O(n) 稳定
相关文章:
![](https://img-blog.csdnimg.cn/969d0f7e690f4925a1991ab574023921.png)
【数据结构】七大排序算法详解
目录 ♫什么是排序 ♪排序的概念 ♪排序的稳定性 ♪排序的分类 ♪常见的排序算法 ♫直接插入排序 ♪基本思想 ♪算法实现 ♪算法稳定性 ♪时间复杂度 ♪空间复杂度 ♫希尔排序 ♪基本思想 ♪算法实现 ♪算法稳定性 ♪时间复杂度 ♪空间复杂度 ♫直接选择排序 ♪基本思想 ♪算法…...
![](https://www.ngui.cc/images/no-images.jpg)
OpenCV之VideoCapture
VideoCaptrue类对视频进行读取操作以及调用摄像头。 头文件: #include <opencv2/video.hpp> 主要函数如下: 构造函数 C: VideoCapture::VideoCapture(); C: VideoCapture::VideoCapture(const string& filename); C: VideoCapture::Video…...
![](https://www.ngui.cc/images/no-images.jpg)
ESP32微控制器与open62541库: 详细指南实现OPC UA通信协议_C语言实例
1. 引言 在现代工业自动化和物联网应用中,通信协议起着至关重要的作用。OPC UA(开放平台通信统一架构)是一个开放的、跨平台的通信协议,被广泛应用于工业4.0和物联网项目中。本文将详细介绍如何在ESP32微控制器上使用C语言和open…...
![](https://img-blog.csdnimg.cn/b1849c22fa1e454eb3f60a9ff31777ed.png)
怎样快速打开github.com
访问这个网站很慢是因为有DNS污染,被一些别有用心的人搞了鬼了, 可以使用火狐浏览器开启火狐浏览器的远程dns解析就可以了.我试了一下好像单独这个办法不一定有用,要结合修改hosts文件方法,双重保障 好像就可以了...
![](https://img-blog.csdnimg.cn/6d970f53dae9464399ce0fe79c5ff3d6.png)
【C#】.Net基础语法二
目录 一、字符串(String) 【1.1】字符串创建和使用 【1.2】字符串其他方法 【1.3】字符串格式化的扩展方法 【1.4】字符串空值和空对象比较 【1.5】字符串中的转移字符 【1.6】大写的String和小写的string 【1.7】StringBuilder类的重要性 二、数组(Array) 【2.1】声…...
![](https://img-blog.csdnimg.cn/20190106163945739.jpg#pic_center)
C++之this指针总结(二百二十)
简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…...
![](https://img-blog.csdnimg.cn/97cbb12c1b03434ebf11b9b55032aa49.png#pic_center)
C++——如何正确的使用STL中的vector?
什么是vector? 在STL(标准模板库)中,vector是一种动态数组容器,可根据需要自动增长或缩小。它可以存储任意类型的元素,并且支持快速的随机访问。 vector是表示可变大小数组的序列容器vector采用的是连续的…...
![](https://img-blog.csdnimg.cn/9d17ac45598f42bdafd83eb6fe326df5.png)
【C语言】模拟实现内存函数
本篇文章目录 相关文章1. 模拟 memcpy 内存拷贝2. 模拟 memmove 内存移动 相关文章 【C语言】数据在内存中是以什么顺序存储的?【C语言】整数在内存中如何存储?又是如何进行计算使用的?【C语言】利用void*进行泛型编程【C语言】4.指针类型部…...
![](https://img-blog.csdnimg.cn/544b2275b77a458ebea5708d9240d8b1.png)
Jenkins学习笔记3
gitgithubjenkins: 架构图: 说明:jenkins知道github有更新了,就pull进行构建build,编译、自动化测试。然后部署到应用服务器。 maven java的项目构建工具。 在开发者电脑上创建空密码密钥对。 [rootgit-developer ~…...
![](https://img-blog.csdnimg.cn/629a5ca6385e454389e4ce2dd249c9bf.jpeg#pic_center)
基于单片机火灾报警器仿真设计
一、系统方案 1、本设计采用51单片机作为主控器。 2、DS18B20采集温度值送到液晶1602显示。 3、MQ2采集烟雾值,送到液晶1602显示。 4、按键设置温度报警值,大于报警值,声光报警。 二、硬件设计 原理图如下: 三、单片机软件设计…...
![](https://img-blog.csdnimg.cn/68a7b510cdf94d8793b0883c5df6824b.jpeg)
阿里测开面试大全(一)附答案完整版
万字长文,建议收藏 1 什么是POM,为什么要使用它? POM是Page Object Model的简称,它是一种设计思想,而不是框架。大概的意思是,把一个一个页面,当做一个对象,页面的元素和元素之间操…...
![](https://img-blog.csdnimg.cn/img_convert/92fefe765d347742fe1e88298d2fd5b8.png)
STL-常用容器
string容器 string构造函数 string本质:类 string和char*区别: char* 是一个指针 string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器。 特点: string类内部封装了很多成员方法 …...
![](https://www.ngui.cc/images/no-images.jpg)
【owt】关闭microk8s 等无关服务
打算部署下owt,发现之前跑了microk8s ,一直运行:操作指令 // 1. 启动 microk8s.start// 2. 关闭 microk8s.stop// 3. kubectl 操作 // --- 查看 cluster microk8s.kubectl cluster-info// --- 查看 nodes microk8s.kubectl get nodes// --- 查看 pods microk8s.kubectl get …...
![](https://img-blog.csdnimg.cn/c3318091f9ec49f294ddb7c91d66ec94.png)
【面试题】——Spring
1.Spring是什么? Spring是一个开源的Java应用框架,它提供了广泛的基础设施支持,用于构建Java应用程序。极大提高了开发效率。它提供了一种轻量级的编程模型,通过依赖注入(Dependency Injection)和面向切面…...
![](https://img-blog.csdnimg.cn/img_convert/a08571f736dc04b5bef51cd09e8e3a0a.gif#pic_center)
【算法思想-排序】根据另一个数组次序排序 - 力扣 1122 题
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…...
![](https://img-blog.csdnimg.cn/845290a9b8af413baa5d3d1614073270.png)
毕业设计|基于stm32单片机的app视频遥控抽水灭火小车设计
基于stm32单片机的app视频遥控抽水灭火水泵小车设计 1、项目简介1.1 系统构成1.2 系统功能 2、部分电路设计2.1 L298N电机驱动电路设计2.2 继电器控制电路设计 3、部分代码展示3.1 小车控制代码3.1 水泵控制代码 4 演示视频及代码资料获取 1、项目简介 视频简介中包含资料http…...
![](https://www.ngui.cc/images/no-images.jpg)
编译原生安卓aosp源码,实现硬改以及定位
系列文章目录 第一章 安卓aosp源码编译环境搭建 第二章 手机硬件参数介绍和校验算法 第三章 修改安卓aosp代码更改硬件参数 第四章 编译定制rom并刷机实现硬改(一) 第五章 编译定制rom并刷机实现硬改(二) 第六章 不root不magisk不xposed lsposed frida原生修改定位 第七章 安卓…...
![](https://www.ngui.cc/images/no-images.jpg)
找单身狗。一个数组中只有两个数字出现一次,其他数字出现了两次,编写一个函数找出这两个只出现一次的数字
例:在{1 2 3 4 5 6 1 2 3 4}找出5和6 方法二: 设计思想: 1.分组原理 (1)将所有数字进行异或,相同数字异或为零,所以只会剩5^6,即为异或的结果xor_result (…...
![](https://www.ngui.cc/images/no-images.jpg)
Java数据结构技巧
Java数据结构技巧 1、循环 for-each循环如果不是"[]"的数组类型,则需要提前判断数据结构是否为空,否则有可能会有空指针异常。 2、对于List对象的i到j位进行排序 for(List<String> now_result:result){List<String> sublist …...
![](https://www.ngui.cc/images/no-images.jpg)
easyui disabled 属性设置
1.设置disabled $("#id").attr("disabled",true); 或 $("#id").attr("disabled","随意字符"); easyui写法 $("#id").numberbox("textbox").attr("disabled", true); $("#id")…...
![](https://img-blog.csdnimg.cn/25f58edc04ae46759f77d3fba63e5c27.png)
使用容器运行Nginx应用及Docker命令
目录 一、使用容器运行Nginx应用 1.1 使用docker run命令运行Nginx应用 1.1.1 观察下载容器镜像过程 1.1.2 观察容器运行情况 编辑 1.2 访问容器中运行的Nginx服务 1.2.1 确认容器IP地址 1.2.2 容器网络说明 1.2.3 在主机中使用curl命令容器IP地址访问 二、Docker命…...
![](https://www.ngui.cc/images/no-images.jpg)
fastapi 基本介绍+使用
FastAPI是一个基于Python 3.6的现代、快速(高性能)的web框架,它使用Starlette作为其底层Web框架。FastAPI有很好的文档和丰富的功能,包括自动为路由生成API文档、查询参数验证、依赖注入、WebSocket等等。 以下是一个FastAPI的基…...
![](https://www.ngui.cc/images/no-images.jpg)
C语言的结构体的认识
注:类似于①、②……是代码的编写顺序,也是对下方代码的注解 【①】、【②】……是用到了之前的代码 #include <stdio.h> //②定义生日结构体,必须声明在前面不然会报错,c语言是从上到下执行的(这点要注意&#…...
![](https://www.ngui.cc/images/no-images.jpg)
只通过在vimrc文件写东西来实现或安装vim的插件
2023年9月23日,周日上午 有时候觉得用插件管理器来安装插件太麻烦了, 所以我就在想能不能只通过在vimrc文件写东西来实现或安装vim的插件, 不过这样做肯定有很大的局限性,但我会尽量做到最好的效果 不定期更新 把下面这些代码…...
![](https://img-blog.csdnimg.cn/231cc4fd84fb47459e648f40e9763a29.png)
云原生Kubernetes:K8S存储卷
目录 一、理论 1.存储卷 2.emptyDir 存储卷 3.hostPath卷 4.NFS共享存储 5.PVC 和 PV 6.静态创建PV 7.动态创建PV 二、实验 1.emptyDir 存储卷 2.hostPath卷 3.NFS共享存储 4.静态创建PV 5.动态创建PV 三、问题 1.生成pod一直pending 2.shoumount -e未显示共享…...
![](https://www.ngui.cc/images/no-images.jpg)
“五育”并举育人体系构建的实践研究课题实施方案
目录 一、研究背景与意义 二、课题理论依据 三、国内外研究情况与现状 四、研究目标...
![](https://img-blog.csdnimg.cn/75c5e8098e434817b19473afe5d12fe3.jpeg)
小样本目标检测:ECEA: Extensible Co-Existing Attention for Few-Shot Object Detection
论文作者:Zhimeng Xin,Tianxu Wu,Shiming Chen,Yixiong Zou,Ling Shao,Xinge You 作者单位:Huazhong University of Science and Technology; UCAS-Terminus AI Lab 论文链接:http://arxiv.org/abs/2309.08196v1 内容简介: 1&…...
![](https://img-blog.csdnimg.cn/3b25d543549e415abec6ddea7454ccb7.png)
Android 10.0 系统开启和关闭黑白模式主题功能实现
1. 概述 在10.0的rom系统开发定制化中,在系统SystemUI的下拉状态栏中,产品开发功能需求要求添加黑白模式功能开关的功能,就是打开黑白模式,系统颜色就会变成黑白颜色, 关闭黑白模式开关系统就会变成彩色模式,所以就需要了解下系统是怎么设置黑白模式和彩色模式的,然后添…...
![](https://www.ngui.cc/images/no-images.jpg)
Linux-VI和VIM
目录 VI的使用 VI的三种模式 进入VI 切换至插入模式(Insert mode)编辑文件 Insert 的切换 退出VI及保存文件 搜索 快捷删除 光标定位到最后一行 VIM查找字符串 全匹配 模糊匹配(正则表达式) 快速查找…...
![](https://img-blog.csdnimg.cn/f95ddae62a4e43a68295601c723f92fb.gif)
【送书】实现可观测性平台的技术要点是什么?
文章目录 实现可观测性平台的技术要点是什么?兼容全域信号量所谓全域信号量有哪些?统一采集和上传工具统一的存储后台自由探索和综合使用数据总结 实现可观测性平台的技术要点是什么? 随着可观测性理念的深入人心,可观测性平台已经开始进入了落地阶段…...
![](/images/no-images.jpg)
宁波营销型网站建设优化建站/上海百度公司总部
经常遇到这样的情况,要取得所有客户的最新交易记录,读取网站所有浏览者最后一次访问时间。一个客户只读取最新的一次记录,相同,大部分的人首先想到的就是排除所有记录,相同的只取一条。用distint,但是distint只能取到一…...
![](/images/no-images.jpg)
公司如何登录网站做就业登记/如何做好seo基础优化
第一题:账户类 题目描述 定义一个基类Account,数据成员包含string类变量userName用于保存账户主人姓名,函数成员包括默认构造函数、带参构造函数用于初始化数据成员和输出姓名的成员函PrintName()。从Account类派生出CreditAccount类…...
![](/images/no-images.jpg)
建设银行官方网站打不开/googleseo优化
参考:https://blog.csdn.net/maweifei/article/details/51221259 # 示例: img_ cv::Mat::zeros(pic_height_, pic_width_, CV_8UC1);Mat不但是一个非常有用的图像容器类,同时也是一个通用的矩阵类。 Mat矩阵(图像容器)创建时CV_8UC1、CV_8U…...
![](/images/no-images.jpg)
长春南京小学网站建设/常见的网站推广方式有哪些
10.1.2 建立方法 方法使用标准函数格式、可访问性和可选的static修饰符来声明。例如 class MyClass {public string GetString() {return "Here is a string.";} } 注意,如果使用了 static 关键字,这个方法就只能通过类来访问,不能…...
![](https://common.cnblogs.com/images/copycode.gif)
学习建设网站书籍/网站怎么推广
异常处理 1. 什么是异常处理 异常是错误发生的信号,一旦程序出错就会产生一个异常,如果该异常没有被应用程序处理,那么该异常就会抛出来,程序的执行也随之终止 异常包含三个部分: 1. traceback异常的追踪信息2. 异常的类型3. 异常的信息 错误分为两大类: 1. 语法上的错误:在程序…...
![](https://img-blog.csdnimg.cn/20210512222033440.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L20wXzQ2Mjg1ODg3,size_16,color_FFFFFF,t_70)
青岛网站搭建公司/蔡甸seo排名公司
TSP旅行售货员问题-回溯法 最近比较颓废,考试实在是太多了,月考简直了。对转专业的学生太不友好了。一大堆公共课简直消磨了我对编程的热情。 今天刚好去听了节一直逃课的晚课,老师找我谈了谈,没有怪我。我也开始思考我目标是什么…...