【排序算法】快速排序(全坤式超详解)———有这一篇就够啦

【排序算法】——快速排序

目录

一:快速排序——思想

二:快速排序——分析

三:快速排序——动态演示图

四:快速排序——单趟排序

4.1:霍尔法

4.2:挖坑法

4.3:前后指针法

五:快速排序——递归实现

5.1:快速排序--->常规法

5.2:快速排序--->三路划分法

六:快速排序——非递归实现

七:快速排序——优化

7.1:快速排序优化--->三数取中选key法

7.2:快速排序优化--->随机数生成选key法

7.3:快速排序优化--->小区间改造

八:快速排序——特性总结


一:快速排序——思想与大致框架

        快速排序是Hoare(霍尔)于1962年提出的一种二叉树结构的交换排序方法。

其基本思想为:

  1. 任取待排序元素序列中的某元素作为基准值,
  2. 按照该排序码将待排序集合分割成两子序列左子序列中所有元素均小于基准值右子序列中所有元素均大于基准值
  3. 然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。

 由快排思想可以推出快速排序的大致框架如下:

#include <stdio.h>// 假设按照升序对array数组中[begin, end]区间中的元素进行排序void QuickSort(int array[], int begin, int end) 
{if (begin >= end){return;}// 按照基准值对array数组的 [begin, end]区间中的元素进行划分int keyi = PartSort(array, begin, end);// 划分成功后以keyi为边界形成了左右两部分 [begin, keyi-1] keyi [div+1, end]// 左部分都是比 keyi 位置上的值小的部分,右部分都是比 keyi 位置上的值大的部分。// 递归排左部分[begin, keyi-1]QuickSort(array, begin, keyi);// 递归排右部分[keyi+1, end]QuickSort(array, keyi+1, end);}int main()
{int a[] = { 2,5,7,1,4,9,6,3,8,0 };int sz = sizeof(a) / sizeof(a[0]);    // 求取数组内元素个数QuickSort(a, 0,sz-1);                // 传递的都是下标return 0;
}

        我们发现与二叉树前序遍历规则非常像,所以我们在分析快速排序过程中的递归框架时可想想二叉树前序遍历规则即可理解并快速写出来,在后序只需分析如何按照基准值来对区间中数据进行划分的方式即可。 

二:快速排序——分析

        对于快速排序,重点就在于基准值 key 的位置,知道 key 的位置之后,分别再对左右两边部分再找 基准值 key 的位置,依次在各个部分区间内找 基准值 key,通过一遍又一遍的递归,到最后区间内只有一个数时,这个递归也就结束了。具体情况,大家可以通过快速排序的动态演示图和递归分解图进行分析。

三:快速排序——动态演示图

快速排序递归演示图:

我们发现它大致就是一个二叉树的前序遍历形态。大家可以一边看图一边进行分析。 

四:***快速排序——单趟排序****

将区间按照基准值划分为左右两半部分的常见方式有:1.霍尔法;2.挖坑法;3.前后指针法

4.1:霍尔法

        因为霍尔是最早实现快速排序的人,所以霍尔法也是整个快排最早的版本。

单趟排序的目的:将区间按照基准值划分为左右两半部分,左边部分比基准值小,右边部分比基准值大。

 霍尔法单趟过程分析:

  1. 先记录下基准值key的位置,让 left 和 right 向两端靠近(直至相遇)。
  2. right 小兵先走,直到遇到一个比 key 值要小的数字就停下。
  3. right 小兵停下后,left 小兵再走,直到遇到一个比 key 值要大的数字就停下。
  4. 交换 left 位置和 right 位置上的值。
  5. right 小兵继续走,重复 2,3,4动作,直到 left 小兵与 right 小兵相遇
  6. 相遇之后,将相遇位置的值与基准值 key 位置上的值交换,让相遇位置置成新的 key。

注意:基准值 key 在左边, right 小兵先走;基准值 key 在右边,left 小兵先走。

那么,相信大家会有这样的疑问,如果相遇位置的值比基准值 key 位置上的值大怎么办?无需担心,相遇位置的值一定就是比基准值 key 位置上的值小

这需要两个方面进行分析:一方面是 key 在左边,另一方面就是 key 在右边。

key 位置在左边

相遇位置值分析:

若 left 小兵与 right 小兵相遇,又有两种情况:1. left 小兵走的时候,遇到 right 小兵(L遇);2.right 小兵走的时候,遇到 left 小兵(R遇L)

1. left 小兵走的时候,遇到 right 小兵

 因为是 key 位置在左边, right 小兵先走,所以当 right 小兵停下时,其位置上的值一定是比 key 位置上的值小的。这时,left 小兵来了, 两个小兵相遇,相遇的位置就是 right 小兵停下的位置,即相遇的位置比 key 位置上的值要小。

2. right 小兵走的时候,遇到 left 小兵

因为是 key 位置在左边, right 小兵先走。经过几轮交换之后,相遇的位置就是 left 小兵的位置,此时,因为经过了上一轮 left 位置上的值 与 right 位置上的值 交换。left 位置上的值就是上一轮交换中 right 停下位置上那个比 key 值小的值。即交换之后 left 位置上的值是比 key 位置上的值要小的,所以相遇的位置比 key 位置上的值要小。

同理,key 位置在右边的时候,也是相同的情况分析。

下面我们来看一看 hoare 版本的代码,一起来分析一下。

// 单趟排序
//		1.霍尔法
int PartSort1(int* a, int left, int right)
{int keyi = left;                // 记录下 key 的位置while (left < right)            // 当 left 与 right 相遇时退出循环{// 右边找小while (left < right && a[right] >= a[keyi]){--right;}// 左边找大while (left < right && a[left] <= a[keyi]){++left;}// 此时 right 位置上的值要比 keyi 位置上的值小,left 位置上的值要比 keyi 位置上的值大// 交换 left 位置与 right 位置上的值。Swap(&a[left], &a[right]);      // 交换后 left 位置上的值比 keyi位置上的值小, right 位置上的值比 keyi 位置上的值大。}// left 与 right 相遇Swap(&a[left], &a[keyi]);keyi = left;            // 生成新的 keyi 位置return keyi;
}// 霍尔单趟排序之后, keyi 位置左边的部分都比 keyi位置的值要小,keyi 位置右边的部分都比 keyi位置的值要大。

4.2:挖坑法

挖坑法的思路与霍尔法的思路大致相同。

挖坑法思路过程分析:

  1. 先将 key 的值存起来,注意:此处的 key 存的是值,而不是位置下标。将该数据位置看作是一个坑(记作是 hole )。
  2. 最初时,left 小兵在最左边(下标为0的位置),right 小兵在最右边。
  3. 如下动图中,因为 hole坑在最左边,所以还是 right 小兵先走,找比 key值要小的值。找到之后将 right 位置上的值放到原来的坑上,在将此时 right 位置 记作新坑
  4. right 位置上形成一个新坑后,left 小兵出发,找比 key 值要大的值。找到之后,将 left 位置上的值放到原来的坑上,在将此时 left 位置 记作新坑
  5. left 位置上形成新坑后,right 小兵再走,重复3,4动作,直到 left 小兵与 right 小兵相遇。
  6. 相遇之后,将坑上填入 key 值。
  7. 最后返回 hole 最后的位置,这个位置就是基准值。

可以确定:两个小兵相遇的位置一定是一个坑。

注意:有坑的小兵不走;填坑时,要先将原来的坑给补上,再建立新坑。

 单趟排序挖坑法代码实现:

// 2.挖坑法
int PartSort2(int* a, int left, int right)
{int key = a[left];            // 将基准值存起来int hole = left;              // 建立第一个坑while (left < right){// 右边找小while (left < right && a[right] >= key){--right;}a[hole] = a[right];        // 填旧坑hole = right;              // 建新坑// 左边找大while (left < right && a[left] <= key){++left;}a[hole] = a[left];hole = left;}a[hole] = key;        // 最后一个坑填 基准值 keyreturn hole;          // 返回基准值的下标
}

4.3:前后指针法

这三种单趟排序的方法思想都是差不多的。不过这种方法不仅是思路还是实现效率都比其他两中方法要好一些,同时这种方法也是大众比较流行的方法之一。

前后指针法思路过程分析:

  1. 先记录下基准值key的位置,不过这种方法不是 right 小兵和 left 小兵往中间走了,而是先用一个 “指针prev” 记录left 的位置,再用一个 “指针cur” 记录 left+1 的位置。
  2. 此时 cur 小兵要找比 key 位置上的值要小的,找到之后,并且 prev+1 != cur,就让 prev+1 的位置上的值与 cur 位置上的值进行交换。
  3. 交换后 cur++,prev++。
  4. 依次重复2,3直至结束循环(cur > right)
  5. 最后将 prev 位置上的值与 key 位置上的值进行交换。再 key = prev。
  6. 返回 key 位置的下标

  单趟排序前后指针法代码实现:

// 3.前后指针法
int PartSort3(int* a, int left, int right)
{int prev = left;            // 定义一个 prev “指针”int cur = left + 1;         // 定义一个 cur “指针”int keyi = left;            // 先确定基准值的位置while (cur <= right){while (a[cur] <= a[keyi] && ++prev != cur)    // cur指针找小,并且 prev先+1,加1之后再进行交换(简化代码){Swap(&a[cur], &a[prev]);}++cur;}Swap(&a[prev], &a[keyi]);        // 交换 key 位置上的值与 prev 位置上的值keyi = prev;return keyi;
}

五:快速排序——递归实现

5.1:快速排序--->常规法

所谓常规法,就是按照我们前面的思路对快速排序进行总结实现,无任何添加,即是常规。

#include<stdio.h>// 快排单趟排序
//        前后指针法
int PartSort(int* a, int left, int right)
{int prev = left;int cur = left + 1;int keyi = left;while (cur <= right){while (a[cur] <= a[keyi] && ++prev != cur){Swap(&a[cur], &a[prev]);}++cur;}Swap(&a[prev], &a[keyi]);keyi = prev;return keyi;
}// 快排递归实现
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}int keyi = PartSort(a, begin, end);// [beign,keyi-1] keyi [keyi+1,end]QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}// 快速排序
int main()
{int a[] = { 2,5,7,1,4,9,6,3,8,0 };int sz = sizeof(a) / sizeof(a[0]);QuickSort(a, 0,sz-1);return 0;
}

