当前位置: 首页 > news >正文

八大排序算法之插入排序+希尔排序

目录

一.前言(总体简介)

关于插入排序

 关于希尔排序:

二.插入排序

函数首部:

算法思路:

算法分析

插入排序代码实现:

插入排序算法的优化前奏: 

三.希尔排序(缩小增量排序)

1.算法思想: 

2.算法拆分解析 

序列分组

分组预排序:

分组预排序的另一种实现方式:

希尔排序的实现思路(这里采用Knuth实现法)

关于gap指数式递减的分析:

四.希尔排序的时间复杂度分析

分组预排序的时间复杂度

gap指数式递减过程中,多次分组预排序的总复杂度分析:

经典数据结构书目中对希尔排序复杂度的说明: 

五.实测对比希尔排序与普通插入排序的时间效率


一.前言(总体简介)

关于插入排序

  • 插入排序的思想:将各元素逐个插入已经有序序列中的指定位置
  • 插入排序的思想很类似于我们玩扑克牌时逐张摸牌整理牌序的方式:
  • 还有一个更贴近算法实现的gif:
  1. 将上面的方条看成数组中的元素
  2. 橙色的方条代表已经排好序的元素序列,蓝色的方条代表待插入的各元素
  3. 在算法实现中,橙色的方条构成的序列用一个下标变量来维护(每次循坏该下标变量加1) 

 关于希尔排序:

  • 希尔排序是插入排序的优化版本,优化算法由希尔本人给出
  • 基本思想是先对数组的子数组(按照一定规则划分而成)进行预排序,使待排序数组变得相对有序,最后再对整个数组进行一次插入排序完成整体的排序

二.插入排序

函数首部:

void InsertSort(DataType* arr, int size);
  • arr是待排序数组首地址指针;
  • size是待排序的元素个数;

算法思路:

  1. 用一个数组下标变量end来维护前end个有序元素(end初始化为0)
  2. 每个循环过程中,将end下标变量指向的元素插入到前end个元素中某个指定位置上构成一个end+1个元素的有序序列,然后end加一,接着执行下一次循环直到end遍历完整个数组后循环结束;
  3. 每次循环过程中,x元素插入的位置通过元素比较来确定的:
  4. end为0时,有序序列元素个数为0;end为1时,有序序列的元素个数为1........;当end为size时,有序序列的元素个数便为size(即数组中size个元素按序排列)此时排序完成
  5. 插入排序便是以这种递推的方式将数组arr调整成有序序列的 

算法分析

  • 从算法思路中可以看到,完成一个元素x插入到前end个元素构成的有序序列的过程中,会发生数据的比较和挪动
  • 在最坏的情况下,每完成一个元素x插入到前end个元素的构成的有序序列的过程中,有序序列的每个元素都要被往后挪动一个位置(即元素比较和挪动的次数为end次)
  • 因此整个排序的过程中发生元素的比较和挪动的总次数为:
  • 所以插入排序的时间复杂度为:O(N^2)  (N为待排序的元素个数);

插入排序代码实现:

两层循环实现:

  • 外层循环用end控制(有size个元素要插入,循环size次)(每次要插入前缀序列的元素x=arr[end])(end下标遍历了整个数组)
    for(int end =0;end<size;++end)
  • 内层循环用insert控制,用于比较和挪动数据,确定x要插入的位置并完成插入(insert每次从end开始递减直到等于0或者刚好找到x要插入的位置)

  • 以排升序为例:

//以排升序为例
void InsertSort(DataType* arr, int size)
{assert(arr);for (int end = 0; end < size; end++)    //用end来维护数组前end个元素构成的有序序列{int x = arr[end];					//x为待插入有序序列的数据int insert = end;					//用变量insert来确定x要插入的位置while (insert>0)					//通过元素比较确定x要插入的位置{if (x < arr[insert-1])			   //说明insert不是x要插入的位置{arr[insert] = arr[insert-1];   //往后挪动数据为x留出空位insert--;                      //令insert指向序列前一个元素}else{break;	    //有序序列中x>=arr[insert-1]说明insert是x要插入的位置}}					//最坏的情况下x会被插入到数组的首地址处(此时数据比较和挪动了end次)arr[insert] = x;    //完成元素x的插入(继续插入下一个元素)}
}
  • 注意算法的边界条件:
  1. 外层循环end增加到size时结束循环(数组各元素下标为0到size-1)
  2. 内层循环insert等于0时说明x前end个元素的有序序列中的所有元素都小,x将被插入到数组下标为insert=0的位置

