算法

堆排序优化思路

堆排序其实是最不好优化的一个,在数据结构都确定的情况下,优化空间太小,除非优化数据结构本身,但那样就不叫做堆排序了。类似堆排序的还有smooth sort和weakheap sort,有兴趣可以自己查找相关资料。 堆排序原理 堆排序其实是选择排序的优化变种,选择排序是把最大或最小的元素放到最边上,然后不断重复以上过程,堆排序也是如此,只不过堆排序通过构建数据结构,让查找最大或最小元素并放到最边上的速度比选择排序快得多。 首先我们先来介绍什么是堆。堆只是个缩写,全名是二叉堆,是一种完全二叉树,它的特点是二叉堆的父节点元素不小于子节点的元素,以下为二叉堆例图 graph TD; 30-->29 30-->28 29-->24 29-->25 28-->26 28-->22 24-->21

素数判断和因子分解

这里记录的是素数判断 Miller Rabbin 的快速判定算法,而分解使用的算法是 Pollard Rho 的玄学分解算法,这个算法的理论依据是生日悖论,这里不具体讨论这个数学问题,具体讨论看前面链接就可以了。 以下我们分别简要介绍这两个算法的原理 首先这是Miller Rabbin的维基百科介绍页,由于页面是中文,这里不做重复介绍。 下面简要解释一下Pollard’s Rho算法的原理,这是它的维基百科页面 首先我们来定义这样一个函数 $$f(x)=(x*x+c)%n$$ 其中n是需要被分解的数,c是一个任意小于n的正整数常数。那么我们给一个初始值x1,通过计算 $f(x1)$ 得到x2,然后去求 $|x1-x2|$ 与 n 的最大公约数,只要结果大于1就找到了分解结果。那如果最大公约数仍然是1,那么就通过刚才的x2求出 $x3=f(x2)$ 并计算 $|x1-x3|$ 与 n 的最大公约数。也就是说,我们可以通过这个公式得到一个数列

二进制技巧

二进制位运算的技巧特别多,这里就做一份cheat sheet,希望能帮助到大家。不过过于简单的就不列举了 单行表达式 作用 表达式 把右边连续的1变成0 n & ( n + 1 ) 把右边第一个1变成0 n & ( n - 1 ) 把右起第一个0变成1 n | ( n + 1 ) 把右起连续的0变成1 n | ( n - 1 ) 取右边连续的1 n ^ ( n + 1 ) 去掉右起第一个1的左边 n & -n 或 n & ( n ^ ( n - 1 ) ) 高低位交换,前x位 ( n << x ) | ( x >> ( 32 - x ) ) 有符号整数计算绝对值 ( n ^ (n >> 31) ) - (n >> 31)

插入排序与希尔排序优化思路

本篇针对插入排序和希尔排序来讲优化思路,有部分内容因为前一篇文章已经有交代,这里不重复,如果你还没有看,请先看前一篇。我们来看插入排序的动图演示 插入排序保证前面一块是有序的情况下,新增的一个元素通过向前交换到合适的位置,所以叫做插入排序。 插入排序基本实现 我们先来看插入排序的基本实现 void insert_sort(sort_element_t * beg, sort_element_t * end) { for (sort_element_t* i = beg + 1; i < end; ++i) { sort_element_t val = *i; sort_element_t* j = i; for (; j > beg && val < j[-1]; --j) { *j = j[-1]; } *j = val; } } 插入排序即使不做任何优化,效率也明显高于上篇所说的冒泡排序和选择排序。那么按照惯例,先上双向看看效果

选择和冒泡排序优化思路

本篇针对两种最基本的排序(冒泡、选择)来讲优化思路。越是简单的东西反而可能存在你越想不到的优化点。但是在开始之前,先给不了解的人讲一个设计原则的问题,我们在设计排序接口的时候,最为常见的有 void sort(type arr[], int len) 也许你也见过 void sort(iter beg, iter end) 这时候问题就来了,很多人会错误地把end认为是最后一个元素,其实不然,这两接口可以相互转换,例如我们可以写 sort(arr, arr + len) ,这样写很自然对不对,但如果你认为end是最后一个元素,那你就不得不改成 sort(arr, arr + len - 1) 。事实上,这类的接口我们需要一个统一的原则,就是左闭右开区间原则,即beg就是首个元素,而end是最后一个元素+1,即end是作为结束标志,不应该把end算在范围内。接下来下面所有的接口写法,都是以 void sort(iter beg, iter end) 这种方式写的,至于这样写有什么好处,接下来我们就看示例。 选择排序

Quick sort(快速排序)杂谈 1

我们现在使用的排序,很大比例在使用quick sort,因为它是平均速度最快的排序,但与此同时它可能也是坑最深的排序,现在我们就来讨论讨论它,因为内容较多,我计划写多篇,本篇是第一篇。 快排的思路 我们先来介绍一下快排的思路。快排的思路其实很简单,在数组中选一个元素,我们就称呼这个元素为pivot,通过与这个元素的比较,把数组划分成不比pivot大的在一边,不比pivot小的在另一边,于是就分成了两个更小的数据,对它们分别再排序就行了。但是,这个描述特别的含糊,首先是怎么选中间元素,这里面有很多不同的做法。然后就是划分了,这个划分方法非常的多,水也特别深,这里主要介绍最为常见的划分方法。

博客第一文,附hugo表格的坑

第一次使用这个hugo就遇到一堆坑,主题并不是随便用,会有SHA-256校验,而在windows平台下用git,clone下来会把\n自动换成\r\n从而导致主题应用失败,服了。 另一个坑就是hugo的表格,你不能像以下这么写 a|b|c -|-|- 1|2|3 这样hugo的引擎是不认为这是表格,正确的做法是改成下面这样