@yydb/light-db 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/LightDB.d.ts +194 -0
- package/dist/api/LightDB.d.ts.map +1 -0
- package/dist/api/LightDB.js +299 -0
- package/dist/api/LightDB.js.map +1 -0
- package/dist/api/Transaction.d.ts +100 -0
- package/dist/api/Transaction.d.ts.map +1 -0
- package/dist/api/Transaction.js +263 -0
- package/dist/api/Transaction.js.map +1 -0
- package/dist/api/index.d.ts +24 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +54 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/types.d.ts +154 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +7 -0
- package/dist/api/types.js.map +1 -0
- package/dist/collection/Collection.d.ts +235 -0
- package/dist/collection/Collection.d.ts.map +1 -0
- package/dist/collection/Collection.js +671 -0
- package/dist/collection/Collection.js.map +1 -0
- package/dist/collection/QueryBuilder.d.ts +225 -0
- package/dist/collection/QueryBuilder.d.ts.map +1 -0
- package/dist/collection/QueryBuilder.js +475 -0
- package/dist/collection/QueryBuilder.js.map +1 -0
- package/dist/collection/QueryParser.d.ts +117 -0
- package/dist/collection/QueryParser.d.ts.map +1 -0
- package/dist/collection/QueryParser.js +438 -0
- package/dist/collection/QueryParser.js.map +1 -0
- package/dist/collection/index.d.ts +42 -0
- package/dist/collection/index.d.ts.map +1 -0
- package/dist/collection/index.js +41 -0
- package/dist/collection/index.js.map +1 -0
- package/dist/collection/types.d.ts +365 -0
- package/dist/collection/types.d.ts.map +1 -0
- package/dist/collection/types.js +7 -0
- package/dist/collection/types.js.map +1 -0
- package/dist/constants/index.d.ts +51 -0
- package/dist/constants/index.d.ts.map +1 -0
- package/dist/constants/index.js +68 -0
- package/dist/constants/index.js.map +1 -0
- package/dist/errors/index.d.ts +69 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +132 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +220 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +729 -0
- package/dist/index.js.map +1 -0
- package/dist/indexes/BPlusTree.d.ts +181 -0
- package/dist/indexes/BPlusTree.d.ts.map +1 -0
- package/dist/indexes/BPlusTree.js +528 -0
- package/dist/indexes/BPlusTree.js.map +1 -0
- package/dist/indexes/IndexManager.d.ts +236 -0
- package/dist/indexes/IndexManager.d.ts.map +1 -0
- package/dist/indexes/IndexManager.js +502 -0
- package/dist/indexes/IndexManager.js.map +1 -0
- package/dist/indexes/PrimaryIndex.d.ts +240 -0
- package/dist/indexes/PrimaryIndex.d.ts.map +1 -0
- package/dist/indexes/PrimaryIndex.js +354 -0
- package/dist/indexes/PrimaryIndex.js.map +1 -0
- package/dist/indexes/SecondaryIndex.d.ts +204 -0
- package/dist/indexes/SecondaryIndex.d.ts.map +1 -0
- package/dist/indexes/SecondaryIndex.js +480 -0
- package/dist/indexes/SecondaryIndex.js.map +1 -0
- package/dist/indexes/errors.d.ts +66 -0
- package/dist/indexes/errors.d.ts.map +1 -0
- package/dist/indexes/errors.js +117 -0
- package/dist/indexes/errors.js.map +1 -0
- package/dist/indexes/index.d.ts +52 -0
- package/dist/indexes/index.d.ts.map +1 -0
- package/dist/indexes/index.js +131 -0
- package/dist/indexes/index.js.map +1 -0
- package/dist/indexes/types.d.ts +246 -0
- package/dist/indexes/types.d.ts.map +1 -0
- package/dist/indexes/types.js +30 -0
- package/dist/indexes/types.js.map +1 -0
- package/dist/performance/BatchWALWriter.d.ts +185 -0
- package/dist/performance/BatchWALWriter.d.ts.map +1 -0
- package/dist/performance/BatchWALWriter.js +490 -0
- package/dist/performance/BatchWALWriter.js.map +1 -0
- package/dist/performance/ColumnarStorage.d.ts +138 -0
- package/dist/performance/ColumnarStorage.d.ts.map +1 -0
- package/dist/performance/ColumnarStorage.js +875 -0
- package/dist/performance/ColumnarStorage.js.map +1 -0
- package/dist/performance/LazyQuery.d.ts +307 -0
- package/dist/performance/LazyQuery.d.ts.map +1 -0
- package/dist/performance/LazyQuery.js +588 -0
- package/dist/performance/LazyQuery.js.map +1 -0
- package/dist/performance/OptimizedBuffer.d.ts +375 -0
- package/dist/performance/OptimizedBuffer.d.ts.map +1 -0
- package/dist/performance/OptimizedBuffer.js +730 -0
- package/dist/performance/OptimizedBuffer.js.map +1 -0
- package/dist/performance/RWLock.d.ts +260 -0
- package/dist/performance/RWLock.d.ts.map +1 -0
- package/dist/performance/RWLock.js +570 -0
- package/dist/performance/RWLock.js.map +1 -0
- package/dist/performance/index.d.ts +41 -0
- package/dist/performance/index.d.ts.map +1 -0
- package/dist/performance/index.js +162 -0
- package/dist/performance/index.js.map +1 -0
- package/dist/performance/types.d.ts +247 -0
- package/dist/performance/types.d.ts.map +1 -0
- package/dist/performance/types.js +26 -0
- package/dist/performance/types.js.map +1 -0
- package/dist/storage/Checkpoint.d.ts +128 -0
- package/dist/storage/Checkpoint.d.ts.map +1 -0
- package/dist/storage/Checkpoint.js +251 -0
- package/dist/storage/Checkpoint.js.map +1 -0
- package/dist/storage/LightFile.d.ts +227 -0
- package/dist/storage/LightFile.d.ts.map +1 -0
- package/dist/storage/LightFile.js +526 -0
- package/dist/storage/LightFile.js.map +1 -0
- package/dist/storage/Recovery.d.ts +172 -0
- package/dist/storage/Recovery.d.ts.map +1 -0
- package/dist/storage/Recovery.js +399 -0
- package/dist/storage/Recovery.js.map +1 -0
- package/dist/storage/SHMFile.d.ts +243 -0
- package/dist/storage/SHMFile.d.ts.map +1 -0
- package/dist/storage/SHMFile.js +436 -0
- package/dist/storage/SHMFile.js.map +1 -0
- package/dist/storage/StorageEngine.d.ts +146 -0
- package/dist/storage/StorageEngine.d.ts.map +1 -0
- package/dist/storage/StorageEngine.js +353 -0
- package/dist/storage/StorageEngine.js.map +1 -0
- package/dist/storage/WALFile.d.ts +248 -0
- package/dist/storage/WALFile.d.ts.map +1 -0
- package/dist/storage/WALFile.js +597 -0
- package/dist/storage/WALFile.js.map +1 -0
- package/dist/storage/index.d.ts +10 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +153 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/types/index.d.ts +220 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +7 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/binary.d.ts +271 -0
- package/dist/utils/binary.d.ts.map +1 -0
- package/dist/utils/binary.js +454 -0
- package/dist/utils/binary.js.map +1 -0
- package/dist/utils/file.d.ts +166 -0
- package/dist/utils/file.d.ts.map +1 -0
- package/dist/utils/file.js +346 -0
- package/dist/utils/file.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +39 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +37 -0
- package/readme.md +124 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LightDB B+ 树实现
|
|
3
|
+
* 用于主键索引,支持 O(log n) 的插入、查找、删除和范围查询
|
|
4
|
+
*/
|
|
5
|
+
import type { Comparator, IndexKey } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* B+ 树实现
|
|
8
|
+
* 提供高效的键值存储和范围查询能力
|
|
9
|
+
*/
|
|
10
|
+
export declare class BPlusTree<K extends IndexKey, V> {
|
|
11
|
+
private root;
|
|
12
|
+
private readonly order;
|
|
13
|
+
private readonly comparator;
|
|
14
|
+
private size;
|
|
15
|
+
private firstLeaf;
|
|
16
|
+
private lastLeaf;
|
|
17
|
+
/**
|
|
18
|
+
* 创建 B+ 树实例
|
|
19
|
+
* @param order B+ 树阶数,默认 64
|
|
20
|
+
* @param comparator 键比较器
|
|
21
|
+
*/
|
|
22
|
+
constructor(order?: number, comparator?: Comparator<K>);
|
|
23
|
+
/**
|
|
24
|
+
* 获取树中键值对数量
|
|
25
|
+
*/
|
|
26
|
+
get Size(): number;
|
|
27
|
+
/**
|
|
28
|
+
* 检查树是否为空
|
|
29
|
+
*/
|
|
30
|
+
isEmpty(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* 插入键值对
|
|
33
|
+
* @param key 键
|
|
34
|
+
* @param value 值
|
|
35
|
+
* @returns 如果键已存在,返回旧值;否则返回 undefined
|
|
36
|
+
*/
|
|
37
|
+
insert(key: K, value: V): V | undefined;
|
|
38
|
+
/**
|
|
39
|
+
* 查找键对应的值
|
|
40
|
+
* @param key 键
|
|
41
|
+
* @returns 值,如果不存在返回 undefined
|
|
42
|
+
*/
|
|
43
|
+
find(key: K): V | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* 检查键是否存在
|
|
46
|
+
* @param key 键
|
|
47
|
+
*/
|
|
48
|
+
has(key: K): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* 删除键值对
|
|
51
|
+
* @param key 键
|
|
52
|
+
* @returns 被删除的值,如果不存在返回 undefined
|
|
53
|
+
*/
|
|
54
|
+
delete(key: K): V | undefined;
|
|
55
|
+
/**
|
|
56
|
+
* 更新键对应的值
|
|
57
|
+
* @param key 键
|
|
58
|
+
* @param value 新值
|
|
59
|
+
* @returns 是否更新成功
|
|
60
|
+
*/
|
|
61
|
+
update(key: K, value: V): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* 范围查询
|
|
64
|
+
* @param start 起始键(包含)
|
|
65
|
+
* @param end 结束键(包含)
|
|
66
|
+
* @param includeStart 是否包含起始键
|
|
67
|
+
* @param includeEnd 是否包含结束键
|
|
68
|
+
* @returns 键值对数组
|
|
69
|
+
*/
|
|
70
|
+
range(
|
|
71
|
+
start?: K,
|
|
72
|
+
end?: K,
|
|
73
|
+
includeStart?: boolean,
|
|
74
|
+
includeEnd?: boolean,
|
|
75
|
+
): Array<{
|
|
76
|
+
key: K;
|
|
77
|
+
value: V;
|
|
78
|
+
}>;
|
|
79
|
+
/**
|
|
80
|
+
* 获取所有键(有序)
|
|
81
|
+
*/
|
|
82
|
+
keys(): K[];
|
|
83
|
+
/**
|
|
84
|
+
* 获取所有值(按键顺序)
|
|
85
|
+
*/
|
|
86
|
+
values(): V[];
|
|
87
|
+
/**
|
|
88
|
+
* 获取所有键值对(有序)
|
|
89
|
+
*/
|
|
90
|
+
entries(): Array<{
|
|
91
|
+
key: K;
|
|
92
|
+
value: V;
|
|
93
|
+
}>;
|
|
94
|
+
/**
|
|
95
|
+
* 清空树
|
|
96
|
+
*/
|
|
97
|
+
clear(): void;
|
|
98
|
+
/**
|
|
99
|
+
* 获取最小键
|
|
100
|
+
*/
|
|
101
|
+
minKey(): K | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* 获取最大键
|
|
104
|
+
*/
|
|
105
|
+
maxKey(): K | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* 获取第一个键值对
|
|
108
|
+
*/
|
|
109
|
+
first():
|
|
110
|
+
| {
|
|
111
|
+
key: K;
|
|
112
|
+
value: V;
|
|
113
|
+
}
|
|
114
|
+
| undefined;
|
|
115
|
+
/**
|
|
116
|
+
* 获取最后一个键值对
|
|
117
|
+
*/
|
|
118
|
+
last():
|
|
119
|
+
| {
|
|
120
|
+
key: K;
|
|
121
|
+
value: V;
|
|
122
|
+
}
|
|
123
|
+
| undefined;
|
|
124
|
+
/**
|
|
125
|
+
* 遍历树
|
|
126
|
+
* @param callback 回调函数
|
|
127
|
+
*/
|
|
128
|
+
forEach(callback: (key: K, value: V) => void): void;
|
|
129
|
+
/**
|
|
130
|
+
* 创建迭代器
|
|
131
|
+
*/
|
|
132
|
+
[Symbol.iterator](): Generator<{
|
|
133
|
+
key: K;
|
|
134
|
+
value: V;
|
|
135
|
+
}>;
|
|
136
|
+
/**
|
|
137
|
+
* 查找键所在的叶子节点
|
|
138
|
+
*/
|
|
139
|
+
private findLeafNode;
|
|
140
|
+
/**
|
|
141
|
+
* 在叶子节点中插入键值对
|
|
142
|
+
*/
|
|
143
|
+
private insertIntoLeaf;
|
|
144
|
+
/**
|
|
145
|
+
* 分裂叶子节点
|
|
146
|
+
*/
|
|
147
|
+
private splitLeaf;
|
|
148
|
+
/**
|
|
149
|
+
* 分裂内部节点
|
|
150
|
+
*/
|
|
151
|
+
private splitInternal;
|
|
152
|
+
/**
|
|
153
|
+
* 查找或创建父节点
|
|
154
|
+
*/
|
|
155
|
+
private findOrCreateParent;
|
|
156
|
+
/**
|
|
157
|
+
* 查找父节点
|
|
158
|
+
*/
|
|
159
|
+
private findParent;
|
|
160
|
+
/**
|
|
161
|
+
* 移除空叶子节点
|
|
162
|
+
*/
|
|
163
|
+
private removeLeafNode;
|
|
164
|
+
/**
|
|
165
|
+
* 二分查找
|
|
166
|
+
*/
|
|
167
|
+
private binarySearch;
|
|
168
|
+
/**
|
|
169
|
+
* 查找键在数组中的索引
|
|
170
|
+
*/
|
|
171
|
+
private findKeyIndex;
|
|
172
|
+
/**
|
|
173
|
+
* 查找第一个大于等于目标键的索引
|
|
174
|
+
*/
|
|
175
|
+
private findFirstGreaterOrEqual;
|
|
176
|
+
/**
|
|
177
|
+
* 更新已存在键的值
|
|
178
|
+
*/
|
|
179
|
+
private updateValue;
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=BPlusTree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BPlusTree.d.ts","sourceRoot":"","sources":["../../src/indexes/BPlusTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* LightDB B+ 树实现
|
|
4
|
+
* 用于主键索引,支持 O(log n) 的插入、查找、删除和范围查询
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.BPlusTree = void 0;
|
|
8
|
+
const errors_1 = require("./errors");
|
|
9
|
+
/**
|
|
10
|
+
* 默认 B+ 树阶数(每个节点最多存储的键数量)
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_ORDER = 64;
|
|
13
|
+
/**
|
|
14
|
+
* B+ 树叶子节点
|
|
15
|
+
*/
|
|
16
|
+
class BPlusTreeLeafNode {
|
|
17
|
+
constructor() {
|
|
18
|
+
this.keys = [];
|
|
19
|
+
this.values = [];
|
|
20
|
+
this.next = null;
|
|
21
|
+
this.prev = null;
|
|
22
|
+
}
|
|
23
|
+
isLeaf() {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* B+ 树内部节点
|
|
29
|
+
*/
|
|
30
|
+
class BPlusTreeInternalNode {
|
|
31
|
+
constructor() {
|
|
32
|
+
this.keys = [];
|
|
33
|
+
this.children = [];
|
|
34
|
+
}
|
|
35
|
+
isLeaf() {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 默认比较器
|
|
41
|
+
* 支持字符串和数值类型的比较
|
|
42
|
+
*/
|
|
43
|
+
function defaultComparator(a, b) {
|
|
44
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
45
|
+
return a - b;
|
|
46
|
+
}
|
|
47
|
+
const strA = String(a);
|
|
48
|
+
const strB = String(b);
|
|
49
|
+
if (strA < strB) return -1;
|
|
50
|
+
if (strA > strB) return 1;
|
|
51
|
+
return 0;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* B+ 树实现
|
|
55
|
+
* 提供高效的键值存储和范围查询能力
|
|
56
|
+
*/
|
|
57
|
+
class BPlusTree {
|
|
58
|
+
/**
|
|
59
|
+
* 创建 B+ 树实例
|
|
60
|
+
* @param order B+ 树阶数,默认 64
|
|
61
|
+
* @param comparator 键比较器
|
|
62
|
+
*/
|
|
63
|
+
constructor(order = DEFAULT_ORDER, comparator) {
|
|
64
|
+
this.size = 0;
|
|
65
|
+
this.firstLeaf = null;
|
|
66
|
+
this.lastLeaf = null;
|
|
67
|
+
if (order < 3) {
|
|
68
|
+
throw new errors_1.IndexOperationError("B+ tree order must be at least 3", "constructor");
|
|
69
|
+
}
|
|
70
|
+
this.order = order;
|
|
71
|
+
this.comparator = comparator ?? defaultComparator;
|
|
72
|
+
this.root = new BPlusTreeLeafNode();
|
|
73
|
+
this.firstLeaf = this.root;
|
|
74
|
+
this.lastLeaf = this.root;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* 获取树中键值对数量
|
|
78
|
+
*/
|
|
79
|
+
get Size() {
|
|
80
|
+
return this.size;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* 检查树是否为空
|
|
84
|
+
*/
|
|
85
|
+
isEmpty() {
|
|
86
|
+
return this.size === 0;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 插入键值对
|
|
90
|
+
* @param key 键
|
|
91
|
+
* @param value 值
|
|
92
|
+
* @returns 如果键已存在,返回旧值;否则返回 undefined
|
|
93
|
+
*/
|
|
94
|
+
insert(key, value) {
|
|
95
|
+
const existingValue = this.find(key);
|
|
96
|
+
if (existingValue !== undefined) {
|
|
97
|
+
this.updateValue(key, value);
|
|
98
|
+
return existingValue;
|
|
99
|
+
}
|
|
100
|
+
const leaf = this.findLeafNode(key);
|
|
101
|
+
this.insertIntoLeaf(leaf, key, value);
|
|
102
|
+
this.size++;
|
|
103
|
+
if (leaf.keys.length > this.order) {
|
|
104
|
+
this.splitLeaf(leaf);
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* 查找键对应的值
|
|
110
|
+
* @param key 键
|
|
111
|
+
* @returns 值,如果不存在返回 undefined
|
|
112
|
+
*/
|
|
113
|
+
find(key) {
|
|
114
|
+
const leaf = this.findLeafNode(key);
|
|
115
|
+
const index = this.binarySearch(leaf.keys, key);
|
|
116
|
+
if (index >= 0 && index < leaf.keys.length) {
|
|
117
|
+
const cmp = this.comparator(leaf.keys[index], key);
|
|
118
|
+
if (cmp === 0) {
|
|
119
|
+
return leaf.values[index];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
for (let i = 0; i < leaf.keys.length; i++) {
|
|
123
|
+
if (this.comparator(leaf.keys[i], key) === 0) {
|
|
124
|
+
return leaf.values[i];
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* 检查键是否存在
|
|
131
|
+
* @param key 键
|
|
132
|
+
*/
|
|
133
|
+
has(key) {
|
|
134
|
+
return this.find(key) !== undefined;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* 删除键值对
|
|
138
|
+
* @param key 键
|
|
139
|
+
* @returns 被删除的值,如果不存在返回 undefined
|
|
140
|
+
*/
|
|
141
|
+
delete(key) {
|
|
142
|
+
const leaf = this.findLeafNode(key);
|
|
143
|
+
const index = this.findKeyIndex(leaf.keys, key);
|
|
144
|
+
if (index === -1) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
const value = leaf.values[index];
|
|
148
|
+
leaf.keys.splice(index, 1);
|
|
149
|
+
leaf.values.splice(index, 1);
|
|
150
|
+
this.size--;
|
|
151
|
+
if (leaf.keys.length === 0 && leaf !== this.root) {
|
|
152
|
+
this.removeLeafNode(leaf);
|
|
153
|
+
}
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* 更新键对应的值
|
|
158
|
+
* @param key 键
|
|
159
|
+
* @param value 新值
|
|
160
|
+
* @returns 是否更新成功
|
|
161
|
+
*/
|
|
162
|
+
update(key, value) {
|
|
163
|
+
const leaf = this.findLeafNode(key);
|
|
164
|
+
const index = this.findKeyIndex(leaf.keys, key);
|
|
165
|
+
if (index === -1) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
leaf.values[index] = value;
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* 范围查询
|
|
173
|
+
* @param start 起始键(包含)
|
|
174
|
+
* @param end 结束键(包含)
|
|
175
|
+
* @param includeStart 是否包含起始键
|
|
176
|
+
* @param includeEnd 是否包含结束键
|
|
177
|
+
* @returns 键值对数组
|
|
178
|
+
*/
|
|
179
|
+
range(start, end, includeStart = true, includeEnd = true) {
|
|
180
|
+
const result = [];
|
|
181
|
+
if (this.size === 0) {
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
let startLeaf;
|
|
185
|
+
let startIndex;
|
|
186
|
+
if (start !== undefined) {
|
|
187
|
+
startLeaf = this.findLeafNode(start);
|
|
188
|
+
startIndex = this.findFirstGreaterOrEqual(startLeaf.keys, start);
|
|
189
|
+
} else {
|
|
190
|
+
startLeaf = this.firstLeaf;
|
|
191
|
+
startIndex = 0;
|
|
192
|
+
}
|
|
193
|
+
let currentLeaf = startLeaf;
|
|
194
|
+
let currentIndex = startIndex;
|
|
195
|
+
while (currentLeaf !== null) {
|
|
196
|
+
for (let i = currentIndex; i < currentLeaf.keys.length; i++) {
|
|
197
|
+
const key = currentLeaf.keys[i];
|
|
198
|
+
if (start !== undefined) {
|
|
199
|
+
const cmp = this.comparator(key, start);
|
|
200
|
+
if (cmp < 0 || (cmp === 0 && !includeStart)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
if (end !== undefined) {
|
|
205
|
+
const cmp = this.comparator(key, end);
|
|
206
|
+
if (cmp > 0 || (cmp === 0 && !includeEnd)) {
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
result.push({ key, value: currentLeaf.values[i] });
|
|
211
|
+
}
|
|
212
|
+
currentLeaf = currentLeaf.next;
|
|
213
|
+
currentIndex = 0;
|
|
214
|
+
}
|
|
215
|
+
return result;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* 获取所有键(有序)
|
|
219
|
+
*/
|
|
220
|
+
keys() {
|
|
221
|
+
const result = [];
|
|
222
|
+
let current = this.firstLeaf;
|
|
223
|
+
while (current !== null) {
|
|
224
|
+
result.push(...current.keys);
|
|
225
|
+
current = current.next;
|
|
226
|
+
}
|
|
227
|
+
return result;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* 获取所有值(按键顺序)
|
|
231
|
+
*/
|
|
232
|
+
values() {
|
|
233
|
+
const result = [];
|
|
234
|
+
let current = this.firstLeaf;
|
|
235
|
+
while (current !== null) {
|
|
236
|
+
result.push(...current.values);
|
|
237
|
+
current = current.next;
|
|
238
|
+
}
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* 获取所有键值对(有序)
|
|
243
|
+
*/
|
|
244
|
+
entries() {
|
|
245
|
+
const result = [];
|
|
246
|
+
let current = this.firstLeaf;
|
|
247
|
+
while (current !== null) {
|
|
248
|
+
for (let i = 0; i < current.keys.length; i++) {
|
|
249
|
+
result.push({ key: current.keys[i], value: current.values[i] });
|
|
250
|
+
}
|
|
251
|
+
current = current.next;
|
|
252
|
+
}
|
|
253
|
+
return result;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* 清空树
|
|
257
|
+
*/
|
|
258
|
+
clear() {
|
|
259
|
+
this.root = new BPlusTreeLeafNode();
|
|
260
|
+
this.firstLeaf = this.root;
|
|
261
|
+
this.lastLeaf = this.root;
|
|
262
|
+
this.size = 0;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* 获取最小键
|
|
266
|
+
*/
|
|
267
|
+
minKey() {
|
|
268
|
+
if (this.size === 0) {
|
|
269
|
+
return undefined;
|
|
270
|
+
}
|
|
271
|
+
return this.firstLeaf.keys[0];
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* 获取最大键
|
|
275
|
+
*/
|
|
276
|
+
maxKey() {
|
|
277
|
+
if (this.size === 0) {
|
|
278
|
+
return undefined;
|
|
279
|
+
}
|
|
280
|
+
return this.lastLeaf.keys[this.lastLeaf.keys.length - 1];
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* 获取第一个键值对
|
|
284
|
+
*/
|
|
285
|
+
first() {
|
|
286
|
+
if (this.size === 0) {
|
|
287
|
+
return undefined;
|
|
288
|
+
}
|
|
289
|
+
return {
|
|
290
|
+
key: this.firstLeaf.keys[0],
|
|
291
|
+
value: this.firstLeaf.values[0],
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* 获取最后一个键值对
|
|
296
|
+
*/
|
|
297
|
+
last() {
|
|
298
|
+
if (this.size === 0) {
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
301
|
+
const lastIndex = this.lastLeaf.keys.length - 1;
|
|
302
|
+
return {
|
|
303
|
+
key: this.lastLeaf.keys[lastIndex],
|
|
304
|
+
value: this.lastLeaf.values[lastIndex],
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* 遍历树
|
|
309
|
+
* @param callback 回调函数
|
|
310
|
+
*/
|
|
311
|
+
forEach(callback) {
|
|
312
|
+
let current = this.firstLeaf;
|
|
313
|
+
while (current !== null) {
|
|
314
|
+
for (let i = 0; i < current.keys.length; i++) {
|
|
315
|
+
callback(current.keys[i], current.values[i]);
|
|
316
|
+
}
|
|
317
|
+
current = current.next;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* 创建迭代器
|
|
322
|
+
*/
|
|
323
|
+
*[Symbol.iterator]() {
|
|
324
|
+
let current = this.firstLeaf;
|
|
325
|
+
while (current !== null) {
|
|
326
|
+
for (let i = 0; i < current.keys.length; i++) {
|
|
327
|
+
yield { key: current.keys[i], value: current.values[i] };
|
|
328
|
+
}
|
|
329
|
+
current = current.next;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* 查找键所在的叶子节点
|
|
334
|
+
*/
|
|
335
|
+
findLeafNode(key) {
|
|
336
|
+
let node = this.root;
|
|
337
|
+
while (!node.isLeaf()) {
|
|
338
|
+
const internalNode = node;
|
|
339
|
+
let i = 0;
|
|
340
|
+
while (i < internalNode.keys.length && this.comparator(key, internalNode.keys[i]) >= 0) {
|
|
341
|
+
i++;
|
|
342
|
+
}
|
|
343
|
+
node = internalNode.children[i];
|
|
344
|
+
}
|
|
345
|
+
return node;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* 在叶子节点中插入键值对
|
|
349
|
+
*/
|
|
350
|
+
insertIntoLeaf(leaf, key, value) {
|
|
351
|
+
let i = 0;
|
|
352
|
+
while (i < leaf.keys.length && this.comparator(key, leaf.keys[i]) > 0) {
|
|
353
|
+
i++;
|
|
354
|
+
}
|
|
355
|
+
leaf.keys.splice(i, 0, key);
|
|
356
|
+
leaf.values.splice(i, 0, value);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* 分裂叶子节点
|
|
360
|
+
*/
|
|
361
|
+
splitLeaf(leaf) {
|
|
362
|
+
const mid = Math.floor(leaf.keys.length / 2);
|
|
363
|
+
const newLeaf = new BPlusTreeLeafNode();
|
|
364
|
+
newLeaf.keys = leaf.keys.splice(mid);
|
|
365
|
+
newLeaf.values = leaf.values.splice(mid);
|
|
366
|
+
newLeaf.next = leaf.next;
|
|
367
|
+
newLeaf.prev = leaf;
|
|
368
|
+
if (leaf.next) {
|
|
369
|
+
leaf.next.prev = newLeaf;
|
|
370
|
+
}
|
|
371
|
+
leaf.next = newLeaf;
|
|
372
|
+
if (leaf === this.lastLeaf) {
|
|
373
|
+
this.lastLeaf = newLeaf;
|
|
374
|
+
}
|
|
375
|
+
const parent = this.findOrCreateParent(leaf);
|
|
376
|
+
const insertIndex = parent.children.indexOf(leaf) + 1;
|
|
377
|
+
const promoteKey = newLeaf.keys[0];
|
|
378
|
+
parent.keys.splice(insertIndex - 1, 0, promoteKey);
|
|
379
|
+
parent.children.splice(insertIndex, 0, newLeaf);
|
|
380
|
+
if (parent.keys.length >= this.order) {
|
|
381
|
+
this.splitInternal(parent);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* 分裂内部节点
|
|
386
|
+
*/
|
|
387
|
+
splitInternal(node) {
|
|
388
|
+
const mid = Math.floor(node.keys.length / 2);
|
|
389
|
+
const newNode = new BPlusTreeInternalNode();
|
|
390
|
+
const promoteKey = node.keys[mid];
|
|
391
|
+
newNode.keys = node.keys.splice(mid + 1);
|
|
392
|
+
node.keys.pop();
|
|
393
|
+
newNode.children = node.children.splice(mid + 1);
|
|
394
|
+
if (node === this.root) {
|
|
395
|
+
const newRoot = new BPlusTreeInternalNode();
|
|
396
|
+
newRoot.keys.push(promoteKey);
|
|
397
|
+
newRoot.children.push(node, newNode);
|
|
398
|
+
this.root = newRoot;
|
|
399
|
+
} else {
|
|
400
|
+
const parent = this.findOrCreateParent(node);
|
|
401
|
+
const insertIndex = parent.children.indexOf(node) + 1;
|
|
402
|
+
parent.keys.splice(insertIndex - 1, 0, promoteKey);
|
|
403
|
+
parent.children.splice(insertIndex, 0, newNode);
|
|
404
|
+
if (parent.keys.length >= this.order) {
|
|
405
|
+
this.splitInternal(parent);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* 查找或创建父节点
|
|
411
|
+
*/
|
|
412
|
+
findOrCreateParent(node) {
|
|
413
|
+
if (node === this.root) {
|
|
414
|
+
const newRoot = new BPlusTreeInternalNode();
|
|
415
|
+
newRoot.children.push(this.root);
|
|
416
|
+
this.root = newRoot;
|
|
417
|
+
return newRoot;
|
|
418
|
+
}
|
|
419
|
+
return this.findParent(this.root, node);
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* 查找父节点
|
|
423
|
+
*/
|
|
424
|
+
findParent(current, target) {
|
|
425
|
+
if (current.isLeaf()) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
const internalNode = current;
|
|
429
|
+
for (const child of internalNode.children) {
|
|
430
|
+
if (child === target) {
|
|
431
|
+
return internalNode;
|
|
432
|
+
}
|
|
433
|
+
if (!child.isLeaf()) {
|
|
434
|
+
const found = this.findParent(child, target);
|
|
435
|
+
if (found) {
|
|
436
|
+
return found;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* 移除空叶子节点
|
|
444
|
+
*/
|
|
445
|
+
removeLeafNode(leaf) {
|
|
446
|
+
if (leaf.prev) {
|
|
447
|
+
leaf.prev.next = leaf.next;
|
|
448
|
+
} else {
|
|
449
|
+
this.firstLeaf = leaf.next;
|
|
450
|
+
}
|
|
451
|
+
if (leaf.next) {
|
|
452
|
+
leaf.next.prev = leaf.prev;
|
|
453
|
+
} else {
|
|
454
|
+
this.lastLeaf = leaf.prev;
|
|
455
|
+
}
|
|
456
|
+
if (leaf === this.root) {
|
|
457
|
+
this.root = new BPlusTreeLeafNode();
|
|
458
|
+
this.firstLeaf = this.root;
|
|
459
|
+
this.lastLeaf = this.root;
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
462
|
+
const parent = this.findParent(this.root, leaf);
|
|
463
|
+
if (parent) {
|
|
464
|
+
const index = parent.children.indexOf(leaf);
|
|
465
|
+
if (index !== -1) {
|
|
466
|
+
parent.children.splice(index, 1);
|
|
467
|
+
if (index > 0) {
|
|
468
|
+
parent.keys.splice(index - 1, 1);
|
|
469
|
+
} else if (parent.keys.length > 0) {
|
|
470
|
+
parent.keys.splice(0, 1);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* 二分查找
|
|
477
|
+
*/
|
|
478
|
+
binarySearch(keys, key) {
|
|
479
|
+
let left = 0;
|
|
480
|
+
let right = keys.length - 1;
|
|
481
|
+
while (left <= right) {
|
|
482
|
+
const mid = Math.floor((left + right) / 2);
|
|
483
|
+
const cmp = this.comparator(keys[mid], key);
|
|
484
|
+
if (cmp === 0) {
|
|
485
|
+
return mid;
|
|
486
|
+
} else if (cmp < 0) {
|
|
487
|
+
left = mid + 1;
|
|
488
|
+
} else {
|
|
489
|
+
right = mid - 1;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
return left;
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* 查找键在数组中的索引
|
|
496
|
+
*/
|
|
497
|
+
findKeyIndex(keys, key) {
|
|
498
|
+
for (let i = 0; i < keys.length; i++) {
|
|
499
|
+
if (this.comparator(keys[i], key) === 0) {
|
|
500
|
+
return i;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return -1;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* 查找第一个大于等于目标键的索引
|
|
507
|
+
*/
|
|
508
|
+
findFirstGreaterOrEqual(keys, key) {
|
|
509
|
+
for (let i = 0; i < keys.length; i++) {
|
|
510
|
+
if (this.comparator(keys[i], key) >= 0) {
|
|
511
|
+
return i;
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
return keys.length;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* 更新已存在键的值
|
|
518
|
+
*/
|
|
519
|
+
updateValue(key, value) {
|
|
520
|
+
const leaf = this.findLeafNode(key);
|
|
521
|
+
const index = this.findKeyIndex(leaf.keys, key);
|
|
522
|
+
if (index !== -1) {
|
|
523
|
+
leaf.values[index] = value;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
exports.BPlusTree = BPlusTree;
|
|
528
|
+
//# sourceMappingURL=BPlusTree.js.map
|