插入排序算法的优化前奏: 

  • 插入排序算法利用了逐个元素递推插入前缀有序数列的方法完成整个待排序序列的调整(元素插入的过程中,前缀序列有序的性质有时可以大大减少元素的比较和挪动次数).
  • 因此插入排序算法有一个特点:当待排序数组arr整体相对有序时,排序过程的时间复杂度接近O(N),举个例子:
  • 插入排序在处理上图的序列过程中元素总的比较次数为size+2次,元素总的挪动次数为3次(总体上可以认为:在处理整体上大致有序的序列时,插入排序的时间复杂度与size是线性相关的);
  • 插入排序的上述特点为算法的优化提供了可能,如果我们能够对序列正式进行插入排序之前,让序列整体上变得相对有序,那么就可以降低排序时间复杂度的数量级,这就是希尔排序诞生的思想起点

三.希尔排序(缩小增量排序)

  • 希尔排序算法由大神D.L.Shell于1959年提出而得名,其本质上在插入排序的基础上进行优化而产生的

先给出排序接口的首部:

void ShellSort(DataType* arr, int size);
  • DataType为typedef定义的元素类型
  • size是待排序数组arr中的元素个数

1.算法思想: 

  • 经过对插入排序的分析我们已经知道:在处理整体上大致有序的序列时,插入排序的时间复杂度待排序元素个数线性相关
  • 因此在正式进行插入排序之前,我们考虑先将序列进行多次分组预排序
  • 多次分组预排序完成后,整体序列变得相对有序,最后再进行一次插入排序完成整体序列的排序

2.算法拆分解析 

序列分组

  1. 序列分组方式图文解析:先确定一个gap值(gap<=size)(将序列划分为gap组),从数组第一个元素开始以gap为间隔构成子序列,如图所示:
  2. 根据上述分组方式,我们简单地进行数学上的分析:由于gap<=size,因此我们一定可以将数组arr分为gap个子序列(每个子序列的元素个数至少为(size/gap)个;当size为gap整数倍时,每个子序列的元素个数为(size/gap)个,当size不为gap整数倍时,每个子序列元素个数最大为(size/gap)+1个);(以上数学表达式中的除法皆为向下取整除法)
  3. 我给这种序列分组模式取个名字:序列固定间隔分组法
  4. 序列固定间隔分组法的另外一种图示形式:
  • 可见每个子序列的首元素分别为下标为0到gap-1的元素
  • 完成了序列的固定间隔分组后,接下来就要对这些子序列分别进行插入排序,即分组预排序

分组预排序:

  • 确定了gap值后,对各个子序列分别进行插入排序:(图示中以gap=3为例子)
  • 分组预排序的代码实现思路:(最基础的思路是三层循环实现)
  1. 数组arr被分为gap组, 所以要对gap个子序列进行插入排序最外层循环gap次,最外层循环用start变量来控制(初始化为0),边界条件为start<gap;
  2. 内两层循环的代码架构与插入排序完全一致
  • 分组预排序的代码实现(建立在插入排序代码的框架上):
    void ShellSort(DataType* arr, int size)
    {assert(arr);int gap;									//将数组划分为gap组(gap待定)for (int start = 0; start < gap; ++start)   //start为每个子序列的首元素下标(gap个子序列循环gap次){for (int end = start; end < size; end += gap)	//用end来维护子序列中的前缀有序序列(end不能大于或等于size)(end下标遍历了子序列){int x = arr[end];							//x为待插入前缀有序序列的元素int insert = end;							//用insert确定x要插入的位置while (insert>start)						//insert=start时说明x要插入到子序列首元素的位置{if (x < arr[insert - gap])				//说明insert不是x要插入的位置{arr[insert] = arr[insert - gap];    //挪动数据,为x空出位置insert -= gap;						//指向子序列的前一个元素}else                                    //x >= arr[insert - gap]说明insert就是x要插入的位置{ break;}}arr[insert] = x;							//完成x元素的插入}	}
    }
  • 代码段完成了一次分组预排序(分组间隔为gap)

  • 代码段中如果gap等于1,分组预排序变为普通的插入排序 

