llrbtree 0.0.1

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.
@@ -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: []