5.2:快速排序--->三路划分法

万事总有漏洞,但总会有大佬来填补这些漏洞。

当一个数组序列中含有多个相同元素的时候,单纯的使用常规法已经不能发挥出独属于快排的全部威力了。这就有大佬提出了三路划分法来解决这一问题。

图:

以下个数组序列为例:

此处:L 指的是 left,c 指的是 cur,R 指的是 right。 

 三路划分法的思想:

  1. 当 a[cur] < key,交换 cur 和 left 位置上的值,left++,cur++。
  2. 当 a[cur] > key,交换 cur 和 right 位置上的值,right--。
  3. 当 a[cur] == key,cur++。

三路划分法的本质:

  • 小的甩到左边,大的甩到右边。、
  • 与 key 值相等的值推到中间。

三路划分法的结果:

[ begin , left-1 ] [ left , right ] [ right + 1 , end ]

三路划分法代码实现:

#include<stdio.h>// 快速排序--递归法---三路划分法
void QuickSort1(int* a, int begin, int end)
{if (begin >= end){return;}int left = begin;int right = end;int key = a[left];int cur = left + 1;while (cur <= right){if (a[cur] > key){Swap(&a[cur], &a[right]);--right;}else if (a[cur] < key){Swap(&a[left], &a[cur]);++left;++cur;}else{++cur;}}// [begin,left-1][left,right][righ+1,end]QuickSort1(a, begin, left - 1);QuickSort1(a, right + 1, end);
}// 快速排序
int main()
{int a[] = { 6,1,6,7,9,6,4,5,6,8 };int sz = sizeof(a) / sizeof(a[0]);QuickSort(a, 0,sz-1);return 0;
}