分组预排序的另一种实现方式:

  • 分组预排序可以用两层循坏来实现:

  • 注:两层循环的分组预排序三层循环的分组预排序其实本质上没有区别,只是元素调整顺序不一样(三层循环是一组接一组子序列完成插入排序,两层循环是逐个元素完成调整)

  • void ShellSort(DataType* arr, int size)
    {assert(arr);int gap;										//gap值待定		for (int end = 0; end < size; ++end)		    //用end来遍历数组每一个元素{int x = arr[end];							//x为待插入子序列前缀的元素int insert = end;							//用insert确定x要插入的位置while (insert >= gap)						//insert<gap的时,insert为下标的元素不需要调整{if (x < arr[insert - gap])				//说明insert不是x要插入的位置{arr[insert] = arr[insert - gap];    //挪动数据,为x空出位置insert -= gap;						//指向子序列的前一个元素}else                                    //x >= arr[insert - gap]说明insert就是x要插入的位置{break;}}arr[insert] = x;							//完成x元素的插入}
    }

    三层循环改为两层循环,其具体代码思路图解如下:

  • 三层循环的写法两层循环的写法本质都是完成了gap为某确定值时的一次分组预排序

  • 同样地,代码段中如果gap等于1,分组预排序变为普通的插入排序 

  • 后续为了简洁起见,我们采用两层循环的分组预排序实现法来完成希尔排序

希尔排序的实现思路(这里采用Knuth实现法)

  • 由之前的分析我们可以知道:gap的值确定了序列的一个划分(序列被划分为gap个子序列),对这些子序列分别进行插入排序便完成了一次序列的分组预排序
  • 我们置gap的初始值为size,gap每次循环按照gap = (gap/3)+1的方式递减(由简单的数学分析可知gap一定会减小到1)(加1就是为了保证gap最终一定会减小到1)
  • 对于每一个gap值我们都对待排序数组进行一次分组预排序
  • 当gap减小到1时,数组已经经过了一次或多次分组预排序,最后再完成一次gap为1的分组预排序(gap为1时的分组预排序等价于普通的插入排序)从而完成数组整体的排序(gap为1的排序必须进行,否则不能保证整体序列一定有序)
  • 我们只需在分组预排序的实现代码外层再套一层由gap控制的循环即可实现上述过程:
    void ShellSort(DataType* arr, int size)
    {assert(arr);int gap = size;										while (gap>1)                  //gap为1时序列已经完成了普通插入排序,排序完成{gap = gap/3 + 1;           //缩小gap的值for (int end = 0; end < size; ++end)		    //用end来遍历数组每一个元素{int x = arr[end];							//x为待插入子序列前缀的元素int insert = end;							//用insert确定x要插入的位置while (insert >= gap)						//insert<gap的时,insert为下标的元素不需要调整{if (x < arr[insert - gap])				//说明insert不是x要插入的位置{arr[insert] = arr[insert - gap];    //挪动数据,为x空出位置insert -= gap;						//指向子序列的前一个元素}else                                    //x >= arr[insert - gap]说明insert就是x要插入的位置{break;}}arr[insert] = x;							//完成x元素的插入}}												
    }

关于gap指数式递减的分析:

  • 希尔排序算法中,gap从size开始呈指数式递减. (这也是缩小增量排序这个名字的来源)
  • 因此,算法中分组预排序的执行次数数量级(logN) (N=size)
  • gap设计成指数式递减这一思想非常重要,这样既保证了在进行gap=1的插入排序之前,完成了一定次数的分组预排序,又保证了分组预排序的次数不会太多(分组预排序的次数如果太多反倒会降低算法整体的效率)

四.希尔排序的时间复杂度分析

希尔排序接口首部:

void ShellSort(DataType* arr, int size)

分组预排序的时间复杂度

序列分组图示:

  • 为了方便分析,我们假设每次分组预排序,size都为gap的整数倍:根据序列固定间隔分组法,待排序数组被划分为gap个子序列,每个子序列元素个数(size/gap)个
  • 根据插入排序的时间复杂度计算公式:完成每组子序列的插入排序算法循环中元素比较和挪动的总次数数量级为:
  • 即完成一次分组预排序时间复杂度计算表达式为:

