From cd61cb631de503b5138dfa83019de84cb12477fe Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 20 Oct 2018 12:49:51 +0800 Subject: [PATCH 01/36] Update README.md --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d2fdc4f..e661349 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ 这里的内容是我学习算法过程的一些记录,希望能一直坚持下去。 -##学习方法 +## 学习方法 * 把所有经典算法写一遍 * 看算法有关源码 @@ -12,7 +12,7 @@ * 刷题 -##基本数据结构和算法 +## 基本数据结构和算法 这些算法全部自己敲一遍: @@ -44,7 +44,7 @@ * 散列函数 * 碰撞解决 -###字符串算法 +### 字符串算法 * 排序 * 查找 @@ -55,7 +55,7 @@ * 数据压缩 -###图的算法 +### 图的算法 * 图的存储结构和基本操作(建立,遍历,删除节点,添加节点) * 最小生成树 @@ -91,7 +91,7 @@ * 哈希表: O(1) -###15个经典基础算法 +### 15个经典基础算法 * Hash * 快速排序 @@ -223,13 +223,13 @@ [程序员编程艺术](http://blog.csdn.net/v_JULY_v/article/details/6460494) -###基本算法演示 +### 基本算法演示 http://sjjg.js.zwu.edu.cn/SFXX/sf1/sfys.html http://www.cs.usfca.edu/~galles/visualization/Algorithms.html -###编程网站 +### 编程网站 http://leetcode.com/ http://openjudge.cn/ 开放在线程序评测平台,可以床架自己的OJ小组 From 6d41800c696f71cdd622f0769ff1abce5c91c07b Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 20 Oct 2018 22:45:29 +0800 Subject: [PATCH 02/36] =?UTF-8?q?Create=20kmp=20=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kmp \347\256\227\346\263\225" | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 "\345\255\227\347\254\246\344\270\262/kmp \347\256\227\346\263\225" diff --git "a/\345\255\227\347\254\246\344\270\262/kmp \347\256\227\346\263\225" "b/\345\255\227\347\254\246\344\270\262/kmp \347\256\227\346\263\225" new file mode 100644 index 0000000..078eb84 --- /dev/null +++ "b/\345\255\227\347\254\246\344\270\262/kmp \347\256\227\346\263\225" @@ -0,0 +1,21 @@ +KMP 算法 +两字符串n,m进行字符串匹配 +m字符串长度l +关键是求数组next的值 +next是m字符的部分匹配度 +部分匹配度:字符串前缀,后缀的最大公共部分的长度 +PS,前缀,后缀不同于平时使用的前缀,后缀 +例如: +ACDB前缀:包含第一个字符,而不包含最后一个字符的全部子串 +A,AC,ACD +ACDB后缀:不包含最后第一个字符,包含最后一个字符的所有子串 +B,DB,CDB + + A C D B A C + m 0 1 2 3 4 5 + next 0 0 0 0 1 2 + 即next数组[0,0,0,0,1,2] + + 而next的求解很关键,采用动态规划概念 + + 未完待续 From 5995839b9c80df6b1f6f73d16dc80e5eda8e3397 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 20 Oct 2018 23:14:43 +0800 Subject: [PATCH 03/36] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e661349..5592701 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ * BFS/DFS (广度/深度优先遍历) * 红黑树 (一种自平衡的`二叉查找树`) * KMP 字符串匹配算法 +https://github.com/chengmo03013106/Learn-Algorithms/blob/master/%E5%AD%97%E7%AC%A6%E4%B8%B2/kmp%20%E7%AE%97%E6%B3%95 * DP (动态规划 dynamic programming) * A*寻路算法: 求解最短路径 * Dijkstra:最短路径算法 (八卦下:Dijkstra是荷兰的计算机科学家,提出”信号量和PV原语“,"解决哲学家就餐问题",”死锁“也是它提出来的) From 9f201a695e72efb54bfd8f24c785b73ef44bb8de Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 28 Oct 2018 16:53:49 +0800 Subject: [PATCH 04/36] =?UTF-8?q?Create=20DP=20=E7=AE=97=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DP \347\256\227\346\263\225" | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 "15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/DP \347\256\227\346\263\225" diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/DP \347\256\227\346\263\225" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/DP \347\256\227\346\263\225" new file mode 100644 index 0000000..ec84237 --- /dev/null +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/DP \347\256\227\346\263\225" @@ -0,0 +1,94 @@ +三角形问题: +step 1 + +N = 5 +n\r n = 1,2,3...; r=1,2,3... +7 +3 8 +8 1 0 +2 7 4 4 +4 5 2 6 5 + +max value = D(r,j) + +new max value = max(D(r+1,j),D(r+1,j+1)) + D(r,j) + +vvv code vvv +#include +#include +#define MAX 101 +using namespace std; +int D[MAX][MAX]; +int n; +int MaxSum(int i, int j){ + if(i==n) + return D[i][j]; + int x = MaxSum(i+1,j); + int y = MaxSum(i+1,j+1); + return max(x,y)+D[i][j]; +} +int main(){ + int i,j; + cin >> n; + for(i=1;i<=n;i++) + for(j=1;j<=i;j++) + cin >> D[i][j]; + cout << MaxSum(1,1) << endl; +} + +递归转换为递推 +#include +#include +using namespace std; + +#define MAX 101 + +int D[MAX][MAX]; +int n; +int maxSum[MAX][MAX]; +int main(){ + int i,j; + cin >> n; + for(i=1;i<=n;i++) + for(j=1;j<=i;j++) + cin >> D[i][j]; + for( int i = 1;i <= n; ++ i ) + maxSum[n][i] = D[n][i]; + for( int i = n-1; i>= 1; --i ) + for( int j = 1; j <= i; ++j ) + maxSum[i][j] = max(maxSum[i+1][j],maxSum[i+1][j+1]) + D[i][j]; + cout << maxSum[1][1] << endl; +} + +空间优化后,final step +#include +#include +using namespace std; + +#define MAX 101 + +int D[MAX][MAX]; +int n; +int * maxSum; + +int main(){ + int i,j; + cin >> n; + for(i=1;i<=n;i++) + for(j=1;j<=i;j++) + cin >> D[i][j]; + maxSum = D[n]; //maxSum指向第n行 + for( int i = n-1; i>= 1; --i ) + for( int j = 1; j <= i; ++j ) + maxSum[j] = max(maxSum[j],maxSum[j+1]) + D[i][j]; + cout << maxSum[1] << endl; +} + +四个步骤: +划分主要问题为子问题 +确定问题状态,每一个状态,都是一个子问题得到的解 +确定初始状态,三角形问题中,初始化边的数量等 +确定状态转移方程 +定义出什么是“状态”,以及在该“状态”下的“值” +在此之后,就要找出不同的状态之间如何迁移,即如何从一个或多个“值”已知的 “状态”,求出另一个“状态”的“值”(递推型)。 +状态的迁移可以用递推公式表示,此递推公式也可被称作“状态转移方程”。 From a74353849c59fa37ed596bf4fce2940c3520e8d0 Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 28 Oct 2018 16:55:19 +0800 Subject: [PATCH 05/36] Update README.md --- .../README.md" | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 449803c..fe06a31 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -4,8 +4,19 @@ ## Dijkstra:最短路径算法 >Dijkstra是荷兰的计算机科学家,提出”信号量和PV原语“,"解决哲学家就餐问题",”死锁“也是它提出来的 -##DP (Dynamic Programming) -动态规划 +## DP (Dynamic Programming) +动态规划: +动态规划法所针对的问题有一个显著的特征,即它所对应的子问题树中的子问题呈现大量的重复。动态规划法的关键就在于,对于重复出现的子问题,只在第一次遇到时加以求解,并把答案保存起来,让以后再遇到时直接引用,不必重新求解 +经典案例: +1.丢硬币: + +2.背包: +一个最优解的子解,也是最优解。 + +3.最大子数组和问题: + +4.三角形问题 +https://github.com/chengmo03013106/Learn-Algorithms/blob/master/15%E4%B8%AA%E7%BB%8F%E5%85%B8%E5%9F%BA%E7%A1%80%E7%AE%97%E6%B3%95/DP%20%E7%AE%97%E6%B3%95 ##BFS/DFS (广度/深度优先遍历) From 51c9b782124a745f04662a5d0d1968f6e26a72c0 Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 28 Oct 2018 18:28:13 +0800 Subject: [PATCH 06/36] =?UTF-8?q?Create=20=E6=97=B6=E9=97=B4=E5=A4=8D?= =?UTF-8?q?=E6=9D=82=E5=BA=A6=E5=AD=A6=E4=B9=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...5\202\345\272\246\345\255\246\344\271\240" | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 "\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\345\255\246\344\271\240" diff --git "a/\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\345\255\246\344\271\240" "b/\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\345\255\246\344\271\240" new file mode 100644 index 0000000..7e5d06a --- /dev/null +++ "b/\346\227\266\351\227\264\345\244\215\346\235\202\345\272\246\345\255\246\344\271\240" @@ -0,0 +1,33 @@ +时间复杂度: + +通常忽略次高项 +只保留最高项 +忽略常数项 + +1.假设一个循环体的时间复杂度O(n),循环次数m,则时间复杂度O(m * n) +例如: +void aFunc(int n) { + for(int i = 0; i < n; i++) { // 循环次数为 n + printf("Hello, World!\n"); // 循环体时间复杂度为 O(1) + } +} +时间复杂度 T(n) = O(n*1) + +2.多个循环体嵌套, m,n,j,k次,既O(m*n*j*k*循环体复杂度(命令行数)) + +3.对于顺序执行的几个时间复杂度计算 +void aFunc(int n) { + // 第一部分时间复杂度为 O(n^2) + for(int i = 0; i < n; i++) { + for(int j = 0; j < n; j++) { + printf("Hello, World!\n"); + } + } + // 第二部分时间复杂度为 O(n) + for(int j = 0; j < n; j++) { + printf("Hello, World!\n"); + } +} + +时间复杂度以第一部分结果,既max(O(第一部分),O(第二部分)) + From cc1742bfcf9412f7662dbe97cf7b1f693e4751f4 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 3 Nov 2018 23:06:33 +0800 Subject: [PATCH 07/36] Update README.md --- "\345\255\227\347\254\246\344\270\262/README.md" | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git "a/\345\255\227\347\254\246\344\270\262/README.md" "b/\345\255\227\347\254\246\344\270\262/README.md" index 4bb1247..cfaa97f 100644 --- "a/\345\255\227\347\254\246\344\270\262/README.md" +++ "b/\345\255\227\347\254\246\344\270\262/README.md" @@ -8,6 +8,16 @@ * 正则表达式 * 数据压缩 +### 十进制数转换成R进制数 +思路:将目标十进制数不断除以R,并取余,直到结果为0为止 +需要注意的是,最后得到的结果不是数值,而是数值字符串 + +### R进制数转换成十进制数 +按权展开 +比如二进制 1001001 +1*pow(2,0) + 0*pow(2,1) + 0*pow(2,2) + 1*pow(2,3) + 0*pow(2,4) + 0*pow(2,5) + 1*pow(2,6) + +r进制数 改用pow(r,数值) ### 排序 From f2286a699005ab9895595399ad8439d3063000dc Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 3 Jan 2019 15:34:31 +0800 Subject: [PATCH 08/36] =?UTF-8?q?=E5=8D=95=E9=A1=B9=E6=89=AB=E6=8F=8F?= =?UTF-8?q?=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 单项扫描排序 --- ...1\253\346\217\217\346\216\222\345\272\217" | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 "\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217" diff --git "a/\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217" "b/\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217" new file mode 100644 index 0000000..c43f759 --- /dev/null +++ "b/\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217" @@ -0,0 +1,35 @@ +void quicksort(int *a, int left, int right){ + if (left=tmp){ + j--; + } + if (i Date: Thu, 3 Jan 2019 15:34:51 +0800 Subject: [PATCH 09/36] =?UTF-8?q?Rename=20=E5=8D=95=E9=A1=B9=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E6=8E=92=E5=BA=8F=20to=20=E5=8D=95=E9=A1=B9=E6=89=AB?= =?UTF-8?q?=E6=8F=8F=E6=8E=92=E5=BA=8F.cpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\241\271\346\211\253\346\217\217\346\216\222\345\272\217.cpp" | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217" => "\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217.cpp" (100%) diff --git "a/\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217" "b/\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217.cpp" similarity index 100% rename from "\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217" rename to "\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217.cpp" From 721c51442d6c823e41a14b9db64ed6409129bedf Mon Sep 17 00:00:00 2001 From: Martin Date: Thu, 3 Jan 2019 15:35:48 +0800 Subject: [PATCH 10/36] Update README.md --- .../README.md" | 41 +------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git "a/\346\216\222\345\272\217\347\256\227\346\263\225/README.md" "b/\346\216\222\345\272\217\347\256\227\346\263\225/README.md" index 2154964..2ebef2c 100644 --- "a/\346\216\222\345\272\217\347\256\227\346\263\225/README.md" +++ "b/\346\216\222\345\272\217\347\256\227\346\263\225/README.md" @@ -93,46 +93,7 @@ 扫描过程分2种: 1. 挖坑排序,2头向中间扫描,先从后向前找,再从前向后找。 2. 单向扫描 - - void quicksort(int *a, int left, int right){ - if (left=tmp){ - j--; - } - if (i Date: Thu, 3 Jan 2019 15:45:22 +0800 Subject: [PATCH 11/36] =?UTF-8?q?Update=20and=20rename=20=E5=8D=95?= =?UTF-8?q?=E9=A1=B9=E6=89=AB=E6=8F=8F=E6=8E=92=E5=BA=8F.cpp=20to=20quick?= =?UTF-8?q?=20sort.cpp?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quick sort.cpp" | 41 +++++++++++++++++++ ...3\346\217\217\346\216\222\345\272\217.cpp" | 35 ---------------- 2 files changed, 41 insertions(+), 35 deletions(-) create mode 100644 "\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" delete mode 100644 "\346\216\222\345\272\217\347\256\227\346\263\225/\345\215\225\351\241\271\346\211\253\346\217\217\346\216\222\345\272\217.cpp" diff --git "a/\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" "b/\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" new file mode 100644 index 0000000..ca6ad6d --- /dev/null +++ "b/\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" @@ -0,0 +1,41 @@ +void quicksort(int *a, int left, int right){ + if (left=tmp){ + j--; + } + if (i=tmp){ - j--; - } - if (i Date: Thu, 3 Jan 2019 15:52:00 +0800 Subject: [PATCH 12/36] Update quick sort.cpp --- .../quick sort.cpp" | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git "a/\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" "b/\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" index ca6ad6d..b360eee 100644 --- "a/\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" +++ "b/\346\216\222\345\272\217\347\256\227\346\263\225/quick sort.cpp" @@ -1,3 +1,10 @@ +注意: +Pivot的选择是一门学问,直接影响到快速排序算法的效率。 +如果只是简单地选择第一个元素或者最后一个元素,那如果遇到逆序数列,或者已经预处理的数列,则可能降低算法的效率 +比如逆序数列,可能时间复杂度达到pow(n,2) +选择数列中值,从实际经验上看来,是一个很好的解决方案 +中值 = min(max(arr[begin] + arr[end]) + arr[(end-begin)/2]) + void quicksort(int *a, int left, int right){ if (left Date: Fri, 4 Jan 2019 18:10:54 +0800 Subject: [PATCH 13/36] =?UTF-8?q?Update=20and=20rename=20=E8=A1=A5?= =?UTF-8?q?=E5=85=85:C=E8=AF=AD=E8=A8=80=E4=BB=A3=E7=A0=81=E8=A7=84?= =?UTF-8?q?=E8=8C=83.md=20to=20C=E4=BB=A3=E7=A0=81=E7=AC=94=E8=AE=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...73\243\347\240\201\347\254\224\350\256\260.md" | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) rename "\350\241\245\345\205\205:C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203.md" => "C\344\273\243\347\240\201\347\254\224\350\256\260.md" (74%) diff --git "a/\350\241\245\345\205\205:C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203.md" "b/C\344\273\243\347\240\201\347\254\224\350\256\260.md" similarity index 74% rename from "\350\241\245\345\205\205:C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203.md" rename to "C\344\273\243\347\240\201\347\254\224\350\256\260.md" index e3b92c5..67d441f 100644 --- "a/\350\241\245\345\205\205:C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203.md" +++ "b/C\344\273\243\347\240\201\347\254\224\350\256\260.md" @@ -1,7 +1,18 @@ +## const 修饰符 +### 成员函数尽量使用const +const 前置,表示返回值不能被修改 +const 后置,表示该函数不会修改成员变量 +函数参数使用const修饰,可以防止手误 无意义赋值: +if ( a*b = c ) +### 使用const enum inline替换#define,便于调试。因为使用#define定义的变量不进入符号表。 -## 补充:C语言代码规范 +## 构造函数,析构函数 +声明virtual析构函数的前提是:类中至少有一个virtual描述的成员函数,否则没有必要 +一定要在在析构函数中处理掉异常 +不在类成员的构造和析构期间调用虚函数。在派生类构造期间,virtual停留在基类阶层;在基类构造期间,virtual函数还不具有virtual属性。 +## 补充:C语言代码规范 这里面的算法代码均使用C语言完成,养成良好的代码规范习惯,不但可以写出优质的代码,也可以更快的阅读其他优秀开源代码。代码规范主要有: ### 符号命名 @@ -41,7 +52,6 @@ enum conn_states { **函数命名** 全小写,单词之间"_"分割。如"split_cmdline_strerror()" - ### 注释 所有注释使用 "/* 这里是注释 */ " @@ -49,5 +59,4 @@ enum conn_states { ### 其他 -合理使用static,const 等关键字,能提升程序的安全性,也能避免函数命名冲突 合理使用数据类型:rel_time_t,uint8_t,uint32_t,uint64_t,size_t,off_t From 60ad730dcd65a3cca9cc0109886a2f436befdd10 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 4 Jan 2019 18:14:30 +0800 Subject: [PATCH 14/36] =?UTF-8?q?Delete=20C=E4=BB=A3=E7=A0=81=E7=AC=94?= =?UTF-8?q?=E8=AE=B0.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...43\347\240\201\347\254\224\350\256\260.md" | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 "C\344\273\243\347\240\201\347\254\224\350\256\260.md" diff --git "a/C\344\273\243\347\240\201\347\254\224\350\256\260.md" "b/C\344\273\243\347\240\201\347\254\224\350\256\260.md" deleted file mode 100644 index 67d441f..0000000 --- "a/C\344\273\243\347\240\201\347\254\224\350\256\260.md" +++ /dev/null @@ -1,62 +0,0 @@ -## const 修饰符 -### 成员函数尽量使用const -const 前置,表示返回值不能被修改 -const 后置,表示该函数不会修改成员变量 -函数参数使用const修饰,可以防止手误 无意义赋值: -if ( a*b = c ) - -### 使用const enum inline替换#define,便于调试。因为使用#define定义的变量不进入符号表。 - -## 构造函数,析构函数 -声明virtual析构函数的前提是:类中至少有一个virtual描述的成员函数,否则没有必要 -一定要在在析构函数中处理掉异常 -不在类成员的构造和析构期间调用虚函数。在派生类构造期间,virtual停留在基类阶层;在基类构造期间,virtual函数还不具有virtual属性。 - -## 补充:C语言代码规范 -这里面的算法代码均使用C语言完成,养成良好的代码规范习惯,不但可以写出优质的代码,也可以更快的阅读其他优秀开源代码。代码规范主要有: - -### 符号命名 - -**局部变量** 尽量短,能表达清楚意思即可,能简写就简写,比如"err" 表示 "error"; "fd" 表示文件描述符 ,循环变量可以使用i,j,k ;结构体成员变量不需要"m_"前缀;全局变量"g_"开头 - -**常量名** 全大写,单词之间"_"分割,如 "MAX_NUMBER_OF_SLAB_CLASSES" ; - -**宏定义** 对于options 宏定义,适当使用前缀 ,比如: -``` -/* Client classes for client limits, currently used only for - * the max-client-output-buffer limit implementation. */ -#define CLIENT_TYPE_NORMAL 0 /* Normal req-reply clients + MONITORs */ -#define CLIENT_TYPE_SLAVE 1 /* Slaves. */ -#define CLIENT_TYPE_PUBSUB 2 /* Clients subscribed to PubSub channels. */ -#define CLIENT_TYPE_MASTER 3 /* Master. */ -#define CLIENT_TYPE_OBUF_COUNT 3 -``` - -**枚举** 使用前缀: -``` -enum conn_states { - conn_listening, /**< the socket which listens for connections */ - conn_new_cmd, /**< Prepare connection for next command */ - conn_waiting, /**< waiting for a readable socket */ - conn_read, /**< reading in a command line */ - conn_parse_cmd, /**< try to parse a command from the input buffer */ - conn_write, /**< writing out a simple response */ - conn_nread, /**< reading in a fixed number of bytes */ - conn_swallow, /**< swallowing unnecessary bytes w/o storing */ - conn_closing, /**< closing this connection */ - conn_mwrite, /**< writing out many items sequentially */ - conn_closed, /**< connection is closed */ - conn_max_state /**< Max state value (used for assertion) */ -}; -``` - -**函数命名** 全小写,单词之间"_"分割。如"split_cmdline_strerror()" - -### 注释 - -所有注释使用 "/* 这里是注释 */ " - - -### 其他 - -合理使用数据类型:rel_time_t,uint8_t,uint32_t,uint64_t,size_t,off_t From c3df77d87b76612742196f575565e2834db12ce9 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 18 Jan 2019 10:21:05 +0800 Subject: [PATCH 15/36] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5592701..e491f66 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ * 链表 * 双向链表 -### 二叉树 +### 二叉树, std set,map 就是使用平衡二叉树实现 * 二叉树 * 二叉查找树 @@ -39,7 +39,7 @@ * 斐波那契堆(Fibonacci Heap) -###哈希表/散列表 (Hash Table) +### 哈希表/散列表 (Hash Table) * 散列函数 * 碰撞解决 From e392b5c71dde1c00090d20e0b9445bee6718a66a Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 18 Jan 2019 10:28:47 +0800 Subject: [PATCH 16/36] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e491f66..28c87d7 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,8 @@ * 快速排序 * 快递选择SELECT * BFS/DFS (广度/深度优先遍历) -* 红黑树 (一种自平衡的`二叉查找树`) +* 红黑树 (一种自平衡的`二叉查找树`): +通过每次插入,删除后旋转,位置红黑树性质,同时以保证最坏情况下时间复杂度仍然可以接受 * KMP 字符串匹配算法 https://github.com/chengmo03013106/Learn-Algorithms/blob/master/%E5%AD%97%E7%AC%A6%E4%B8%B2/kmp%20%E7%AE%97%E6%B3%95 * DP (动态规划 dynamic programming) From b21ad661c958e25ef8b1baff28e4ef044d177452 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 09:38:16 +0800 Subject: [PATCH 17/36] map using red black tree vs hash map --- .../map_vs_unorder_map.cpp" | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 "15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/map_vs_unorder_map.cpp" diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/map_vs_unorder_map.cpp" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/map_vs_unorder_map.cpp" new file mode 100644 index 0000000..17d90eb --- /dev/null +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/map_vs_unorder_map.cpp" @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include +using namespace std; + +const int kRunTime1 = 1000*1000; // 循环次数 +const int kRunTime2 = 1000*10000; +int main() +{ + std::map mp; + std::unordered_map unordermp; + + timeval st, et; + + cout << "插入个数 = " << kRunTime1 << endl; + gettimeofday(&st, NULL); + for(int i = 0; i < kRunTime1; ++i) + { + mp.insert(make_pair(i, i)); + } + gettimeofday(&et, NULL); + cout << "1 有序map测试时间insert time:" << (et.tv_sec-st.tv_sec)*1000 + (et.tv_usec-st.tv_usec)/1000 << "ms" << endl; + + gettimeofday(&st, NULL); + for(int i = 0; i < kRunTime1; ++i) + { + unordermp.insert(make_pair(i, i)); + } + gettimeofday(&et, NULL); + cout << "1 无序map测试时间insert time:" << (et.tv_sec-st.tv_sec)*1000 + (et.tv_usec-st.tv_usec)/1000 << "ms" << endl; + + cout << "\n插入个数 = " << kRunTime2 << endl; + mp.clear(); + gettimeofday(&st, NULL); + for(int i = 0; i < kRunTime2; ++i) + { + mp.insert(make_pair(i, i)); + } + gettimeofday(&et, NULL); + cout << "2 有序map测试时间insert time:" << (et.tv_sec-st.tv_sec)*1000 + (et.tv_usec-st.tv_usec)/1000 << "ms" << endl; + + mp.clear(); + gettimeofday(&st, NULL); + for(int i = 0; i < kRunTime2; ++i) + { + mp.emplace(make_pair(i, i)); + } + gettimeofday(&et, NULL); + cout << "2 有序map测试时间emplace time:" << (et.tv_sec-st.tv_sec)*1000 + (et.tv_usec-st.tv_usec)/1000 << "ms" << endl; + + unordermp.clear(); + gettimeofday(&st, NULL); + for(int i = 0; i < kRunTime2; ++i) + { + unordermp.insert(make_pair(i, i)); + } + gettimeofday(&et, NULL); + cout << "2 无序map测试时间insert time:" << (et.tv_sec-st.tv_sec)*1000 + (et.tv_usec-st.tv_usec)/1000 << "ms" << endl; + + unordermp.clear(); + gettimeofday(&st, NULL); + for(int i = 0; i < kRunTime2; ++i) + { + unordermp.emplace(make_pair(i, i)); + } + gettimeofday(&et, NULL); + cout << "2 无序map测试时间emplace time:" << (et.tv_sec-st.tv_sec)*1000 + (et.tv_usec-st.tv_usec)/1000 << "ms" << endl; + + return 0; +} +--------------------- + +/* first round */ +插入个数 = 1000000 +1 有序map测试时间insert time:922ms +1 无序map测试时间insert time:360ms + +插入个数 = 10000000 +2 有序map测试时间insert time:10451ms +2 有序map测试时间emplace time:10531ms +2 无序map测试时间insert time:3854ms +2 无序map测试时间emplace time:2956ms +--------------------- +/* second round */ +插入个数 = 1000000 +1 有序map测试时间insert time:918ms +1 无序map测试时间insert time:344ms + +插入个数 = 10000000 +2 有序map测试时间insert time:10470ms +2 有序map测试时间emplace time:10597ms +2 无序map测试时间insert time:3826ms +2 无序map测试时间emplace time:2932ms +--------------------- +/* third round*/ +插入个数 = 1000000 +1 有序map测试时间insert time:909ms +1 无序map测试时间insert time:376ms + +插入个数 = 10000000 +2 有序map测试时间insert time:10395ms +2 有序map测试时间emplace time:10505ms +2 无序map测试时间insert time:4015ms +2 无序map测试时间emplace time:3102ms +--------------------- From 63248bb78e03afdca3e9c8d0bda05b63fd084f4d Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 09:54:53 +0800 Subject: [PATCH 18/36] Adding scaling of compartion hash map and map. --- .../README.md" | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index fe06a31..5f9576a 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -21,9 +21,29 @@ https://github.com/chengmo03013106/Learn-Algorithms/blob/master/15%E4%B8%AA%E7%B ##BFS/DFS (广度/深度优先遍历) -##红黑树 +## 红黑树 一种自平衡的`二叉查找树` +map和hash_map性能测试 +大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 + 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: + hash_map(10万) map(10万) hash_map(20万) map(20万) hash_map(30万) map(30万) +添加 93 47 156 94 203 172 +遍历 16 15 16 16 16 15 +查找 0 0 32 31 31 32 +删除 8422 32 33765 63 76016 78 + +hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 + + +时间单位仍为毫秒:map遍历性能较好,查找性能低于hash map + hash_map(100万) map(100万) hash_map(200万) map(200万) hash_map(300万) map(300万) +遍历 94 31 203 32 297 47 +查找 94 234 188 531 281 875 + +### 结论: +两大组测试完毕,整体结论也可以得出:一般应用情况下,我们保存的数据不超过100万份,查找的频繁程度不高情况下使用map性能比较好;而保存的数据较多时(超过100万),查找频繁时使用hash_map的性能就高于map了。 + ##KMP 字符串匹配算法 From 114b7bb5210a35b63ba9ebd90912aa2544c8893c Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 09:55:41 +0800 Subject: [PATCH 19/36] Update README.md --- .../README.md" | 4 ++++ 1 file changed, 4 insertions(+) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 5f9576a..917486e 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -29,10 +29,14 @@ map和hash_map性能测试 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: hash_map(10万) map(10万) hash_map(20万) map(20万) hash_map(30万) map(30万) 添加 93 47 156 94 203 172 + 遍历 16 15 16 16 16 15 + 查找 0 0 32 31 31 32 + 删除 8422 32 33765 63 76016 78 + hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 From c123ffac72b5145ed0ac3c9a22ee7588030f3fd7 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 09:56:24 +0800 Subject: [PATCH 20/36] Update README.md --- .../README.md" | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 917486e..75858dd 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -28,22 +28,19 @@ map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: hash_map(10万) map(10万) hash_map(20万) map(20万) hash_map(30万) map(30万) -添加 93 47 156 94 203 172 - -遍历 16 15 16 16 16 15 - -查找 0 0 32 31 31 32 - -删除 8422 32 33765 63 76016 78 + 添加 93 47 156 94 203 172 + 遍历 16 15 16 16 16 15 + 查找 0 0 32 31 31 32 + 删除 8422 32 33765 63 76016 78 hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 时间单位仍为毫秒:map遍历性能较好,查找性能低于hash map - hash_map(100万) map(100万) hash_map(200万) map(200万) hash_map(300万) map(300万) -遍历 94 31 203 32 297 47 -查找 94 234 188 531 281 875 + hash_map(100万) map(100万) hash_map(200万) map(200万) hash_map(300万) map(300万) + 遍历 94 31 203 32 297 47 + 查找 94 234 188 531 281 875 ### 结论: 两大组测试完毕,整体结论也可以得出:一般应用情况下,我们保存的数据不超过100万份,查找的频繁程度不高情况下使用map性能比较好;而保存的数据较多时(超过100万),查找频繁时使用hash_map的性能就高于map了。 From 217646c9e057d124160f27e3d6674db975a76244 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:03:00 +0800 Subject: [PATCH 21/36] Update README.md --- .../README.md" | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 75858dd..8d93430 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -27,11 +27,11 @@ https://github.com/chengmo03013106/Learn-Algorithms/blob/master/15%E4%B8%AA%E7%B map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: - hash_map(10万) map(10万) hash_map(20万) map(20万) hash_map(30万) map(30万) - 添加 93 47 156 94 203 172 - 遍历 16 15 16 16 16 15 - 查找 0 0 32 31 31 32 - 删除 8422 32 33765 63 76016 78 +|:-:|hash_map(10万)|map(10万)|hash_map(20万)|map(20万)|hash_map(30万)|map(30万) +添加|93|47|156|94|203|172 +遍历|16|15|16|16|16|15 +查找|0|0|32| 31|31|32 +删除|8422|32|33765|63|76016|78 hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 From d31b2f26d7a75d1e432a7c6c6fcfd724d28491c9 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:04:05 +0800 Subject: [PATCH 22/36] Update README.md --- .../README.md" | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 8d93430..c6e603a 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -27,11 +27,11 @@ https://github.com/chengmo03013106/Learn-Algorithms/blob/master/15%E4%B8%AA%E7%B map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: -|:-:|hash_map(10万)|map(10万)|hash_map(20万)|map(20万)|hash_map(30万)|map(30万) -添加|93|47|156|94|203|172 -遍历|16|15|16|16|16|15 -查找|0|0|32| 31|31|32 -删除|8422|32|33765|63|76016|78 +|:-:|hash_map(10万)|map(10万)|hash_map(20万)|map(20万)|hash_map(30万)|map(30万)| +|添加|93|47|156|94|203|172| +|遍历|16|15|16|16|16|15| +|查找|0|0|32|31|31|32| +|删除|8422|32|33765|63|76016|78| hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 From aa88b30cfa83f532942eeb5f1b5e62d35feec7c6 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:07:33 +0800 Subject: [PATCH 23/36] Update README.md --- .../README.md" | 2 ++ 1 file changed, 2 insertions(+) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index c6e603a..1dba57c 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -27,7 +27,9 @@ https://github.com/chengmo03013106/Learn-Algorithms/blob/master/15%E4%B8%AA%E7%B map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: + |:-:|hash_map(10万)|map(10万)|hash_map(20万)|map(20万)|hash_map(30万)|map(30万)| +|----|----|----|----|--------|----| |添加|93|47|156|94|203|172| |遍历|16|15|16|16|16|15| |查找|0|0|32|31|31|32| From 5ddd476a2413aba7f73f82f27963830e29506736 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:08:13 +0800 Subject: [PATCH 24/36] Update README.md --- .../README.md" | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 1dba57c..d5d0b21 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -28,12 +28,12 @@ map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: -|:-:|hash_map(10万)|map(10万)|hash_map(20万)|map(20万)|hash_map(30万)|map(30万)| -|----|----|----|----|--------|----| -|添加|93|47|156|94|203|172| -|遍历|16|15|16|16|16|15| -|查找|0|0|32|31|31|32| -|删除|8422|32|33765|63|76016|78| +:-:|hash_map(10万)|map(10万)|hash_map(20万)|map(20万)|hash_map(30万)|map(30万) +----|----|----|----|--------|---- +添加|93|47|156|94|203|172 +遍历|16|15|16|16|16|15 +查找|0|0|32|31|31|32 +删除|8422|32|33765|63|76016|78 hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 From dd2eaa981edcf96d5268f83ccf356e25f1c99069 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:09:23 +0800 Subject: [PATCH 25/36] Update README.md --- .../README.md" | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index d5d0b21..7640b0f 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -28,8 +28,7 @@ map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: -:-:|hash_map(10万)|map(10万)|hash_map(20万)|map(20万)|hash_map(30万)|map(30万) -----|----|----|----|--------|---- + :-: | hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) 添加|93|47|156|94|203|172 遍历|16|15|16|16|16|15 查找|0|0|32|31|31|32 From 11185dd83c2a09f0c346ed2e6475ae2de58597dc Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:11:29 +0800 Subject: [PATCH 26/36] Update README.md --- .../README.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 7640b0f..2fd718b 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -29,10 +29,10 @@ map和hash_map性能测试 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: :-: | hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) -添加|93|47|156|94|203|172 -遍历|16|15|16|16|16|15 -查找|0|0|32|31|31|32 -删除|8422|32|33765|63|76016|78 + 添加 | 93 | 47 | 156 | 94 | 203 | 172 + 遍历 | 16 | 15 | 16 | 16 | 16 | 15 + 查找 | 0 | 0 | 32 | 31 | 31 | 32 + 删除 | 84 | 2 | 2 | 32 | 33765 | 63 | 76016 | 78 hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 From 51b0ea86b908ff6d3d99908a8aa9c4f8de374d9b Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:14:23 +0800 Subject: [PATCH 27/36] Update README.md --- .../README.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 2fd718b..85b2e25 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -28,7 +28,7 @@ map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: - :-: | hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) + | hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) 添加 | 93 | 47 | 156 | 94 | 203 | 172 遍历 | 16 | 15 | 16 | 16 | 16 | 15 查找 | 0 | 0 | 32 | 31 | 31 | 32 From 93fdb0795e2fc49941a7329f7f13f7f09e35bef2 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:15:20 +0800 Subject: [PATCH 28/36] Update README.md --- .../README.md" | 1 + 1 file changed, 1 insertion(+) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 85b2e25..249a53e 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -29,6 +29,7 @@ map和hash_map性能测试 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: | hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) + | ------| ------- | ------ | ------ | ------- | ------ 添加 | 93 | 47 | 156 | 94 | 203 | 172 遍历 | 16 | 15 | 16 | 16 | 16 | 15 查找 | 0 | 0 | 32 | 31 | 31 | 32 From d8c8c73c3b5f6a7e031d3f78cac58ce2dd0b8284 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:16:46 +0800 Subject: [PATCH 29/36] Update README.md --- .../README.md" | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 249a53e..54a4f96 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -28,12 +28,12 @@ map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: - | hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) - | ------| ------- | ------ | ------ | ------- | ------ - 添加 | 93 | 47 | 156 | 94 | 203 | 172 - 遍历 | 16 | 15 | 16 | 16 | 16 | 15 - 查找 | 0 | 0 | 32 | 31 | 31 | 32 - 删除 | 84 | 2 | 2 | 32 | 33765 | 63 | 76016 | 78 + 1| hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) + 2| ------| ------- | ------ | ------ | ------- | ------ + 3|添加 | 93 | 47 | 156 | 94 | 203 | 172 + 4|遍历 | 16 | 15 | 16 | 16 | 16 | 15 + 5|查找 | 0 | 0 | 32 | 31 | 31 | 32 + 6|删除 | 84 | 2 | 2 | 32 | 33765 | 63 | 76016 | 78 hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 From 08142d65e8aff51722060b1f618bd5aef83be14a Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 23 Jan 2019 10:20:04 +0800 Subject: [PATCH 30/36] Update README.md --- .../README.md" | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index 54a4f96..a5a82ff 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -28,12 +28,12 @@ map和hash_map性能测试 大家都知道在C++的STL中map是使用树来做查找算法,而hash_map使用hash表来排列配对,是使用关键字来计算表位置。那使用起来他们的差别主要是什么呢?对于性能差别是什么,适合什么情况下应用呢?于是我对它们进行了一些测试,并记录了测试数据供大家分享。 测试的内容主要是map和hash_map的添加、删除、查找和遍历操作,首先进行了几组测试,分别是10万次、30万次,时间单位均为毫秒,具体的性能对照如下: - 1| hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万) - 2| ------| ------- | ------ | ------ | ------- | ------ - 3|添加 | 93 | 47 | 156 | 94 | 203 | 172 - 4|遍历 | 16 | 15 | 16 | 16 | 16 | 15 - 5|查找 | 0 | 0 | 32 | 31 | 31 | 32 - 6|删除 | 84 | 2 | 2 | 32 | 33765 | 63 | 76016 | 78 + 1| hash_map(10万) | map(10万) | hash_map(20万) | map(20万) | hash_map(30万) | map(30万)
+ 2| ------| ------- | ------ | ------ | ------- | ------
+ 3|添加 | 93 | 47 | 156 | 94 | 203 | 172
+ 4|遍历 | 16 | 15 | 16 | 16 | 16 | 15
+ 5|查找 | 0 | 0 | 32 | 31 | 31 | 32
+ 6|删除 | 84 | 2 | 2 | 32 | 33765 | 63 | 76016 | 78
hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比map可能慢1000倍,从而得到结论是删除和插入操作较多的情况下,map比hash_map的性能更好,添加和删除的数据量越大越明显。 @@ -45,7 +45,7 @@ hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比m 查找 94 234 188 531 281 875 ### 结论: -两大组测试完毕,整体结论也可以得出:一般应用情况下,我们保存的数据不超过100万份,查找的频繁程度不高情况下使用map性能比较好;而保存的数据较多时(超过100万),查找频繁时使用hash_map的性能就高于map了。 +**两大组测试完毕,整体结论也可以得出:一般应用情况下,我们保存的数据不超过100万份,查找的频繁程度不高情况下使用map性能比较好;而保存的数据较多时(超过100万),查找频繁时使用hash_map的性能就高于map了。** ##KMP 字符串匹配算法 From 93f596fe36938c9182488a92f9b60e3b6884c0b5 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 29 Jan 2019 15:59:44 +0800 Subject: [PATCH 31/36] Update README.md --- .../README.md" | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" index a5a82ff..ae335d7 100644 --- "a/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" +++ "b/15\344\270\252\347\273\217\345\205\270\345\237\272\347\241\200\347\256\227\346\263\225/README.md" @@ -52,7 +52,13 @@ hash_map的添加和删除操作比map要慢,尤其是删除操作hash_map比m ##遗传算法 -##启发式搜索 +## 启发式搜索 +启发式简单例子: +内存分配: +*** +if num == size + size *= 2 +*** ##图像特征提取之SIFT算法 From bd13aea7b1a477f28a55cf9310b7bf5bd4407538 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 30 Jan 2019 17:20:46 +0800 Subject: [PATCH 32/36] =?UTF-8?q?C=E8=AF=AD=E8=A8=80=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E8=A7=84=E8=8C=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit add C语言代码规范 --- ...3\243\347\240\201\350\247\204\350\214\203" | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 "C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203" diff --git "a/C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203" "b/C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203" new file mode 100644 index 0000000..e3b92c5 --- /dev/null +++ "b/C\350\257\255\350\250\200\344\273\243\347\240\201\350\247\204\350\214\203" @@ -0,0 +1,53 @@ + + +## 补充:C语言代码规范 + +这里面的算法代码均使用C语言完成,养成良好的代码规范习惯,不但可以写出优质的代码,也可以更快的阅读其他优秀开源代码。代码规范主要有: + +### 符号命名 + +**局部变量** 尽量短,能表达清楚意思即可,能简写就简写,比如"err" 表示 "error"; "fd" 表示文件描述符 ,循环变量可以使用i,j,k ;结构体成员变量不需要"m_"前缀;全局变量"g_"开头 + +**常量名** 全大写,单词之间"_"分割,如 "MAX_NUMBER_OF_SLAB_CLASSES" ; + +**宏定义** 对于options 宏定义,适当使用前缀 ,比如: +``` +/* Client classes for client limits, currently used only for + * the max-client-output-buffer limit implementation. */ +#define CLIENT_TYPE_NORMAL 0 /* Normal req-reply clients + MONITORs */ +#define CLIENT_TYPE_SLAVE 1 /* Slaves. */ +#define CLIENT_TYPE_PUBSUB 2 /* Clients subscribed to PubSub channels. */ +#define CLIENT_TYPE_MASTER 3 /* Master. */ +#define CLIENT_TYPE_OBUF_COUNT 3 +``` + +**枚举** 使用前缀: +``` +enum conn_states { + conn_listening, /**< the socket which listens for connections */ + conn_new_cmd, /**< Prepare connection for next command */ + conn_waiting, /**< waiting for a readable socket */ + conn_read, /**< reading in a command line */ + conn_parse_cmd, /**< try to parse a command from the input buffer */ + conn_write, /**< writing out a simple response */ + conn_nread, /**< reading in a fixed number of bytes */ + conn_swallow, /**< swallowing unnecessary bytes w/o storing */ + conn_closing, /**< closing this connection */ + conn_mwrite, /**< writing out many items sequentially */ + conn_closed, /**< connection is closed */ + conn_max_state /**< Max state value (used for assertion) */ +}; +``` + +**函数命名** 全小写,单词之间"_"分割。如"split_cmdline_strerror()" + + +### 注释 + +所有注释使用 "/* 这里是注释 */ " + + +### 其他 + +合理使用static,const 等关键字,能提升程序的安全性,也能避免函数命名冲突 +合理使用数据类型:rel_time_t,uint8_t,uint32_t,uint64_t,size_t,off_t From a6ee9a9c8287dca4de3af02e3686cbfb269f724f Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 11 Oct 2019 16:11:24 +0800 Subject: [PATCH 33/36] Update README.md merge ngx_queue_t, which is double link with sentry. --- "\351\223\276\350\241\250/README.md" | 58 ++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git "a/\351\223\276\350\241\250/README.md" "b/\351\223\276\350\241\250/README.md" index 714a1fe..f4c40dc 100644 --- "a/\351\223\276\350\241\250/README.md" +++ "b/\351\223\276\350\241\250/README.md" @@ -24,5 +24,63 @@ typedef struct Entry{ ``` +### 带哨兵的双向链表 + +取自Nginx 源码 中 ngx_queue_t 的使用: +``` +struct ngx_queue_s { + ngx_queue_t * prev; + ngx_queue_t * prev; +} ngx_queue_t; +``` + +首先定义,并且初始化一个哨兵节点 +``` +ngx_queue_t sentry; +ngx_queue_init(&sentry); +``` +定义自己的结构体: +``` +struct my_node_t { + int a; + char b; + void c; + // 加入queue节点 + ngx_queue_t queue; +}; +``` +#### 插入 +``` +//头部插入 +int insert_head(h,x) { + (x)->next = (h)->next; + (x)->next->prev = x; + (x)->prev = h; + (h)->next = x; +} + +//尾部插入 +int insert_tail(h,x) { + (x)->prev = (h)->prev; + (x)->prev->next = x; + (x)->next = h; + (h)->prev = x; +} +``` + +用法: +``` +my_node_t x,y; +insert_head(&sentry,&x); +insert_tail(&sentry,&y); +``` +PS:保持哨兵节点的 prev 指向链表的尾数据节点,next 指向链表的头数据节点 + + + + + + + From fd814ebcc135e38d7cba0bea5d77e129f1b834b5 Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 11 Oct 2019 18:10:30 +0800 Subject: [PATCH 34/36] Update README.md silly mistake --- "\351\223\276\350\241\250/README.md" | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git "a/\351\223\276\350\241\250/README.md" "b/\351\223\276\350\241\250/README.md" index f4c40dc..3f6c0b7 100644 --- "a/\351\223\276\350\241\250/README.md" +++ "b/\351\223\276\350\241\250/README.md" @@ -24,7 +24,7 @@ typedef struct Entry{ ``` -### 带哨兵的双向链表 +### 带哨兵(sentinel)的双向链表 取自Nginx 源码 中 ngx_queue_t 的使用: ``` @@ -36,8 +36,8 @@ struct ngx_queue_s { 首先定义,并且初始化一个哨兵节点 ``` -ngx_queue_t sentry; -ngx_queue_init(&sentry); +ngx_queue_t sentinel; +ngx_queue_init(&sentinel); ``` 定义自己的结构体: ``` @@ -71,10 +71,10 @@ int insert_tail(h,x) { 用法: ``` my_node_t x,y; -insert_head(&sentry,&x); -insert_tail(&sentry,&y); +insert_head(&sentinel,&x); +insert_tail(&sentinel,&y); ``` -PS:保持哨兵节点的 prev 指向链表的尾数据节点,next 指向链表的头数据节点 +PS:保持哨兵(sentinel)节点的 prev 指向链表的尾数据节点,next 指向链表的头数据节点 From de2426b29e2ab284c5ddc063ec63b07271338c16 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 6 Nov 2019 14:42:09 +0800 Subject: [PATCH 35/36] =?UTF-8?q?Update=20=E5=A0=86=E5=92=8C=E6=A0=88.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 栈的排序:利用辅助栈对已有栈进行排序 --- .../\345\240\206\345\222\214\346\240\210.md" | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git "a/\347\256\227\346\263\225\351\227\256\351\242\230\351\200\211\347\274\226/\345\240\206\345\222\214\346\240\210.md" "b/\347\256\227\346\263\225\351\227\256\351\242\230\351\200\211\347\274\226/\345\240\206\345\222\214\346\240\210.md" index 926492e..158d27a 100644 --- "a/\347\256\227\346\263\225\351\227\256\351\242\230\351\200\211\347\274\226/\345\240\206\345\222\214\346\240\210.md" +++ "b/\347\256\227\346\263\225\351\227\256\351\242\230\351\200\211\347\274\226/\345\240\206\345\222\214\346\240\210.md" @@ -1,5 +1,5 @@ -##堆和栈 +## 堆和栈 栈的数据结构 @@ -42,9 +42,23 @@ void enqueue(Queue,Value); void dequeue(Queue); ``` - 这里的题目是有关栈和队列的问题。 +#### 栈的排序:利用辅助栈对已有栈进行排序 + +题目: + +一个栈中元素的类型为整型,现在想将该栈从顶到底按从大到小的顺序排序,只许申请一个栈,除此之外可以申请新的变量,但不能申请额外的数据结构。如何完成排序? + +题解: + +需要用到辅助栈。stack执行pop操作,弹出元素记为cur; + +如果cur小于或等于assist的栈顶元素,则将cur直接压入assist; + +如果cur大于assist的栈顶元素,则将assist的元素逐一弹出并压入stack,知道cur小于或等于assist的栈顶元素,再将cur压入assist + +执行上述操作后,直到stack空,将assist所有元素逐一压入stack #### 循环队列中元素个数 @@ -136,4 +150,4 @@ void reverseStack(){ - \ No newline at end of file + From 380cf45514805a1e5d76adcd6ee06287052021a0 Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 13 Dec 2021 23:49:46 +0800 Subject: [PATCH 36/36] Update README.md --- .../3-\345\271\263\350\241\241\346\240\221AVL/README.md" | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git "a/\344\272\214\345\217\211\346\240\221/3-\345\271\263\350\241\241\346\240\221AVL/README.md" "b/\344\272\214\345\217\211\346\240\221/3-\345\271\263\350\241\241\346\240\221AVL/README.md" index cacf95a..e613715 100644 --- "a/\344\272\214\345\217\211\346\240\221/3-\345\271\263\350\241\241\346\240\221AVL/README.md" +++ "b/\344\272\214\345\217\211\346\240\221/3-\345\271\263\350\241\241\346\240\221AVL/README.md" @@ -1,9 +1,14 @@ ### AVL 实现过程中的问题 +不平衡定义:左右子树深度>=2 +1. RR,root右旋90度 +2. LL,root左旋90度 +3. RL,先右旋,再左旋;右旋时,甩锅到小弟,小弟执行右旋90度;领导直接踩在有问题的同事(引起不平衡的节点)头上;然后执行左旋;之前如果有子树,先去掉;等旋转结束后,再回来按照大小处理子树位置。 +4. LR,先左旋,再右旋;左旋时,帅锅到小弟,小弟替领导左旋90度;同上,左右相反。 ### AVL 实际使用案例 * LLVM 的 ImmutableSet,其底层的实现选择为 AVL 树 - * 《一种基于二叉平衡树的P2P覆盖网络的研究》论文 \ No newline at end of file + * 《一种基于二叉平衡树的P2P覆盖网络的研究》论文