六:快速排序——非递归实现

        因为递归这个过程是在内存中的栈空间内实现的,但是在内存中栈所含有的空间很少,当递归层数太多时,往往存在栈溢出的情况,那么解决的方法,就是将递归版本改为非递归版本,这就需要借助以前学的栈(先进后出)这一工具来模拟实现非递归的快速排序,因为栈是在内存中的堆区实现的,而内存上的堆空间很大很大,完全不需要考虑空间溢出的问题。

实现非递归的思路:

  1. 入栈一定要保证先入右,再入左
  2. 取两次栈顶元素作为 区间的 left 和 right。
  3. 对该区间进行单趟排序。排序完:[ left , keyi - 1 ] keyi [ keyi + 1 , right ]
  4. 重复2,3过程直到栈为空。

快速排序非递归代码实现:

// 快速排序--非递归法
void QuickSortNonR(int* a, int begin, int end)
{Stack st;            // 定义一个栈STInit(&st);STPush(&st, end);    // 栈:先入右STPush(&st, begin);  // 再入左while (!STEmpty(&st)){int left = STTop(&st);    // 取栈顶作为 区间的左边界STPop(&st);int right = STTop(&st);   // 取栈顶作为 区间的右边界STPop(&st);int keyi = PartSort2(a, left, right);    // 单趟排序得出 keyi// [left,keyi-1]keyi[keyi+1,right]if (left < keyi - 1)                // 判断该区间是否合法{STPush(&st, keyi - 1);STPush(&st, left);}if (keyi + 1 < right)               // 判断该区间是否合法{STPush(&st, right);STPush(&st, keyi + 1);}}STDestroy(&st);
}