gap指数式递减过程中,多次分组预排序的总复杂度分析:

  • 可以发现一个规律:gap值越大(gap<=size)分组预排序元素比较和挪动次数的上限就越低(复杂度越接近线性),因此利用较大的gap值进行分组预排序将总体序列调整为相对有序序列的设计非常巧妙!!!

  • 将size写成N,则希尔排序的时间复杂度总体的数量级大致为NlogN
  • 该证明并不严格,但是总体上反映出了希尔排序通过多次分组预排序的方法尝试降低整体排序的时间复杂度数量级的思想。
  • 希尔大神设计该算法时,gap的递减方式是:gap=gap/2
  • gap = (gap/3)+1这种缩小增量的公式是由kunth大神给出的,希尔排序的最优gap递减公式目前尚未求得(这牵涉到一些尚未得到完全解决的数学难题)

经典数据结构书目中对希尔排序复杂度的说明: 

以下文段摘自《数据结构-用面相对象方法与C++描述》--- 殷人昆

  • gap的取法有多种.最初Shell提出取gap=gap/2,直到gap=1,后来Kunth提出取gap=(gap/3) +1.还有人提出都取奇数为好,也有人提出各gap互质为好.无论哪一种主张都没有得到证明
  • 对希尔排序的时间复杂度的分析很困难,在特定情况下可以准确地估算关键码的比较次数和对象移动次数,但想要弄清关键码比较次数和对象移动次数与增量选择之间的依赖关系,并给出完全的数学分析,还没有人能够做到。在Kunth所著的《计算机程序设计技巧》第三卷中,利用大量的实验数据统计资料得出,当n很大时,关键码平均比较次数和对象平均移动次数大约在n^1.25 到1.6n^1.25范围内,这是在利用直接插入排序作为子序列排序方法的情况下得到的

从上述文段中我们可以得知,受当前数学分析的限制,我们可以暂且根据Kunth大神的实验结果,将希尔排序的时间复杂度看成是: O(N^1.25)

五.实测对比希尔排序与普通插入排序的时间效率

  • 利用随机数生成器创建两个十万个元素的相同整形数组,一个用直接插入排序进行排序,另外一个用希尔排序进行排序,打印出两者所消耗的时间(单位为毫秒)
    int main()
    {srand(time(0));const int N = 100000;int* arr1 = (int*)malloc(sizeof(int) * N);int* arr2 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){arr1[i] = rand();arr2[i] = arr1[i];}int begin1 = clock();InsertSort(arr1, N);int end1 = clock();printf("IsertSort:%d\n", end1-begin1);int begin2 = clock();ShellSort(arr2, N);int end2 = clock();printf("ShellSort:%d\n", end2-begin2);return 0;
    }

  • 可见希尔排序的算法优化思路虽然新奇复杂,但毫无疑问的是,希尔大神对插入排序所进行的优化是非常成功的!!!!(而且数据量越大希尔排序的优化效果就越明显)

相关文章:

八大排序算法之插入排序+希尔排序

目录 一.前言(总体简介) 关于插入排序 关于希尔排序: 二.插入排序 函数首部: 算法思路: 算法分析 插入排序代码实现: 插入排序算法的优化前奏: 三.希尔排序(缩小增量排序) 1.算法思想: 2.算法拆分解析 序列分组 分组预排序: 分组预排序的另一种实现方式: 希尔…...

蓝桥杯第十四届蓝桥杯模拟赛第三期考场应对攻略(C/C++)

这里把我的想法和思路写出来&#xff0c;恳请批评指正&#xff01; 目录 考前准备 试题1&#xff1a; 试题2&#xff1a; 试题3&#xff1a; 试题4&#xff1a; 试题5&#xff1a; 试题6&#xff1a; 试题7&#xff1a; 试题8&#xff1a; 试题9&#xff1a; 试题1…...

【数论】最大公约数、约数的个数与约数之和定理

Halo&#xff0c;这里是Ppeua。平时主要更新C语言&#xff0c;C&#xff0c;数据结构算法......感兴趣就关注我吧&#xff01;你定不会失望。 &#x1f308;个人主页&#xff1a;主页链接 &#x1f308;算法专栏&#xff1a;专栏链接 我会一直往里填充内容哒&#xff01; &…...

第28篇:Java日期Calendar类总结(二)

目录 1、获取系统当前时间 2、获取指定日期 3、对象字段类型 4 、对象信息设置 4.1 Set设置...

