Skip to content

Commit 687d64d

Browse files
committed
update content
1 parent 7538c90 commit 687d64d

File tree

12 files changed

+360
-21
lines changed

12 files changed

+360
-21
lines changed

Algorithm/Sort.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,13 @@ print count_sort(case, 5)
320320
3. 对每个不是空的桶子进行排序。
321321
4. 从不是空的桶子里把项目再放回原来的序列中。
322322

323+
# 混合排序
324+
325+
Introsort(内省排序)是由David Musser在1997年设计的排序算法。这个排序算法首先从快速排序开始,当递归深度超过一定深度(深度为排序元素数量的对数值)后转为堆排序。采用这个方法,内省排序既能在常规数据集上实现快速排序的高性能,又能在最坏情况下仍保持。
326+
327+
introsort的大致思想是:当数据很大时先用quicksort,当递归超过一定深度时改用heapsort,最后每个子序列元素个数小于某个阈值时,就改用insertionsort。由此可知,它乃综合各家之长的算法。
328+
在2000年6月,SGI的C++标准模板库的 [stl_algo.h](http://www.sgi.com/tech/stl/stl_algo.h) 中的不稳定排序算法采用了Musser的introsort算法。在此实现中,切换到插入排序的数据量阈值为16个。
329+
323330
# 更多阅读
324331

325332
[冒泡排序](https://zh.wikipedia.org/wiki/冒泡排序)

C++/GDB_Debug.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,13 @@ gdb调试中需要用到的命令
177177

178178
![][1]
179179

180+
180181
# 参考
181182

182183
[使用gdb调试程序详解](http://www.vimer.cn/2009/11/使用gdb调试程序详解.html)
183184
[GDB中应该知道的几个调试方法](http://coolshell.cn/articles/3643.html)
184-
[Codesign gdb on Mac OS X Yosemite](http://andresabino.com/2015/04/14/codesign-gdb-on-mac-os-x-yosemite-10-10-2/)
185+
[Codesign gdb on Mac OS X Yosemite](http://andresabino.com/2015/04/14/codesign-gdb-on-mac-os-x-yosemite-10-10-2/)
186+
[C++编译器无法捕捉到的8种错误](http://blog.jobbole.com/15837/)
185187

186188
[1]: http://7xrlu9.com1.z0.glb.clouddn.com/C++_GDB_Debug_1.png
187189

C++/Keywords.md

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ int main()
242242
243243
# final
244244
245-
C++ 11 中引入了final关键字
245+
C++ 11 中引入了final关键字,用来阻止类的进一步派生和虚函数的进一步重载。
246246
247247
> Specifies that a virtual function cannot be overridden in a derived class or that a class cannot be inherited from.
248248
@@ -270,7 +270,42 @@ struct C : B // Error: B is final
270270
};
271271
```
272272

273-
[final 描述错误](http://www.nowcoder.com/questionTerminal/8272c92814ca40c39f9a534485c90be2)
273+
# override
274+
275+
一个派生类可以覆盖在基类中声明的虚函数,这是面向对象设计的基础。然而这么简单的操作也会出错,关于覆盖虚函数的两个常见错误如下:
276+
277+
* `无意中覆盖`:派生类不小心实现了一个和基类名字和参数列表相同的虚函数。
278+
* `签名不匹配`:本来要覆盖基类的虚函数,结果导致产生了一个新的函数。
279+
280+
使用 override 可以避免这两个问题。因为 override 明确告诉编译器该函数覆盖了基类中的虚函数,任何违反了这一语义的实现编译器都将显式地给出错误提示。
281+
282+
> In a member function declaration or definition, override ensures that the function is virtual and is overriding a virtual function from the base class. The program is ill-formed (a compile-time error is generated) if this is not true.
283+
284+
看一个简单的例子:
285+
286+
```c++
287+
struct A
288+
{
289+
virtual void foo();
290+
void bar();
291+
};
292+
293+
struct B : A
294+
{
295+
void foo() const override; // Error: B::foo does not override A::foo
296+
// (signature mismatch)
297+
void foo() override; // OK: B::foo overrides A::foo
298+
void bar() override; // Error: A::bar is not virtual
299+
};
300+
```
301+
302+
编译器实现 override 的方法很简单,如下:
303+
304+
> The override special identifier means that the compiler will check the base class(es) to see if there is a virtual function with this exact signature. And if there is not, the compiler will error out.
305+
306+
不过注意 override 和 final 一样,不是C++保留字:
307+
308+
> Note that neither override nor final are language keywords. They are technically identifiers; they only gain special meaning when used in those specific contexts. In any other location, they can be valid identifiers.
274309
275310
# 更多阅读
276311

Coding/ProducerConsumer.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
/*
22
* @Author: [email protected]
3-
* @Last Modified time: 2016-04-18 17:37:33
3+
* @Last Modified time: 2016-09-10 11:12:19
4+
* Worked on Mac OS X
45
*/
56

67
#include <stdio.h>
78
#include <stdlib.h>
89
#include <pthread.h>
910
#include <unistd.h>
10-
#include <dispatch/dispatch.h>
11+
#include <dispatch/dispatch.h> // OS X
1112

1213
const int BufLen = 10; // 缓冲区长度
1314
int buf[BufLen] = {0};

DataBase/Index.md

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用
7272
7373
## 为什么使用B+Tree
7474
75-
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在查找过程中磁盘I/O操作次数的渐进复杂度。换句话说,**索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数**。
75+
一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储的磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,I/O存取的消耗要高几个数量级,所以评价一个数据结构作为索引的优劣最重要的指标就是在**查找过程中磁盘I/O操作次数的渐进复杂度**。换句话说,**索引的结构组织要尽量减少查找过程中磁盘I/O的存取次数**。
7676
7777
### 磁盘存取原理
7878
@@ -93,7 +93,7 @@ B-Tree有许多变种,其中最常见的是B+Tree,例如MySQL就普遍使用
9393
9494
一般来说,B+Tree比B-Tree更适合实现外存储索引结构,具体原因与外存储器原理及计算机存取原理有关。
9595
96-
先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:
96+
先从B-Tree分析,根据B-Tree的定义,可知检索一次最多需要访问h个节点。数据库系统的设计者巧妙利用了磁盘预读原理,将**一个节点的大小设为等于一个页**,这样每个节点只需要一次I/O就可以完全载入。为了达到这个目的,在实际实现B-Tree还需要使用如下技巧:
9797
9898
每次新建节点时,直接申请一个页的空间,这样就保证一个节点物理上也存储在一个页里,加之计算机存储分配都是按页对齐的,就实现了一个node只需一次I/O。B-Tree中一次检索最多需要h-1次I/O(根节点常驻内存),渐进复杂度为O(h)=O(log<sub>d</sub>N)。一般实际应用中,出度d是非常大的数字,通常超过100,因此h非常小(通常不超过3)。综上所述,用B-Tree作为索引结构效率是非常高的。
9999
@@ -107,7 +107,7 @@ floor表示向下取整。由于B+Tree内节点去掉了data域,因此可以
107107
108108
从数据结构角度看,索引分为以下几类:
109109
110-
1. B+树索引:最常见的索引类型,基于B-Tree数据结构。B-Tree的基本思想是,所有值(被索引的列)都是排过序的,每个叶节点到跟节点距离相等。所以B-Tree适合用来查找某一范围内的数据,而且可以直接支持数据排序(ORDER BY)。但是当索引多列时,列的顺序特别重要,需要格外注意。InnoDB和MyISAM都支持B-Tree索引。InnoDB用的是一个变种B+Tree,而MyISAM为了节省空间对索引进行了压缩,从而牺牲了性能。
110+
1. B+树索引:最常见的索引类型,基于B-Tree数据结构。B-Tree的基本思想是,所有值(被索引的列)都是排过序的,每个叶节点到根节点距离相等。所以B-Tree适合用来查找某一范围内的数据,而且可以直接支持数据排序(ORDER BY)。但是当索引多列时,列的顺序特别重要,需要格外注意。InnoDB和MyISAM都支持B-Tree索引。InnoDB用的是一个变种B+Tree,而MyISAM为了节省空间对索引进行了压缩,从而牺牲了性能。
111111
2. hash索引:基于hash表。所以这种索引只支持精确查找,不支持范围查找,不支持排序。其检索效率非常高,检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。目前只有Memory引擎支持显式的hash索引,Memory引擎默认的索引类型即是Hash索引,虽然它也支持B-Tree索引。
112112
3. FULLTEXT索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较。Full-text索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的 WHERE 语句的参数匹配。可以对某列分别进行full-text索引和B-Tree索引,两者互不冲突。Full-text索引配合MATCH AGAINST操作使用,而不是一般的WHERE语句加LIKE。
113113
4. Spatial (R-Tree)(空间)索引:只有MyISAM引擎支持,并且支持的不好。
@@ -150,7 +150,6 @@ floor表示向下取整。由于B+Tree内节点去掉了data域,因此可以
150150
151151
这里先说一下`联合索引`的概念。在上文中,我们都是假设索引只引用了单个的列,实际上,MySQL中的索引可以以一定顺序引用多个列,这种索引叫做联合索引,一般的,一个联合索引是一个有序元组<a1, a2, …, an>,其中各个元素均为数据表的一列。因此,单列索引可以看成联合索引元素数为1的特例。以employees.titles表为例,下面先查看其上都有哪些索引:
152152
153-
154153
```SQL
155154
SHOW INDEX FROM employees.titles;
156155
+--------+------------+----------+--------------+-------------+-----------+-------------+------+------------+
@@ -163,15 +162,14 @@ SHOW INDEX FROM employees.titles;
163162
+--------+------------+----------+--------------+-------------+-----------+-------------+------+------------+
164163
```
165164

166-
从结果中可以到titles表的主索引为<emp_no, title, from_date>,还有一个辅助索引<emp_no>。为了避免多个索引使事情变复杂(MySQL的SQL优化器在多索引时行为比较复杂),这里我们将辅助索引drop掉:
165+
从结果中可以到titles表的主索引为\<emp_no, title, from_date\>,还有一个辅助索引\<emp_no\>。为了避免多个索引使事情变复杂(MySQL的SQL优化器在多索引时行为比较复杂),这里我们将辅助索引drop掉:
167166

168167
ALTER TABLE employees.titles DROP INDEX emp_no;
169168

170169
这样就可以专心分析索引PRIMARY的行为了。
171170

172171
### 情况一:全列匹配。
173172

174-
175173
```SQL
176174
EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10001' AND title='Senior Engineer' AND from_date='1986-06-26';
177175
+----+-------------+--------+-------+---------------+---------+---------+-------------------+------+-------+
@@ -194,7 +192,7 @@ EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10001';
194192
+----+-------------+--------+------+---------------+---------+---------+-------+------+-------+
195193
```
196194

197-
当查询条件精确匹配索引的左边连续一个或几个列时,如<emp_no>或<emp_no, title>,所以可以被用到,但是只能用到一部分,即条件所组成的最左前缀。上面的查询从分析结果看用到了PRIMARY索引,但是key_len为4,说明只用到了索引的第一列前缀。
195+
当查询条件精确匹配索引的左边连续一个或几个列时,如\<emp_no\>\<emp_no, title\>,索引可以被用到,但是只能用到一部分,即条件所组成的最左前缀。上面的查询从分析结果看用到了PRIMARY索引,但是key_len为4,说明只用到了索引的第一列前缀。
198196

199197
如果查询条件用到了索引中列的精确匹配,但是中间某个条件未提供。如下:
200198

@@ -207,7 +205,7 @@ EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10001' AND from_date='1986-
207205
+----+-------------+--------+------+---------------+---------+---------+-------+------+-------------+
208206
```
209207

210-
因为title未提供,所以查询只用到了索引的第一列,而后面的from_date虽然也在索引中,但是由于title不存在而无法和左前缀连接,因此需要对结果进行扫描过滤from_date(这里由于emp_no唯一,所以不存在扫描)。如果想让from_date也使用索引而不是where过滤,可以增加一个辅助索引<emp_no, from_date>,此时上面的查询会使用这个索引。
208+
因为title未提供,所以查询只用到了索引的第一列,而后面的from_date虽然也在索引中,但是由于title不存在而无法和左前缀连接,因此需要对结果进行扫描过滤from_date(这里由于emp_no唯一,所以不存在扫描)。如果想让from_date也使用索引而不是where过滤,可以增加一个辅助索引\<emp_no, from_date\>,此时上面的查询会使用这个索引。
211209

212210
### 情况三:查询条件没有指定索引第一列。
213211

@@ -220,7 +218,7 @@ EXPLAIN SELECT * FROM employees.titles WHERE from_date='1986-06-26';
220218
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
221219
```
222220

223-
由于不是最左前缀,索引这样的查询显然用不到索引
221+
由于不是最左前缀,这样的查询显然用不到索引
224222

225223
### 情况四:范围查询。
226224

@@ -239,7 +237,6 @@ EXPLAIN SELECT * FROM employees.titles WHERE emp_no < '10010' and title='Senior
239237

240238
如果查询条件中含有函数或表达式,则MySQL不会为这列使用索引(虽然某些在数学意义上可以使用)。例如:
241239

242-
243240
```SQL
244241
EXPLAIN SELECT * FROM employees.titles WHERE emp_no='10001' AND left(title, 6)='Senior';
245242
+----+-------------+--------+------+---------------+---------+---------+-------+------+-------------+
@@ -328,7 +325,7 @@ SELECT count(DISTINCT(concat(first_name, left(last_name, 4))))/count(*) AS Selec
328325
+-------------+
329326
```
330327

331-
这时选择性已经很理想了,而这个索引的长度只有18,比<first_name, last_name>短了接近一半,我们把这个前缀索引 建上:
328+
这时选择性已经很理想了,而这个索引的长度只有18,比\<first_name, last_name\>短了接近一半,我们把这个前缀索引 建上:
332329

333330
```SQL
334331
ALTER TABLE employees.employees

0 commit comments

Comments
 (0)