自己实现基于key-value的NoSQL数据库(三)—— B+树和Hash算法

释放双眼,带上耳机,听听看~!

前一篇文章中,效率成了很关键的问题,比较数据库还是需要能高效查找数据才行

那么如何解决查找问题呢?一个很好的办法是使用B+树,关于B+树就不做多的介绍了,网上有很多

这里只贴出定义


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1B-树
2
3       是一种多路搜索树(并不是二叉的):
4
5       1.定义任意非叶子结点最多只有M个儿子;且M>2;
6
7       2.根结点的儿子数为[2, M];
8
9       3.除根结点以外的非叶子结点的儿子数为[M/2, M];
10
11       4.每个结点存放至少M/2-1(取上整)和至多M-1个关键字;(至少2个关键字)
12
13       5.非叶子结点的关键字个数=指向儿子的指针个数-1;
14
15       6.非叶子结点的关键字:K[1], K[2], …, K[M-1];且K[i] < K[i+1];
16
17       7.非叶子结点的指针:P[1], P[2], …, P[M];其中P[1]指向关键字小于K[1]的
18
19子树,P[M]指向关键字大于K[M-1]的子树,其它P[i]指向关键字属于(K[i-1], K[i])的子树;
20
21       8.所有叶子结点位于同一层;
22
23       如:(M=3)
24

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
1B+树
2
3       B+树是B-树的变体,也是一种多路搜索树:
4
5       1.其定义基本与B-树同,除了:
6
7       2.非叶子结点的子树指针与关键字个数相同;
8
9       3.非叶子结点的子树指针P[i],指向关键字值属于[K[i], K[i+1])的子树
10
11(B-树是开区间);
12
13       5.为所有叶子结点增加一个链指针;
14
15       6.所有关键字都在叶子结点出现;
16

1
2
1 至于实现,给出一个连接可以看看 https://github.com/begeekmyfriend/bplustree
2

然后数据库的键是字符串型的,如果转换出数字呢?答案是用hash算法,网上也有很多经典的实现

这里给出Bizzard公司的经典算法(采用了部分,不是全部)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
1#pragma once
2
3#include <string>
4
5unsigned long cryptTable[0x500];
6
7void prepareCryptTable()
8{
9   unsigned long seed = 0x00100001, index1 = 0, index2 = 0, i;
10
11  for (index1 = 0; index1 < 0x100; index1++)
12  {
13      for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
14      {
15          unsigned long temp1, temp2;
16          seed = (seed * 125 + 3) % 0x2AAAAB;
17          temp1 = (seed & 0xFFFF) << 0x10;
18          seed = (seed * 125 + 3) % 0x2AAAAB;
19          temp2 = (seed & 0xFFFF);
20          cryptTable[index2] = (temp1 | temp2);
21      }
22  }
23}
24
25unsigned long HashString(const std::string& key, unsigned long dwHashType)
26{
27  unsigned char *ckey = (unsigned char *)key.c_str();
28  unsigned long seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
29  int ch;
30  while (*ckey != 0)
31  {
32      ch = toupper(*ckey++);
33      seed1 = cryptTable[(dwHashType << 8) + ch] ^ (seed1 + seed2);
34      seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
35  }
36  return seed1;
37}
38

1
2
1 暴雪的源码中是用了三次hash值来决定一个数据的,数据冲突的几率是
2

1: 18889465931478580854784
几乎不可能出现

而我们这里由于纯粹的学习原理而已,所以采用一次就行了

接下来就是要把这两个算法整合进数据库中,用来代替以前的搜索算法

需要对算法进行一定的修改

在下一张章中实现

给TA打赏
共{{data.count}}人
人已打赏
安全运维

OpenSSH-8.7p1离线升级修复安全漏洞

2021-10-23 10:13:25

安全运维

设计模式的设计原则

2021-12-12 17:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索