【Python】字符串 - 集大成篇

目录 1. 不同语言的字符串比较 1.1 C 语言 1.2 C 语言 1.2.1 C 风格字符串 1.2.2 C 风格字符串 1.3 JAVA 1.4 Python 2. Python 字符串 2.1 方法 2.2.1 title () 2.2.2 lower () 2.2.3 upper () 2.2.4 rstrip () 2.2.5 lstrip …...

IDEA: 如何导入项目模块 以及 将 Java程序打包 JAR 详细步骤

IDEA&#xff1a; 如何导入项目模块 以及 将 Java程序打包 JAR 详细步骤 、 文章目录IDEA&#xff1a; 如何导入项目模块 以及 将 Java程序打包 JAR 详细步骤IDEA 导入项目模块 Module一. 创建一个空项目二. 导入 Module三. 将 Module 与 当前项目关联上IDEA 将 Java程序打包成…...

算法的效率——时间复杂度和空间复杂度

文章目录1. 算法效率1.1 什么是算法1.2 算法的好坏2. 时间复杂度2.1 什么是时间复杂度2.2 时间复杂度的计算方法2.3 大O的渐进表示法2.4 常见时间复杂度计算举例3. 空间复杂度4. 常见复杂度对比1. 算法效率 1.1 什么是算法 目前普遍认可对算法的定义是&#xff1a;算法是解决…...

2021年 第12届 蓝桥杯 Java B组 省赛真题详解及小结【第1场省赛 2021.04.18】

总分&#xff1a;5 一、试题A&#xff1a;ASC 得分&#xff1a;5分 本题总分&#xff1a;5 分 【问题描述】 已知大写字母 A 的 ASCII 码为 65&#xff0c;请问大写字母 L 的 ASCII 码是多少&#xff1f; 【答案提交】 这是一道结果填空的题&#xff0c;你只需要算出结果后提…...

透过等待看数据库

等待分类与解决基本流程步骤1.定位问题系统等待往往能直观的反映出系统问题。通过一些常见的等待类型&#xff0c;同样可以找到系统瓶颈&#xff0c;结合性能计数器往往定位更准确。如&#xff1a;系统中存在大量IO类等待&#xff0c;那么可能表示你的磁盘或内存是语句运行缓慢…...

中科亿海微FPGA

国产FPGA中&#xff0c;紫光、安路、高云称得上是三小龙&#xff0c;其他的半斤八两&#xff0c;中科亿海微也算是其中之一。 其产品为亿海神针系列&#xff0c;如下&#xff1a; 可见其最小规模也有9.2KLUT&#xff0c;最大竟有136K之多了&#xff0c;对比其他国产&#xff0…...

【链表OJ题(三)】链表中倒数第k个结点

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;数据结构 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录链表OJ题(三)1. 链表…...

华为防火墙的学习

防火墙 - 含义和定义 什么是防火墙&#xff1f; 防火墙的工作原理 防火墙的区域&#xff1a; 包过滤防火墙----访问控制列表技术---三层技术 代理防火墙----中间人技术---应用层 状态防火墙---会话追踪技术---三层、四层 UTM---深度包检查技术----应用层 下一代防火墙 防火墙的…...

SPI 接口OLED 模块 - 兼容5V 和3.3V 电平

PCB 布局参考了老王0.8元128x32OLED显示屏转接板&#xff0c;开源项目地址&#xff1a;老王0.8元128x32OLED。 老王家买的屏幕放了快一年了&#xff0c;终于还是决定整个单独的模块&#xff0c;之前一直打算集成到开发板上的&#xff0c;不太灵活。相比那个转接板&#xff0c;主…...

css布局和定位

在Web开发中&#xff0c;CSS布局和定位是非常重要的技能。在这篇博客中&#xff0c;我们将深入探讨CSS布局和定位的概念、基本技术和最佳实践。 **CSS布局基础** ├── 盒模型 │ ├── 内边距 │ │ ├── padding │ │ ├── padding-top │ │ ├── p…...

python -- 批量读取多个文件,并将每个文件中相同变量累加

python – 批量读取多个文件&#xff0c;并将每个文件中相同变量累加 情况描述 现有多个nc文件&#xff0c;位于同一个文件夹中&#xff0c;如下所示每个文件中都有相同的变量&#xff0c;想要读取每个文件中的变量然后将其加起来意思就是说&#xff1a; 文件1中的变量文件2中…...

