diff --git a/1 String/KMP.md b/1 String/KMP.md new file mode 100644 index 0000000..03d0bd1 --- /dev/null +++ b/1 String/KMP.md @@ -0,0 +1,7 @@ +# 字符串匹配算法 KMP + +KMP于1977年被提出,全称 Knuth–Morris–Pratt 算法; 名字分别是:Donald Knuth(K), James H. Morris(M), Vaughan Pratt(P). + +KMP算法是一种字符串匹配算法,可以在 O(n+m) 的时间复杂度内实现两个字符串的匹配。 + + diff --git a/2 List/README.md b/2 List/README.md index 458996f..1e0460f 100644 --- a/2 List/README.md +++ b/2 List/README.md @@ -23,6 +23,13 @@ java 中扩容,每次扩容新增原先容量的 1/2 这个就不介绍了。重点说下双向链表。 +### 链表 VS 数组 + + +* 查询: 数组 O(1), 内存连续, 有序时可以用二分查找;有界 +* 删除: 链表只需要移动指针 O(1) ,数组的话删除元素需要移动后续的元素 O(N) + + ## 双向链表 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。 diff --git a/4 Tree/9-红黑树 R-B tree/红黑树.md b/4 Tree/9-红黑树 R-B tree/红黑树.md index a33a927..ff83a6d 100644 --- a/4 Tree/9-红黑树 R-B tree/红黑树.md +++ b/4 Tree/9-红黑树 R-B tree/红黑树.md @@ -49,3 +49,10 @@ + + + + + + + diff --git a/4 Tree/README.md b/4 Tree/README.md index 78c138a..1b16e27 100644 --- a/4 Tree/README.md +++ b/4 Tree/README.md @@ -23,10 +23,12 @@ ## [AVL树](3-平衡树AVL/README.md) +绝对的平衡二叉树; ## [红黑树](9-红黑树%20R-B%20tree/红黑树.md) +弱平衡二叉树;使用广泛 ## [字典树trie](4-字典树Trie/README.md) @@ -50,10 +52,6 @@ -## 赫夫曼编码 Huffman - - - diff --git a/5 Graph/DFS 和 BFS.md b/5 Graph/DFS 和 BFS.md index cbfbc4a..ecd990f 100644 --- a/5 Graph/DFS 和 BFS.md +++ b/5 Graph/DFS 和 BFS.md @@ -1,4 +1,12 @@ -# DFS 和 BFS +# DFS 和 BFS 搜索算法 + + +> DFS用递归的形式,用到了栈结构,先进后出; BFS选取状态用队列的形式,先进先出。 + + + + + diff --git a/5 Graph/README.md b/5 Graph/README.md index 7fe21e1..a4d7452 100644 --- a/5 Graph/README.md +++ b/5 Graph/README.md @@ -9,12 +9,12 @@ ### 应用场景 -工业界有哪些应用场景 +工业界有哪些应用场景? * 匹配,如打车中司乘匹配引擎,如何做到效率最优 -* 并行任务调度,一组任务,任务有优先级,如何合理安排任务调度,在最短时间内完成 -* 导航路径规划,在使用导航软件时,用户在选择一个开始地点和目的地之后导航软件会给出各种如路程最短,不走高速,时长最短等方案 -* 社区发现,在好友关系中,根据社区之间联系或紧密,利用图 louvain 算法或者其他算法对用户进行分群从而达到精准营销,个性化服务等 +* 并行任务调度: 一组任务,任务有优先级,如何合理安排任务调度,在最短时间内完成 +* 导航路径规划:在使用导航软件时,用户在选择一个开始地点和目的地之后导航软件会给出各种如路程最短,不走高速,时长最短等方案 +* 社区发现: 在好友关系中,根据社区之间联系或紧密,利用图 louvain 算法或者其他算法对用户进行分群从而达到精准营销,个性化服务等 * 金融贷后催收:利用图算法找出符合条件的失联人的联系人,从而提高催收失联修复的覆盖率、有效联系率,助力不良资产的回收 * 套汇 @@ -45,8 +45,8 @@ #### 遍历 -* 广度优先 -* 深度优先 +* 广度优先 BFS +* 深度优先 DFS Dijkstra A* @@ -67,3 +67,6 @@ https://www.jiqizhixin.com/articles/2019-05-16-14 + + + diff --git a/5 Graph/最短路径.md b/5 Graph/最短路径.md index 38713e8..0b952ad 100644 --- a/5 Graph/最短路径.md +++ b/5 Graph/最短路径.md @@ -1 +1,8 @@ -# 最短路径 \ No newline at end of file +# 最短路径 + + +Dijkstra(迪杰斯特拉) + + + + diff --git a/6 Sort/README.md b/6 Sort/README.md index ac51c25..9cfae22 100644 --- a/6 Sort/README.md +++ b/6 Sort/README.md @@ -3,21 +3,32 @@ **排序的稳定性** 是指对于相等的元素,排序之后,任然保存2个元素的位置没有变,就是稳定的排序,反之就是不稳定排序。 -**交换排序算法** +* 交换排序算法 +* 桶排序 + +### 交换排序算法 * 冒泡排序 :没轮确定一个最大的数排后面 -* 插入排序 * 选择排序 :每轮选择最小的数排前面 -* 希尔排序 -* 快排 : 选最后一个作为pivot(基数), 将数据分为 左边小于 pivot, 右边大于 pivot -* 归并排序 : -* 堆排序 +* 快排 : 选最后一个作为pivot(基数), 将数据分为 左边小于 pivot, 右边大于 pivot; 分治递归, 二叉树的前序遍历思路 +* 归并排序 : 将无序的数组,分成2个子数组分别排序,然后再merge ; 分治递归, 二叉树的后续遍历思路 +* 插入排序 : +* 希尔排序 : +* 堆排序 : -**线性排序算法** + +### 线性排序算法 * 桶排序 +### 小结 + +常见的排序算法都是比较排序,比较排序的时间复杂度通常为 O(n^2) 或 O(nlogn) +但是如果带排序的数字有一些特俗性时,我们可以根据这来设计更加优化的排序算法。 + + + # 交换排序算法 排序算法的复杂度由 `比较的次数` 和 `交换的次数` 一起决定。 @@ -31,6 +42,8 @@ 在a【i,n】中最小的元素和 a[i]交换位置。空间复杂度O(1),时间复杂度 O(n^2) +![](./selectsort.gif) + ### 冒泡排序 @@ -40,50 +53,41 @@ 这样,即使是排好序的拿冒泡排序排序,比较的时间复杂度O(n^2) - - - -### 插入排序 - -1. 第一个元素算作已经排好 -2. 取下一个元素,从已经排好的序列元素中,从后向前扫描 -3. 如果排好序的元素大于 新元素,排好序的元素移到下一个位置 -4. 重复3,直到直到最后的插入位置 -5. 重复2 - -类似插入扑克牌的效果 - -最坏的情况: 待排序的是一个逆序排放的数组,这样导致每一轮都要移动元素;此时复杂度是是0(n^2) -最好的情况: 待排序的是一已经顺序排放的数字,此时只需要做一轮比较就够了 0(n)。因此可以看到,**对大部分数据已经有序这样的数组排序,使用`插入排序`非常有优势** - -空间复杂度O(1) - - -### 希尔排序 - -递减增量排序算法,对`插入排序`的改进,实质是分组插入排序,又叫`缩小增量排序` - -1. 先将待排数列分割成若干子序列(增量为m) -2. 对每个子序列使用`插入排序` -3. 减小增量,再排序 -4. 对全体元素做一次`插入排序` - -`希尔排序`提升排序的奥秘就在于`数据元素越有序,使用插入排序效率越高` - +![](./bubblesort.gif) ### 快速排序 +时间复杂度 平均复杂度 O(n * logn) , 最坏 O(n^2) +空间复杂度 +快速排序是对冒泡排序的改进,划分交换排序。 + + 递归一次,pivot 左边都比它小,右边都比它大。这是递归,分治的思想。 -> 快速排序就是个二叉树的前序遍历,归并排序就是个二叉树的后序遍历 +> 快速排序就是个二叉树的前序遍历思路,归并排序就是个二叉树的后序遍历思路 + + +代码框架如下 + +``` +void quicksort(int *a, int left, int right){ + if (left