效果演示:

七:快速排序——优化

7.1:快速排序优化--->三数取中选key法

        在快速排序问世以来,一些人发现,keyi 的位置,是影响快排效率的最大因素,将 keyi 放在合理的位置就可再次增大该排序的运行效率。因此就有一些大佬采用了三数取中的方法解决选 keyi 位置不合适的问题。

所谓三数取中:就是取头,中,尾三个元素,比较大小,选择那个排在中间的数据作为基准值 keyi 。再进行快速排序,这种优化方法就能使该排序效率比原来高。

 三数取中优化法代码实现:

// 快速排序--优化1---三数取中选key
int GetMidIndex1(int* a, int left, int right)
{int mid = (left + right) / 2;if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[right] < a[left]){return left;}else{return right;}}else{if (a[mid] > a[right]){return mid;}else if (a[right] > a[left]){return left;}else{return right;}}
}

这样一来,中间值的下标就被返回过来了,将其带入到快排代码中,让它成为新的 keyi 。

// 快速排序--递归法
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}int mid = GetMidIndex1(a, begin, end);Swap(&a[begin], &a[mid]);        // 再交换中间值位置与最左边位置int keyi = PartSort3(a, begin, end);// [beign,keyi-1] keyi [keyi+1,end]QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}

7.2:快速排序优化--->随机数生成选key法

有人说,三数取中法有些死板,所取的值只能是固定位置,于是又有人在基于三数取中优化法之上,进行了再次优化——随机数生成选 key 法。

随机数生成选 key 法:就是 mid 的值并不只能是 (left+right) / 2 得来的,而是由 随机数生成而来。即  mid = left + (rand() % (right - left))。

随机数生成选 key 法代码实现:

// 快速排序--优化2---随机数选key
int GetMidIndex2(int* a, int left, int right)
{int mid = left + (rand() % (right - left));if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[right] < a[left]){return left;}else{return right;}}else{if (a[mid] > a[right]){return mid;}else if (a[right] > a[left]){return left;}else{return right;}}
}

7.3:快速排序优化--->小区间改造

        因为快速排序是递归实现进行的,所以当递归到最后几层时,数组中的值其实已经接近有序了,并且这时再次进行递归会极大占用栈(函数栈帧开辟的地方,函数的递归都是在栈中进行实现的)的空间。

由于我们的快排递归类似于二叉树这样的结构,即越到最后所递归的次数越多。所以我们对其进行优化,当其区间内个数小于等于 10 时,就使用插入排序算法对其进行排序

那么该如何将其带入到快速排序的代码中来呢?

小区间改造法代码实现:

// 插入排序
void InsertSort(int* a, int n)
{for (int i = 1; i < n; i++){int tmp = a[i];int end = i - 1;while (end >= 0){if (a[end] > tmp){a[end + 1] = a[end];--end;}else{break;}}a[end + 1] = tmp;}
}// 快速排序--递归法
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}if (end - begin <= 10){InsertSort(a, end - begin + 1);    // [begin,end] 两个闭区间,求个数要 +1return;}int mid = GetMidIndex2(a, begin, end);Swap(&a[begin], &a[mid]);int keyi = PartSort3(a, begin, end);// [beign,keyi-1] keyi [keyi+1,end]QuickSort(a, begin, keyi - 1);QuickSort(a, keyi + 1, end);
}

八:快速排序——特性总结

1. 时间复杂度:O(N*logN)
2. 空间复杂度:O(logN)
3. 稳定性:不稳定

 快速排序思导图:


总结:本篇介绍了关于快速排序的hoare法,挖坑法,前后指针法单趟排序,以及三种快速排序的实现和三种优化。总的来说,还是有一些难度的,建议大家多多看看动图和思维导图用于辅助大家理解快排,多多动手,总之,这篇内容是相当硬核的,难度也有些大,当然希望这篇内容对大家理解快速排序能够有用。

这篇文章到这里就结束了,希望大家多多支持,可以的话用小手点个小虹心或者关注一下呀。大家的反馈是我更新最大动力。

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

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

相关文章

【platform push 提示 Invalid source ref: HEAD】

platform push 提示 Invalid source ref: HEAD 场景&#xff1a;环境&#xff1a;排查过程&#xff1a;解决&#xff1a; 场景&#xff1a; 使用platform push 命令行输入git -v 可以输出git 版本号&#xff0c;但就是提示Invalid source ref: HEAD&#xff0c;platform creat…

x-cmd install | Tuistash - Logstash 实时监控,告别图形界面,高效便捷!

目录 核心优势&#xff0c;一览无遗安装适用场景&#xff0c;广泛覆盖功能亮点&#xff0c;不容错过 还在为 Logstash 的监控而头疼吗&#xff1f;还在频繁切换图形界面查看数据吗&#xff1f;现在&#xff0c;有了 Tuistash&#xff0c;一切都将变得简单高效&#xff01; Tui…

【JEECG】BasicTable单元格编辑,插槽添加下拉组件样式错位

1.功能说明 BasicTable表格利用插槽&#xff0c;添加组件实现单元格编辑功能&#xff0c;选择组件下拉框错位 2.效果展示 3.解决方案 插槽内组件增加&#xff1a;:getPopupContainer"getPopupContainer" <template #salesOrderProductStatus"{ column, re…

论文阅读笔记——ROBOGROUND: Robotic Manipulation with Grounded Vision-Language Priors

RoboGround 论文 一类中间表征是语言指令&#xff0c;但对于空间位置描述过于模糊&#xff08;“把杯子放桌上”但不知道放桌上哪里&#xff09;&#xff1b;另一类是目标图像或点流&#xff0c;但是开销大&#xff1b;由此 GeoDEX 提出一种兼具二者的掩码。 相比于 GR-1&#…

K8S的使用(部署pod\service)+安装kubesphere图形化界面使用和操作

master节点中通过命令部署一个tomcat 查看tomcat被部署到哪个节点上 在节点3中进行查看 在节点3中进行停止容器&#xff0c;K8S会重新拉起一个服务 如果直接停用节点3&#xff08;模拟服务器宕机&#xff09;&#xff0c;则K8S会重新在节点2中拉起一个服务 暴露tomcat访…

纷析云开源财务软件:重新定义企业财务自主权

痛点直击&#xff1a;传统财务管理的三大桎梏 “黑盒”困局 闭源商业软件代码不可见&#xff0c;企业无法自主调整功能&#xff0c;政策变化或业务升级依赖厂商排期&#xff0c;响应滞后。 数据托管于第三方平台&#xff0c;存在泄露风险&#xff0c;合规审计被动受限。 成本…

mybatis 的多表查询

文章目录 多表查询一对一一对多 多表查询 一对一 开启代码片段编写 专注于 SQL的 编写 JDBC 的写法&#xff0c;注重于 SQL mybatis 在 一对一查询时&#xff0c;核心在于 建立每个表对应的实体类主键根据 主键 id 进行查询&#xff0c;副标根据 设定外键进行查询 在 SQL编写…

Scrapy爬虫实战:如何用Rules实现高效数据采集

Scrapy是一个强大的Python爬虫框架&#xff0c;而其中的Rules类则为爬虫提供了更高级的控制方式。本文将详细介绍如何在Scrapy中使用Rules&#xff0c;以及各个参数的具体作用&#xff0c;并结合实际场景说明Rules的必要性。 为什么需要Rules&#xff1f; 在Web爬取过程中&…

ActiveMQ 性能优化与网络配置实战(一)

一、引言 在当今分布式系统和微服务架构盛行的时代&#xff0c;消息中间件作为实现系统间异步通信、解耦和削峰填谷的关键组件&#xff0c;其重要性不言而喻。ActiveMQ 作为一款广泛应用的开源消息中间件&#xff0c;凭借其对多种消息协议的支持、灵活的部署方式以及丰富的功能…