低代码开发流程是怎么样的?

低代码开发流程是怎么样的&#xff1f;现在很多文章都在下功夫宣传what&#xff08;低代码是什么&#xff09;、why&#xff08;为什么要用低代码&#xff09;&#xff0c;但是很少有文章能够系统讨论how&#xff08;怎么用低代码&#xff09;的问题。 所以我花3天的时间准备了…...

任何时候都不要在 for 循环中删除 List 集合元素!!!

首先说结论&#xff1a;无论什么场景&#xff0c;都不要对List使用for循环的同时&#xff0c;删除List集合元素&#xff0c;因为这么做就是不对的。 阿里开发手册也明确说明禁止使用foreach删除、增加List元素。 正确删除元素的方式是使用迭代器&#xff08;Iterator&#xff…...

koa+Vite+vue3+ts+pinia构建项目

一、 初始化构建项目 npm create vite myProject -- --template vue-ts 注&#xff1a;Vite 需要 Node.js 版本 14.18&#xff0c;16。然而&#xff0c;有些模板需要依赖更高的 Node 版本才能正常运行&#xff0c;当你的包管理器发出警告时&#xff0c;请注意升级你的 Node 版…...

k8s-yaml文件

文章目录一、K8S支持的文件格式1、yaml和json的主要区别2、YAML语言格式二、YAML1、查看 API 资源版本标签2、编写资源配置清单2.1 编写 nginx-test.yaml 资源配置清单2.2 创建资源对象2.3 查看创建的pod资源3、创建service服务对外提供访问并测试3.1 编写nginx-svc-test.yaml文…...

存储引擎

目录 ❤ MySQL存储引擎 什么是存储引擎? MySQL支持哪个存储引擎? ❤ 各种存储引擎的特性 概述 各种存储引擎的特性 各种搜索引擎介绍 ❤ 常用存储引擎及适用场景 ❤ 存储引擎在mysql中的使用 存储引擎相关sql语句 指定存储引擎建表 在建表时指定 在配置文件中…...

Go中 channel的使用

文章目录背景channel 简介使用说明声明发送和接受数据关闭channel使用示例背景 使用 sync 包和 context 包的工具可以实现多个协程之间互相协作, 但是没有一种很好的方式解决多个协程之间通信的问题. golang 作者 Rob Pike 说过一句话&#xff0c;不要通过共享内存来通信&…...

【C++】string OJ练习

文章目录1. 仅仅反转字母思路分析代码实现2. 字符串中的第一个唯一字符题目分析代码实现3. 《剑指offer》——替换空格解法一&#xff1a;寻找替换思路分析代码实现优化解法二&#xff1a;空间换时间思路分析代码实现4.字符串最后一个单词的长度思路分析代码实现5. 字符串相加思…...

进程间通信IPC

进程间通信IPC (InterProcess Communication) 一、进程间通信的概念 每个进程各自有不同的用户地址空间&#xff0c;任何一个进程的全局变量在另一个进程中都看不到&#xff0c;所以进程之间要交换数据必须通过内核&#xff0c;在内核中开辟一块缓冲区&#xff0c;进程1把数据…...

操作系统-页面淘汰算法(下)-软件设计(二十六)

操作系统-PV操作&#xff08;上&#xff09;-软件设计&#xff08;二十五&#xff09;https://blog.csdn.net/ke1ying/article/details/129476031 存储管理-分区存储组织 问&#xff1a;计算机系统内存大小为128k&#xff0c;当前系统分配情况如图&#xff0c;那么作业4再次申…...

23种设计模式-责任链模式(Android开发实际应用场景介绍)

什么是责任链模式 责任链模式是一种行为型设计模式&#xff0c;它的核心思想是将请求从一系列处理者中传递&#xff0c;直到其中一个处理者能够处理它为止。在这个过程中&#xff0c;请求可以被任何一个处理者处理&#xff0c;也可以被拒绝&#xff0c;直到有一个处理者能够处…...

Socket+Select+Epoll笔记

讲到epoll&#xff0c;就必须了解Socket&#xff0c;上篇博客写了Socket的基本使用方法&#xff0c;步骤主要为创建一个socketsocket是进程之间通信的&#xff0c;那么进程通信如何找到这个socket呢&#xff1f;当然是端口号&#xff0c;所以socket就要和端口号进行绑定&#x…...

