llrbtree 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,478 @@
1
+ /*
2
+ * MIT License
3
+ * Copyright (c) 2019 Kyuden Masahiro
4
+ */
5
+
6
+ #include <stdlib.h>
7
+ #include "tree.h"
8
+
9
+ static int
10
+ is_red(node_t *node)
11
+ {
12
+ return node == NULL ? 0 : node->color == node_red;
13
+ }
14
+
15
+ static int
16
+ is_black(node_t *node)
17
+ {
18
+ return node == NULL ? 0 : node->color == node_black;
19
+ }
20
+
21
+ static node_t*
22
+ rotate_left(node_t *upper)
23
+ {
24
+ node_t *lower;
25
+
26
+ lower = upper->right;
27
+ upper->right = lower->left;
28
+ if (upper->right != NULL) {
29
+ upper->right->parent = upper;
30
+ }
31
+
32
+ lower->left = upper;
33
+ lower->parent = upper->parent;
34
+ lower->left->parent = lower;
35
+
36
+ lower->color = upper->color;
37
+ upper->color = node_red;
38
+
39
+ return lower;
40
+ }
41
+
42
+ static node_t*
43
+ rotate_right(node_t *upper)
44
+ {
45
+ node_t *lower;
46
+
47
+ lower = upper->left;
48
+ upper->left = lower->right;
49
+ if (upper->left != NULL) {
50
+ upper->left->parent = upper;
51
+ }
52
+
53
+ lower->right = upper;
54
+ lower->parent = upper->parent;
55
+ lower->right->parent = lower;
56
+
57
+ lower->color = upper->color;
58
+ upper->color = node_red;
59
+
60
+ return lower;
61
+ }
62
+
63
+ static void
64
+ flip_color(node_t *node)
65
+ {
66
+ is_red(node) ? (node->color = node_black) : (node->color = node_red);
67
+
68
+ if (node->left != NULL) {
69
+ is_red(node->left) ? (node->left->color = node_black) : (node->left->color = node_red);
70
+ }
71
+ if (node->right != NULL) {
72
+ is_red(node->right) ? (node->right->color = node_black) : (node->right->color = node_red);
73
+ }
74
+ }
75
+
76
+ static node_t*
77
+ fix_up(node_t *node)
78
+ {
79
+ if (is_red(node->right)) {
80
+ node = rotate_left(node);
81
+ }
82
+ if (is_red(node->left) && is_red(node->left->left)) {
83
+ node = rotate_right(node);
84
+ }
85
+ if (is_red(node->left) && is_red(node->right)) {
86
+ flip_color(node);
87
+ }
88
+
89
+ return node;
90
+ }
91
+
92
+ static node_t*
93
+ move_red_left(node_t *node)
94
+ {
95
+ flip_color(node);
96
+ if (node->right != NULL && is_red(node->right->left)) {
97
+ node->right = rotate_right(node->right);
98
+ node = rotate_left(node);
99
+ flip_color(node);
100
+ }
101
+
102
+ return node;
103
+ }
104
+
105
+ static node_t*
106
+ move_red_right(node_t *node)
107
+ {
108
+ flip_color(node);
109
+ if (node->left != NULL && is_red(node->left->left)) {
110
+ node = rotate_right(node);
111
+ flip_color(node);
112
+ }
113
+
114
+ return node;
115
+ }
116
+
117
+ static node_t*
118
+ delete_min(tree_t *tree, node_t *node)
119
+ {
120
+ if (node->left == NULL) {
121
+ tree->free_node(node, tree->context);
122
+ return NULL;
123
+ }
124
+ if (is_black(node->left) && (node->left->left == NULL || is_black(node->left->left))) {
125
+ node = move_red_left(node);
126
+ }
127
+
128
+ node->left = delete_min(tree, node->left);
129
+ return fix_up(node);
130
+ }
131
+
132
+ static node_t*
133
+ min(node_t *node)
134
+ {
135
+ while (node->left != NULL) {
136
+ node = node->left;
137
+ }
138
+ return node;
139
+ }
140
+
141
+ static void
142
+ free_nodes(tree_t *tree, node_t *node)
143
+ {
144
+ if (node == NULL) return;
145
+
146
+ free_nodes(tree, node->left);
147
+ free_nodes(tree, node->right);
148
+ tree->free_node(node, tree->context);
149
+ }
150
+
151
+ static int
152
+ verify_bintree(tree_t *tree)
153
+ {
154
+ node_t *first, *next;
155
+
156
+ first = tree_first(tree);
157
+
158
+ while (first != NULL && (next = tree_next(tree, first))) {
159
+ if (tree->compare(first->key, next->key, tree->context) >= 0) {
160
+ return 0;
161
+ }
162
+ first = next;
163
+ }
164
+ return 1;
165
+ }
166
+
167
+ static unsigned int
168
+ verify_redblack(node_t *root)
169
+ {
170
+ unsigned height_left, height_right;
171
+
172
+ if (root != NULL) {
173
+ height_left = verify_redblack(root->left);
174
+ height_right = verify_redblack(root->right);
175
+ if (height_left == 0 || height_right == 0) return 0;
176
+ if (height_left != height_right) return 0;
177
+ if (is_red(root)) {
178
+ if (is_red(root->left)) return 0;
179
+ if (is_red(root->right)) return 0;
180
+ return height_left;
181
+ }
182
+ if (is_red(root)) return 0;
183
+ return height_left + 1;
184
+ }
185
+ return 1;
186
+ }
187
+
188
+ static node_count_t
189
+ verify_node_count(node_t *root)
190
+ {
191
+ if (root == NULL) return 0;
192
+
193
+ return 1 + verify_node_count(root->left) + verify_node_count(root->right);
194
+ }
195
+
196
+ void
197
+ tree_free(tree_t *tree)
198
+ {
199
+ free_nodes(tree, tree->root_node);
200
+ tree->root_node = NULL;
201
+ tree->node_count = 0;
202
+ }
203
+
204
+ tree_t*
205
+ tree_init(tree_t *tree, compare_t comp, alloc_node_t al, free_node_t fr, void *context)
206
+ {
207
+ tree->compare = comp;
208
+ tree->alloc_node = al;
209
+ tree->free_node = fr;
210
+ tree->context = NULL;
211
+ tree->node_count = 0;
212
+ tree->root_node = NULL;
213
+ tree->context = context;
214
+ return tree;
215
+ }
216
+
217
+ int
218
+ tree_verify(tree_t *tree)
219
+ {
220
+ if (is_red(tree->root_node)) return 0;
221
+ if (tree->root_node->parent != NULL) return 0;
222
+ if (!verify_bintree(tree)) return 0;
223
+ if (!verify_redblack(tree->root_node)) return 0;
224
+ if (verify_node_count(tree->root_node) != tree->node_count) return 0;
225
+ return 1;
226
+ }
227
+
228
+ int
229
+ tree_similar(const tree_t *left, const tree_t *right)
230
+ {
231
+ if (left->compare != right->compare) return 0;
232
+ if (left->alloc_node != right->alloc_node) return 0;
233
+ if (left->free_node != right->free_node) return 0;
234
+ if (left->context != right->context) return 0;
235
+ return 1;
236
+ }
237
+
238
+ node_t*
239
+ tree_lookup(tree_t *tree, const void *key)
240
+ {
241
+ node_t *root = tree->root_node;
242
+ int result;
243
+
244
+ while (root != NULL) {
245
+ result = tree->compare(key, root->key, tree->context);
246
+ if (result < 0) {
247
+ root = root->left;
248
+ } else if (result > 0) {
249
+ root = root->right;
250
+ } else {
251
+ return root;
252
+ }
253
+ }
254
+
255
+ return NULL;
256
+ }
257
+
258
+ node_t*
259
+ tree_lower_bound(tree_t *tree, const void *key)
260
+ {
261
+ node_t *root = tree->root_node;
262
+ node_t *tentative = 0;
263
+
264
+ while (root != NULL) {
265
+ int result = tree->compare(key, root->key, tree->context);
266
+
267
+ if (result > 0) {
268
+ root = root->right;
269
+ } else if (result < 0) {
270
+ tentative = root;
271
+ root = root->left;
272
+ } else {
273
+ return root;
274
+ }
275
+ }
276
+
277
+ return tentative;
278
+ }
279
+
280
+ node_t*
281
+ tree_upper_bound(tree_t *tree, const void *key)
282
+ {
283
+ node_t *root = tree->root_node;
284
+ node_t *tentative = 0;
285
+
286
+ while (root != NULL) {
287
+ int result = tree->compare(key, root->key, tree->context);
288
+
289
+ if (result < 0) {
290
+ root = root->left;
291
+ } else if (result > 0) {
292
+ tentative = root;
293
+ root = root->right;
294
+ } else {
295
+ return root;
296
+ }
297
+ }
298
+
299
+ return tentative;
300
+ }
301
+
302
+ static node_t*
303
+ recursive_insert(tree_t *tree, node_t *node, node_t *new_node, const void *key)
304
+ {
305
+ int result = -1;
306
+ if (node == NULL) {
307
+ tree->node_count++;
308
+ return new_node;
309
+ }
310
+
311
+ result = tree->compare(key, node->key, tree->context);
312
+
313
+ if (result == 0) {
314
+ node->data = new_node->data;
315
+ } else if (result < 0) {
316
+ node->left = recursive_insert(tree, node->left, new_node, key);
317
+ node->left->parent = node;
318
+ } else {
319
+ node->right = recursive_insert(tree, node->right, new_node, key);
320
+ node->right->parent = node;
321
+ }
322
+
323
+ return fix_up(node);
324
+ }
325
+
326
+ int
327
+ tree_insert(tree_t *tree, node_t *node, const void *key)
328
+ {
329
+ tree->root_node = recursive_insert(tree, tree->root_node, node, key);
330
+ tree->root_node->color = node_black;
331
+ return 1;
332
+ }
333
+
334
+ static node_t*
335
+ recursive_delete(tree_t *tree, node_t *node, const void *key)
336
+ {
337
+ node_t *min_node;
338
+
339
+ if (node == NULL) return NULL;
340
+
341
+ if (tree->compare(key, node->key, tree->context) < 0) {
342
+ if (is_black(node->left) && (node->left->left == NULL || is_black(node->left->left))) {
343
+ node = move_red_left(node);
344
+ }
345
+ node->left = recursive_delete(tree, node->left, key);
346
+ } else {
347
+ if (is_red(node->left)) {
348
+ node = rotate_right(node);
349
+ }
350
+
351
+ if (is_black(node->right) && (node->right->left == NULL || is_black(node->right->left))) {
352
+ node = move_red_right(node);
353
+ }
354
+
355
+ if (tree->compare(key, node->key, tree->context) == 0) {
356
+ if (node->right == NULL) {
357
+ tree->free_node(node, tree->context);
358
+ return NULL;
359
+ }
360
+
361
+ min_node = min(node->right);
362
+ node->key = min_node->key;
363
+ node->data = min_node->data;
364
+ node->right = delete_min(tree, node->right);
365
+ } else {
366
+ node->right = recursive_delete(tree, node->right, key);
367
+ }
368
+ }
369
+
370
+ return fix_up(node);
371
+ }
372
+
373
+ void
374
+ tree_delete(tree_t *tree, const void *key)
375
+ {
376
+ tree->root_node = recursive_delete(tree, tree->root_node, key);
377
+ if (tree->root_node != NULL) {
378
+ tree->root_node->color = node_black;
379
+ }
380
+ tree->node_count--;
381
+ }
382
+
383
+ node_t*
384
+ tree_first(tree_t *tree)
385
+ {
386
+ node_t *root = tree->root_node, *left;
387
+
388
+ if (root != NULL) {
389
+ while ((left = root->left) != NULL) {
390
+ root = left;
391
+ }
392
+ }
393
+
394
+ return (root == NULL) ? NULL : root;
395
+ }
396
+
397
+ node_t*
398
+ tree_last(tree_t *tree)
399
+ {
400
+ node_t *root = tree->root_node, *right;
401
+
402
+ if (root != NULL) {
403
+ while ((right = root->right) != NULL) {
404
+ root = right;
405
+ }
406
+ }
407
+
408
+ return (root == NULL) ? NULL : root;
409
+ }
410
+
411
+ node_t*
412
+ tree_next(tree_t *tree, node_t *curr)
413
+ {
414
+ node_t *parent, *left;
415
+
416
+ if (curr->right != NULL) {
417
+ curr = curr->right;
418
+ while ((left = curr->left) != NULL) {
419
+ curr = left;
420
+ }
421
+ return curr;
422
+ }
423
+
424
+ parent = curr->parent;
425
+
426
+ while (parent != NULL && curr == parent->right) {
427
+ curr = parent;
428
+ parent = curr->parent;
429
+ }
430
+
431
+ return (parent == NULL) ? NULL : parent;
432
+ }
433
+
434
+ node_t*
435
+ tree_prev(tree_t *tree, node_t *curr)
436
+ {
437
+ node_t *parent, *right;
438
+
439
+ if (curr->left != NULL) {
440
+ curr = curr->left;
441
+ while ((right = curr->right) != NULL) {
442
+ curr = right;
443
+ }
444
+ return curr;
445
+ }
446
+
447
+ parent = curr->parent;
448
+
449
+ while (parent != NULL && curr == parent->left) {
450
+ curr = parent;
451
+ parent = curr->parent;
452
+ }
453
+
454
+ return (parent == NULL) ? NULL : parent;
455
+ }
456
+
457
+ int
458
+ tree_isempty(tree_t *tree)
459
+ {
460
+ return tree->node_count == 0;
461
+ }
462
+
463
+ int
464
+ tree_isfull(tree_t *tree)
465
+ {
466
+ return tree->node_count == NODE_COUNT_T_MAX;
467
+ }
468
+
469
+ node_t*
470
+ node_init(node_t *node, void *data)
471
+ {
472
+ node->data = data;
473
+ node->parent = NULL;
474
+ node->left = NULL;
475
+ node->right = NULL;
476
+ node->color = node_red;
477
+ return node;
478
+ }
@@ -0,0 +1,63 @@
1
+ /*
2
+ * MIT License
3
+ * Copyright (c) 2019 Kyuden Masahiro
4
+ */
5
+
6
+ #ifndef LLRB_TREE_H
7
+ #define LLRB_TREE_H
8
+
9
+ #include <limits.h>
10
+
11
+ #ifdef __cplusplus
12
+ extern "C" {
13
+ #endif
14
+
15
+ #define NODE_COUNT_T_MAX ULONG_MAX
16
+
17
+ typedef enum { node_red, node_black } node_color_t;
18
+
19
+ typedef struct node_t {
20
+ struct node_t *left;
21
+ struct node_t *right;
22
+ struct node_t *parent;
23
+ node_color_t color;
24
+ const void *key;
25
+ void *data;
26
+ } node_t;
27
+
28
+ typedef unsigned long node_count_t;
29
+ typedef int (*compare_t)(const void *, const void *, void *);
30
+ typedef node_t *(*alloc_node_t)(void *);
31
+ typedef void (*free_node_t)(node_t *, void *);
32
+
33
+ typedef struct tree_t {
34
+ node_t *root_node;
35
+ node_count_t node_count;
36
+ compare_t compare;
37
+ alloc_node_t alloc_node;
38
+ free_node_t free_node;
39
+ void *context;
40
+ } tree_t;
41
+
42
+ extern void tree_free(tree_t *);
43
+ extern tree_t *tree_init(tree_t *, compare_t, alloc_node_t, free_node_t, void *);
44
+ extern int tree_verify(tree_t *);
45
+ extern int tree_similar(const tree_t *, const tree_t *);
46
+ extern node_t *tree_lookup(tree_t *, const void *);
47
+ extern node_t *tree_lower_bound(tree_t *, const void *);
48
+ extern node_t *tree_upper_bound(tree_t *, const void *);
49
+ extern int tree_insert(tree_t *, node_t *, const void *);
50
+ extern void tree_delete(tree_t *, const void *);
51
+ extern node_t *tree_first(tree_t *);
52
+ extern node_t *tree_last(tree_t *);
53
+ extern node_t *tree_next(tree_t *, node_t *);
54
+ extern node_t *tree_prev(tree_t *, node_t *);
55
+ extern int tree_isempty(tree_t *);
56
+ extern int tree_isfull(tree_t *);
57
+ extern node_t *node_init(node_t *, void *);
58
+
59
+ #ifdef __cplusplus
60
+ }
61
+ #endif
62
+
63
+ #endif
@@ -0,0 +1,3 @@
1
+ class LLRBTree
2
+ VERSION = '0.0.1'
3
+ end
data/lib/llrbtree.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'llrbtree/llrbtree'
2
+ require 'llrbtree/version'
data/llrbtree.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'llrbtree'
3
+ spec.version = '0.0.1'
4
+ spec.authors = ['kyuden']
5
+ spec.email = ['msmsms.um@gmail.com']
6
+
7
+ spec.summary = %q{Left-Leaning Red-Black Tree for Ruby.}
8
+ spec.description = %q{Left-Leaning Red-Black Tree for Ruby.}
9
+ spec.homepage = 'https://github.com/kyuden/llrbtree'
10
+
11
+ # Specify which files should be added to the gem when it is released.
12
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
13
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
14
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ end
16
+ spec.bindir = 'exe'
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ['lib']
19
+ spec.extensions = %w[ext/llrbtree/extconf.rb]
20
+
21
+ spec.add_development_dependency 'bundler'
22
+ spec.add_development_dependency 'rake'
23
+ spec.add_development_dependency 'test-unit'
24
+ spec.add_development_dependency 'rake-compiler'
25
+ end
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: llrbtree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - kyuden
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-01-30 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: test-unit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake-compiler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Left-Leaning Red-Black Tree for Ruby.
70
+ email:
71
+ - msmsms.um@gmail.com
72
+ executables: []
73
+ extensions:
74
+ - ext/llrbtree/extconf.rb
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".ruby-version"
79
+ - ".travis.yml"
80
+ - CODE_OF_CONDUCT.md
81
+ - Gemfile
82
+ - README.md
83
+ - Rakefile
84
+ - bin/console
85
+ - bin/setup
86
+ - ext/llrbtree/depend
87
+ - ext/llrbtree/extconf.rb
88
+ - ext/llrbtree/llrbtree.c
89
+ - ext/llrbtree/tree.c
90
+ - ext/llrbtree/tree.h
91
+ - lib/llrbtree.rb
92
+ - lib/llrbtree/version.rb
93
+ - llrbtree.gemspec
94
+ homepage: https://github.com/kyuden/llrbtree
95
+ licenses: []
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubygems_version: 3.0.1
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Left-Leaning Red-Black Tree for Ruby.
116
+ test_files: []