免费视频压缩软件

一、本地软件&#xff08;支持离线使用&#xff09; 1. HandBrake 平台&#xff1a;Windows / macOS / Linux 特点&#xff1a;开源免费&#xff0c;支持多种格式转换&#xff0c;提供丰富的预设选项&#xff08;如“Fast 1080p”快速压缩&#xff09;&#xff0c;可自定义分…

消除AttributeError: module ‘ttsfrd‘ has no attribute ‘TtsFrontendEngine‘报错输出的记录

#工作记录 尝试消除 消除“模块ttsfrd没有属性ttsfrontendengine”的错误的记录 报错摘录&#xff1a; Traceback (most recent call last): File "F:\PythonProjects\CosyVoice\webui.py", line 188, in <module> cosyvoice CosyVoice(args.model_di…

Acrel-EIoT 能源物联网云平台在能耗监测系统中的创新设计

摘要 随着能源管理的重要性日益凸显&#xff0c;能耗监测系统成为实现能源高效利用的关键手段。本文详细介绍了基于安科瑞Acrel-EIoT能源物联网云平台的能耗监测系统的设计架构与应用实践。该平台采用分层分布式结构&#xff0c;涵盖感知层、网络层、平台层和应用层&#xff0…

计算机网络-同等学力计算机综合真题及答案

计算机网络-同等学力计算机综合真题及答案 &#xff08;2003-2024&#xff09; 2003 年网络 第二部分 计算机网络&#xff08;共 30 分&#xff09; &#xff08;因大纲变动因此 2004 年真题仅附真题&#xff0c;不作解析。&#xff09; 一、填空题&#xff08;共 10 分&#…

PyTorch常用命令详解:助力深度学习开发

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4-turbo模型生成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认其准…

深度学习:梯度下降法的数学原理

梯度下降法——是一种最优化算法,用于找到函数的局部极小值或全局最小值。它基于函数的梯度(或偏导数)信息来更新参数,目标是通过逐渐调整参数值来最小化目标函数的值。在机器学习算法中,梯度下降是最常采用的方法之一,尤其是在深度学习模型中,BP反向传播方法的核心就是…

刷leetcodehot100返航版--哈希表5/5、5/6

回顾一下之前做的哈希&#xff0c;貌似只有用到 unordered_set&#xff1a;存储无序元素unordered_map&#xff1a;存储无序键值对 代码随想录 常用代码模板2——数据结构 - AcWing C知识回顾-CSDN博客 1.两数之和5/5【30min】 1. 两数之和 - 力扣&#xff08;LeetCode&am…

openwrt 使用quilt 打补丁(patch)

1,引入 本文简单解释如何在OpenWRT下通过quilt命令打补丁--patch&#xff0c;也可查看openwrt官网提供的文档 2&#xff0c;以下代码通过编译net-snmp介绍 ① 执行编译命令之后&#xff0c;进入build_dir的net-snmp-5.9.1目录下&#xff0c;改目录即为snmp最终编译的目录了 /…

【开发工具】Window安装WSL及配置Vscode获得Linux开发环境

笔者面试时需要本地IDE手撕代码并测试&#xff0c;但是windows开发环境用不习惯&#xff0c;Min64和json配置也比较麻烦&#xff0c;因此采用WSLvscode的方式快速配置Linux开发环境 WSL安装 直接在微软商店搜索WSL即可 系统设置 开始菜单搜索启用或关闭 Windows 功能&…

【C语言】初阶数据结构相关习题(一)

&#x1f386;个人主页&#xff1a;夜晚中的人海 今日语录&#xff1a;人的生命似洪水在奔流&#xff0c;不遇着岛屿、暗礁&#xff0c;难以激起美丽的浪花。——奥斯特洛夫斯基 文章目录 ⭐一、判定是否互为字符重排&#x1f389;二、 回文排列&#x1f680;三、字符串压缩&am…

MySQL----数据库的操作

1. 查看数据库 语法&#xff1a;show databases; 示例展示&#xff1a; 2. 创建库 语法&#xff1a; CREATE DATABASE [IF NOT EXISTS] database_name[CHARACTER SET charset_name][COLLATE collation_name]; 注意&#xff1a;[] 为可选项 {} 为必选项 database_name 为数据…