git查看最近修改的文件

git log --name-status 每次修改的文件列表, 显示状态 git log --name-only 每次修改的文件列表 git log --stat 每次修改的文件列表, 及文件修改的统计 git whatchanged 每次修改的文件列表 git whatchanged --stat 每次修改的文件列表, 及文件修改的统计 git show 显示最…...

【算法基础(四)】堆排序(二)

堆排序&#xff08;二&#xff09; 把数组从零开始连续的一段 完全二叉树 size i 左 son 2*11 i 右 son 2*12 父 (i-1) / 2 堆是完全二叉树&#xff0c;分为大根堆和小根堆 在完全二叉树里&#xff0c;每一棵子数最大的值是头节点的值&#xff0c;就是大根堆 同理&…...

C++类型转换

C语言的转换是在变量前加类型名进行转换的&#xff0c;比如double pi 3.14;int a (int) pi;对于指针也是如此double* dptr &pi;int* iptr (int*)dptr;虽然c兼容了C语言的转型方式&#xff0c;但是也做了很多限制&#xff0c;比如向上类型转换&#xff0c;在c中建议使用…...

Keil MDK6要来了,将嵌入式软件开发水平带到新高度,支持跨平台(2023-03-11)

注&#xff1a;这个是MDK6&#xff0c;不是MDK5 AC6&#xff0c;属于下一代MDK视频版&#xff1a; https://www.bilibili.com/video/BV16s4y157WF Keil MDK6要来了&#xff0c;将嵌入式软件开发水平带到新高度&#xff0c;支持跨平台一年一度的全球顶级嵌入式会展Embedded Wor…...

钱多网站/推广小程序

matlab中矩阵LDLT分解与Cholesky分解矩阵LDLT分解与Cholesky分解&#xff1a;矩阵的LDLT消去函数的程序代码&#xff1a;%矩阵的LDLT分解function [s,l,d]ldlt(a)s1;l0;d0;%判断矩阵是否对称if a~a %矩阵不对称&#xff0c;输出错误信息 s0;else bdiag(a); %列向量b存放矩阵a的…...

万户网络做网站很垃圾/it行业培训机构一般多少钱

//释放PersonA 对象 那么我需要先把DogB release&#xff0c;然后在释放 [personA release];//清空指针personA nil; //------ 关于retainCount为1 、 -1 、 0 、 无穷大的条件 //1&#xff1a;为对象计数&#xff0c;当创建对象时或者对象即将释放时为1&#xff0c;即对象计…...

怎么查网站做百度竞价信息/app开发公司排行榜

一、准备工作 1、Lumen环境搭建 可参考上篇文章《Lumen安装配置使用入门》一文。 2、数据库信息 数据库地址&#xff1a;localhost 数据库名称&#xff1a;lumenauth 数据库用户&#xff1a;root 数据库密码&#xff1a;****** 二、初始化Lumen lumen new LumenAuth 三…...

网站源码之家/网络推广和运营的区别

视差效果通过在网页向下滚动的时候&#xff0c;控制北京的移动速度比前景的移动速度慢来创建出令人惊叹的3D效果。 实现方式&#xff1a; CSS3实现 有点&#xff1a;发开时间短&#xff0c;性能和开发效率比较好。 缺点&#xff1a;不能兼容低版本的浏览器。 jQuery实现&a…...

wordpress充值功能/怎么制作网页链接

2020中甲联赛第二阶段第一轮&#xff0c;冲超组成都赛区成都兴城人居队的唐淼、保级1组梅州赛区贵州恒丰队的马格利卡、保级2组常州赛区呼和浩特队的奥古斯托&#xff0c;三人当选最佳球员。成都兴城人居 19号 唐淼位置&#xff1a;前卫 年龄&#xff1a;30本轮与老对手泰州远…...

统计wordpress/成都谷歌seo

分析 它居然真的是个nlog^3暴力&#xff1f;&#xff01; 两个数在加小于min(lowbit(x),lowbit(y))的数时对他们的奇偶性不影响 因此每次加上min(lowbit(x),lowbit(y))判断此时的奇偶性 直接排序即可 代码 #include<bits/stdc.h> using namespace std; #define int long …...