Skip to content

Commit 77eb220

Browse files
committed
feat: 补全文档并新增可编辑 CodeRunner 组件
1 parent 2838ab2 commit 77eb220

14 files changed

Lines changed: 3733 additions & 8 deletions

File tree

Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,385 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
4+
enum { T = 2, MAX_KEYS = 2 * T - 1, MAX_CHILDREN = 2 * T };
5+
6+
typedef struct BTreeNode {
7+
int n;
8+
int leaf;
9+
int keys[MAX_KEYS];
10+
struct BTreeNode *child[MAX_CHILDREN];
11+
} BTreeNode;
12+
13+
typedef struct {
14+
BTreeNode *root;
15+
} BTree;
16+
17+
static BTreeNode *bt_new_node(int leaf) {
18+
BTreeNode *x = (BTreeNode *)calloc(1, sizeof(*x));
19+
if (x == NULL) {
20+
return NULL;
21+
}
22+
x->leaf = leaf;
23+
return x;
24+
}
25+
26+
static void bt_destroy_node(BTreeNode *x) {
27+
if (x == NULL) {
28+
return;
29+
}
30+
if (!x->leaf) {
31+
for (int i = 0; i <= x->n; ++i) {
32+
bt_destroy_node(x->child[i]);
33+
}
34+
}
35+
free(x);
36+
}
37+
38+
static void bt_destroy(BTree *t) {
39+
bt_destroy_node(t->root);
40+
t->root = NULL;
41+
}
42+
43+
static const BTreeNode *bt_search(const BTreeNode *x, int k, int *pos) {
44+
int i = 0;
45+
while (i < x->n && k > x->keys[i]) {
46+
++i;
47+
}
48+
if (i < x->n && k == x->keys[i]) {
49+
if (pos != NULL) {
50+
*pos = i;
51+
}
52+
return x;
53+
}
54+
if (x->leaf) {
55+
return NULL;
56+
}
57+
return bt_search(x->child[i], k, pos);
58+
}
59+
60+
static void bt_traverse(const BTreeNode *x) {
61+
if (x == NULL) {
62+
return;
63+
}
64+
for (int i = 0; i < x->n; ++i) {
65+
if (!x->leaf) {
66+
bt_traverse(x->child[i]);
67+
}
68+
printf("%d ", x->keys[i]);
69+
}
70+
if (!x->leaf) {
71+
bt_traverse(x->child[x->n]);
72+
}
73+
}
74+
75+
static void split_child(BTreeNode *x, int i) {
76+
BTreeNode *y = x->child[i];
77+
BTreeNode *z = bt_new_node(y->leaf);
78+
if (z == NULL) {
79+
fprintf(stderr, "out of memory\n");
80+
exit(1);
81+
}
82+
83+
z->n = T - 1;
84+
for (int j = 0; j < T - 1; ++j) {
85+
z->keys[j] = y->keys[j + T];
86+
}
87+
if (!y->leaf) {
88+
for (int j = 0; j < T; ++j) {
89+
z->child[j] = y->child[j + T];
90+
}
91+
}
92+
93+
y->n = T - 1;
94+
95+
for (int j = x->n; j >= i + 1; --j) {
96+
x->child[j + 1] = x->child[j];
97+
}
98+
x->child[i + 1] = z;
99+
100+
for (int j = x->n - 1; j >= i; --j) {
101+
x->keys[j + 1] = x->keys[j];
102+
}
103+
x->keys[i] = y->keys[T - 1];
104+
x->n += 1;
105+
}
106+
107+
static void insert_nonfull(BTreeNode *x, int k) {
108+
int i = x->n - 1;
109+
110+
if (x->leaf) {
111+
while (i >= 0 && k < x->keys[i]) {
112+
x->keys[i + 1] = x->keys[i];
113+
--i;
114+
}
115+
x->keys[i + 1] = k;
116+
x->n += 1;
117+
return;
118+
}
119+
120+
while (i >= 0 && k < x->keys[i]) {
121+
--i;
122+
}
123+
++i;
124+
125+
if (x->child[i]->n == MAX_KEYS) {
126+
split_child(x, i);
127+
if (k > x->keys[i]) {
128+
++i;
129+
}
130+
}
131+
insert_nonfull(x->child[i], k);
132+
}
133+
134+
static void bt_insert(BTree *t, int k) {
135+
if (t->root == NULL) {
136+
t->root = bt_new_node(1);
137+
if (t->root == NULL) {
138+
fprintf(stderr, "out of memory\n");
139+
exit(1);
140+
}
141+
t->root->keys[0] = k;
142+
t->root->n = 1;
143+
return;
144+
}
145+
146+
if (bt_search(t->root, k, NULL) != NULL) {
147+
return;
148+
}
149+
150+
BTreeNode *r = t->root;
151+
if (r->n == MAX_KEYS) {
152+
BTreeNode *s = bt_new_node(0);
153+
if (s == NULL) {
154+
fprintf(stderr, "out of memory\n");
155+
exit(1);
156+
}
157+
t->root = s;
158+
s->child[0] = r;
159+
split_child(s, 0);
160+
161+
int i = 0;
162+
if (k > s->keys[0]) {
163+
i = 1;
164+
}
165+
insert_nonfull(s->child[i], k);
166+
} else {
167+
insert_nonfull(r, k);
168+
}
169+
}
170+
171+
static int find_key(const BTreeNode *x, int k) {
172+
int idx = 0;
173+
while (idx < x->n && x->keys[idx] < k) {
174+
++idx;
175+
}
176+
return idx;
177+
}
178+
179+
static int get_pred(BTreeNode *x, int idx) {
180+
BTreeNode *cur = x->child[idx];
181+
while (!cur->leaf) {
182+
cur = cur->child[cur->n];
183+
}
184+
return cur->keys[cur->n - 1];
185+
}
186+
187+
static int get_succ(BTreeNode *x, int idx) {
188+
BTreeNode *cur = x->child[idx + 1];
189+
while (!cur->leaf) {
190+
cur = cur->child[0];
191+
}
192+
return cur->keys[0];
193+
}
194+
195+
static void remove_from_leaf(BTreeNode *x, int idx) {
196+
for (int i = idx + 1; i < x->n; ++i) {
197+
x->keys[i - 1] = x->keys[i];
198+
}
199+
x->n -= 1;
200+
}
201+
202+
static void merge(BTreeNode *x, int idx) {
203+
BTreeNode *child = x->child[idx];
204+
BTreeNode *sibling = x->child[idx + 1];
205+
206+
child->keys[T - 1] = x->keys[idx];
207+
for (int i = 0; i < sibling->n; ++i) {
208+
child->keys[i + T] = sibling->keys[i];
209+
}
210+
if (!child->leaf) {
211+
for (int i = 0; i <= sibling->n; ++i) {
212+
child->child[i + T] = sibling->child[i];
213+
}
214+
}
215+
child->n += sibling->n + 1;
216+
217+
for (int i = idx + 1; i < x->n; ++i) {
218+
x->keys[i - 1] = x->keys[i];
219+
}
220+
for (int i = idx + 2; i <= x->n; ++i) {
221+
x->child[i - 1] = x->child[i];
222+
}
223+
x->n -= 1;
224+
free(sibling);
225+
}
226+
227+
static void borrow_from_prev(BTreeNode *x, int idx) {
228+
BTreeNode *child = x->child[idx];
229+
BTreeNode *sibling = x->child[idx - 1];
230+
231+
for (int i = child->n - 1; i >= 0; --i) {
232+
child->keys[i + 1] = child->keys[i];
233+
}
234+
if (!child->leaf) {
235+
for (int i = child->n; i >= 0; --i) {
236+
child->child[i + 1] = child->child[i];
237+
}
238+
}
239+
240+
child->keys[0] = x->keys[idx - 1];
241+
if (!child->leaf) {
242+
child->child[0] = sibling->child[sibling->n];
243+
}
244+
245+
x->keys[idx - 1] = sibling->keys[sibling->n - 1];
246+
child->n += 1;
247+
sibling->n -= 1;
248+
}
249+
250+
static void borrow_from_next(BTreeNode *x, int idx) {
251+
BTreeNode *child = x->child[idx];
252+
BTreeNode *sibling = x->child[idx + 1];
253+
254+
child->keys[child->n] = x->keys[idx];
255+
if (!child->leaf) {
256+
child->child[child->n + 1] = sibling->child[0];
257+
}
258+
x->keys[idx] = sibling->keys[0];
259+
260+
for (int i = 1; i < sibling->n; ++i) {
261+
sibling->keys[i - 1] = sibling->keys[i];
262+
}
263+
if (!sibling->leaf) {
264+
for (int i = 1; i <= sibling->n; ++i) {
265+
sibling->child[i - 1] = sibling->child[i];
266+
}
267+
}
268+
269+
child->n += 1;
270+
sibling->n -= 1;
271+
}
272+
273+
static void fill(BTreeNode *x, int idx) {
274+
if (idx != 0 && x->child[idx - 1]->n >= T) {
275+
borrow_from_prev(x, idx);
276+
} else if (idx != x->n && x->child[idx + 1]->n >= T) {
277+
borrow_from_next(x, idx);
278+
} else if (idx != x->n) {
279+
merge(x, idx);
280+
} else {
281+
merge(x, idx - 1);
282+
}
283+
}
284+
285+
static void delete_from_node(BTreeNode *x, int k);
286+
287+
static void remove_from_nonleaf(BTreeNode *x, int idx) {
288+
int k = x->keys[idx];
289+
290+
if (x->child[idx]->n >= T) {
291+
int pred = get_pred(x, idx);
292+
x->keys[idx] = pred;
293+
delete_from_node(x->child[idx], pred);
294+
} else if (x->child[idx + 1]->n >= T) {
295+
int succ = get_succ(x, idx);
296+
x->keys[idx] = succ;
297+
delete_from_node(x->child[idx + 1], succ);
298+
} else {
299+
merge(x, idx);
300+
delete_from_node(x->child[idx], k);
301+
}
302+
}
303+
304+
static void delete_from_node(BTreeNode *x, int k) {
305+
int idx = find_key(x, k);
306+
307+
if (idx < x->n && x->keys[idx] == k) {
308+
if (x->leaf) {
309+
remove_from_leaf(x, idx);
310+
} else {
311+
remove_from_nonleaf(x, idx);
312+
}
313+
return;
314+
}
315+
316+
if (x->leaf) {
317+
return;
318+
}
319+
320+
int was_last = (idx == x->n);
321+
if (x->child[idx]->n < T) {
322+
fill(x, idx);
323+
}
324+
325+
if (was_last && idx > x->n) {
326+
delete_from_node(x->child[idx - 1], k);
327+
} else {
328+
delete_from_node(x->child[idx], k);
329+
}
330+
}
331+
332+
static void bt_delete(BTree *t, int k) {
333+
if (t->root == NULL) {
334+
return;
335+
}
336+
337+
delete_from_node(t->root, k);
338+
339+
if (t->root->n == 0) {
340+
BTreeNode *old = t->root;
341+
if (old->leaf) {
342+
t->root = NULL;
343+
} else {
344+
t->root = old->child[0];
345+
}
346+
free(old);
347+
}
348+
}
349+
350+
int main(void) {
351+
BTree t = {0};
352+
int data[] = {10, 20, 5, 6, 12, 30, 7, 17};
353+
int n = (int)(sizeof(data) / sizeof(data[0]));
354+
355+
for (int i = 0; i < n; ++i) {
356+
bt_insert(&t, data[i]);
357+
}
358+
359+
printf("inorder: ");
360+
bt_traverse(t.root);
361+
printf("\n");
362+
363+
int q1 = 6;
364+
int q2 = 15;
365+
printf("search %d: %s\n", q1, bt_search(t.root, q1, NULL) != NULL ? "found" : "not found");
366+
printf("search %d: %s\n", q2, bt_search(t.root, q2, NULL) != NULL ? "found" : "not found");
367+
368+
int removed[] = {6, 13, 7, 4, 2, 16};
369+
int m = (int)(sizeof(removed) / sizeof(removed[0]));
370+
for (int i = 0; i < m; ++i) {
371+
printf("delete %d\n", removed[i]);
372+
bt_delete(&t, removed[i]);
373+
printf("inorder: ");
374+
bt_traverse(t.root);
375+
printf("\n");
376+
}
377+
378+
int q3 = 6;
379+
int q4 = 7;
380+
printf("search %d: %s\n", q3, bt_search(t.root, q3, NULL) != NULL ? "found" : "not found");
381+
printf("search %d: %s\n", q4, bt_search(t.root, q4, NULL) != NULL ? "found" : "not found");
382+
383+
bt_destroy(&t);
384+
return 0;
385+
}

0 commit comments

Comments
 (0)