victory 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -0
  3. data/.rubocop.yml +11 -1
  4. data/README.md +4 -6
  5. data/Rakefile +11 -4
  6. data/USAGE.md +159 -0
  7. data/ext/algorithms/string/LICENSE.md +21 -0
  8. data/ext/algorithms/string/extconf.rb +4 -0
  9. data/ext/algorithms/string/string.c +68 -0
  10. data/ext/containers/bst/LICENSE.md +21 -0
  11. data/ext/containers/bst/bst.c +247 -0
  12. data/ext/containers/bst/extconf.rb +4 -0
  13. data/ext/containers/deque/LICENSE.md +21 -0
  14. data/ext/containers/deque/deque.c +247 -0
  15. data/ext/containers/deque/extconf.rb +4 -0
  16. data/ext/containers/rbtree_map/LICENSE.md +21 -0
  17. data/ext/containers/rbtree_map/extconf.rb +4 -0
  18. data/ext/containers/rbtree_map/rbtree.c +498 -0
  19. data/ext/containers/splaytree_map/LICENSE.md +21 -0
  20. data/ext/containers/splaytree_map/extconf.rb +4 -0
  21. data/ext/containers/splaytree_map/splaytree.c +419 -0
  22. data/ext/containers/xor_list/extconf.rb +4 -0
  23. data/ext/containers/xor_list/xor_list.c +122 -0
  24. data/lib/algorithms/search.rb +104 -0
  25. data/lib/algorithms/sort.rb +389 -0
  26. data/lib/algorithms/string.rb +29 -0
  27. data/lib/containers/deque.rb +193 -0
  28. data/lib/containers/heap.rb +524 -0
  29. data/lib/containers/kd_tree.rb +131 -0
  30. data/lib/containers/list.rb +81 -0
  31. data/lib/containers/prefix_tree.rb +61 -0
  32. data/lib/containers/priority_queue.rb +135 -0
  33. data/lib/containers/queue.rb +89 -0
  34. data/lib/containers/rb_tree_map.rb +420 -0
  35. data/lib/containers/splay_tree_map.rb +290 -0
  36. data/lib/containers/stack.rb +88 -0
  37. data/lib/containers/suffix_array.rb +92 -0
  38. data/lib/containers/trie.rb +204 -0
  39. data/lib/containers/tuple.rb +20 -0
  40. data/lib/victory/version.rb +1 -1
  41. data/lib/victory.rb +8 -1
  42. data/victory.gemspec +12 -3
  43. metadata +73 -12
  44. data/.idea/encodings.xml +0 -4
  45. data/.idea/misc.xml +0 -7
  46. data/.idea/modules.xml +0 -8
  47. data/.idea/victory.iml +0 -13
  48. data/.idea/workspace.xml +0 -233
  49. data/ext/victory/extconf.rb +0 -3
  50. data/ext/victory/victory.c +0 -9
  51. data/ext/victory/victory.h +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 338b333cefdfe98444e20851393081ad3af713717bf00f346d99826732721280
4
- data.tar.gz: cc5c8517bc3ba2ff7d8b662f72901d47673c32921d62fa4e65d19afd294c110f
3
+ metadata.gz: 717f4606348a07fae563b347197930dc0ebae3a48f1d28fc83edf3f6616197c7
4
+ data.tar.gz: 968a58a7f01bd4659ba396b570db14821eeafb318294b5a9deb3c8ba8dc02647
5
5
  SHA512:
6
- metadata.gz: ff55c99e4e2b5974e6b373ed6dfecd1b7134623b9a13107d9a8f7871e63fac3350d407f2c07e7b6b6bbdd9f89f21af8e88799101d8fd874f03859460ad8c638c
7
- data.tar.gz: 210bd6551491e26c9b4f41b217fea8cef55521edb11a99fa5703b3e392d778daf835085e2c1d0b17d26739ddd0c6aa87faecb6a62257fab2a633fea80c252fcf
6
+ metadata.gz: fe1daf498c13876f2a8d580cb5c2d1fcf22581dabb88858d56925d034380cddadf060c78ac07b80fd302538177ad79543466b951699bee92e1722dac3f60e7ed
7
+ data.tar.gz: 77305c8712aa38e77ca69e9fa907bd5cc00a905bd4b9e1966a8a958e927b7bde1b6179e7890743d370707aeabce2a3a0cfaf9d6e78363dc613fa10e9a6ec8091
data/.gitignore CHANGED
@@ -96,3 +96,8 @@ fabric.properties
96
96
  .idea/sonarlint
97
97
 
98
98
  # End of https://www.gitignore.io/api/intellij
99
+
100
+ .idea/
101
+
102
+ Gemfile.lock
103
+ **/*.gem
data/.rubocop.yml CHANGED
@@ -13,4 +13,14 @@ Layout/SpaceAroundOperators:
13
13
  Style/TrailingCommaInArrayLiteral:
14
14
  Enabled: false
15
15
  AllCops:
16
- TargetRubyVersion: 2.6
16
+ TargetRubyVersion: 2.6
17
+ Style/WordArray:
18
+ Enabled: false
19
+ Metrics/AbcSize:
20
+ Enabled: false
21
+ Metrics/MethodLength:
22
+ Max: 20
23
+ Style/Documentation:
24
+ Enabled: false
25
+ Style/FrozenStringLiteralComment:
26
+ Enabled: false
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Victory
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/victory`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ A gem providing all useful algorithms and data structures for contests
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,7 +20,7 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
25
- TODO: Write usage instructions here
23
+ Can be found at [usage](https://github.com/Szetty/victory/blob/master/USAGE.md).
26
24
 
27
25
  ## Development
28
26
 
@@ -32,7 +30,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
30
 
33
31
  ## Contributing
34
32
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/victory. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
33
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Szetty/victory. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
34
 
37
35
  ## License
38
36
 
@@ -40,4 +38,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
40
38
 
41
39
  ## Code of Conduct
42
40
 
43
- Everyone interacting in the Victory project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/victory/blob/master/CODE_OF_CONDUCT.md).
41
+ Everyone interacting in the Victory project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Szetty/victory/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile CHANGED
@@ -11,8 +11,15 @@ require "rake/extensiontask"
11
11
 
12
12
  task :build => :compile
13
13
 
14
- Rake::ExtensionTask.new("victory") do |ext|
15
- ext.lib_dir = "lib/victory"
16
- end
14
+ Rake::ExtensionTask.new('algorithms/string') { |ext| ext.name = "CString" }
15
+ Rake::ExtensionTask.new('containers/deque') { |ext| ext.name = "CDeque" }
16
+ Rake::ExtensionTask.new('containers/bst') { |ext| ext.name = "CBst" }
17
+ Rake::ExtensionTask.new('containers/rbtree_map') { |ext| ext.name = "CRBTreeMap" }
18
+ Rake::ExtensionTask.new('containers/splaytree_map') { |ext| ext.name = "CSplayTreeMap" }
19
+ Rake::ExtensionTask.new('containers/xor_list') { |ext| ext.name = 'XORList' }
20
+
21
+ require 'rspec/core/rake_task'
22
+
23
+ RSpec::Core::RakeTask.new
17
24
 
18
- task :default => [:clobber, :compile, :test]
25
+ task :default => [:clobber, :compile, :spec, :test]
data/USAGE.md ADDED
@@ -0,0 +1,159 @@
1
+ # Usage
2
+
3
+ In this markdown you will see the usage of all the datastructures and algorithms available through the standard library and this gem.
4
+
5
+ # Data Structures
6
+
7
+ * [Array](#array)
8
+ * [Hash](#hash)
9
+ * [Set](#set)
10
+ * [Struct](#struct)
11
+ * [OpenStruct](#openstruct)
12
+ * [Tuple](#tuple)
13
+
14
+ <a name="array" />
15
+
16
+ ## Array
17
+
18
+ ```ruby
19
+ []
20
+ # => []
21
+ Array.new(4)
22
+ # => [nil, nil, nil, nil]
23
+ Array.new(4, 4)
24
+ # => [4, 4, 4, 4]
25
+
26
+ a = [:a, :b, :c, :d]
27
+ a[2]
28
+ # => :c
29
+ a[1] = 3
30
+ a
31
+ # => [:a, 3, :c, :d]
32
+
33
+ b = [1,2,3]
34
+ b[10] = :foo
35
+ b
36
+ # => [1, 2, 3, nil, nil, nil, nil, nil, nil, nil, :foo]
37
+ ```
38
+
39
+ <a name="hash" />
40
+
41
+ ## Hash
42
+
43
+ ```ruby
44
+ {}
45
+ Hash.new(default = nil)
46
+ # => {}
47
+ {"a" => 100, "b" => 200}
48
+ # => {"a"=>100, "b"=>200}
49
+ {a: 100, b: 200}
50
+ # => {:a=>100, :b=>200}
51
+ a = {}
52
+ a[1] = 2
53
+ a
54
+ # => {1=>2}
55
+ a[1]
56
+ # => 2
57
+ ```
58
+
59
+ <a name="set" />
60
+
61
+ ## Set
62
+
63
+ ```ruby
64
+ require 'set'
65
+
66
+ s = Set.new
67
+ # => #<Set: {}>
68
+ s << :a
69
+ # => #<Set: {:a}>
70
+ s << :a
71
+ # => #<Set: {:a}>
72
+ s << :b
73
+ # => #<Set: {:a, :b}>
74
+ ```
75
+
76
+ <a name="struct" />
77
+
78
+ ## Struct
79
+
80
+ ```ruby
81
+ Face = Struct.new(:hair, :eyes, :skin)
82
+
83
+ my_face = Face.new :blond, :blue, :awesome
84
+ # => #<struct Face hair=:blond, eyes=:blue, skin=:awesome>
85
+
86
+ my_face[:hair]
87
+ # => :blond
88
+ my_face.hair
89
+ # => :blond
90
+ my_face.nose
91
+ # NoMethodError: undefined method `nose' for #<struct Face hair=:blond, eyes=:blue, skin=:awesome>
92
+ my_face[:nose]
93
+ # NameError: no member 'nose' in struc
94
+
95
+
96
+ class PayChecks < Struct.new(:week1, :week2, :week3, :week4)
97
+ def total
98
+ inject :+
99
+ end
100
+ end
101
+
102
+ pay_checks = PayChecks.new 100, 800, 300, 45
103
+ # => #<struct PayChecks week1=100, week2=800, week3=300, week4=45>
104
+ pay_checks.total
105
+ # => 1245
106
+ ```
107
+
108
+ <a name="openstruct" />
109
+
110
+ ## OpenStruct
111
+
112
+ ```ruby
113
+ require 'ostruct'
114
+
115
+ x = OpenStruct.new
116
+ # => #<OpenStruct>
117
+
118
+ x[:a]
119
+ # => nil
120
+ x
121
+ # => #<OpenStruct>
122
+
123
+ x[:a] = 0
124
+ # => 0
125
+ x
126
+ # => #<OpenStruct a=0>
127
+ x.a
128
+ # => 0
129
+
130
+ x.b
131
+ # => nil
132
+ x
133
+ # => #<OpenStruct a=0>
134
+ x[:b] = 123
135
+ # => 123
136
+ x
137
+ # => #<OpenStruct a=0, b=123>
138
+ ```
139
+
140
+ <a name="tuple" />
141
+
142
+ ## Tuple
143
+
144
+ ```ruby
145
+ t = T[1, 2, 3]
146
+
147
+ a, _, c = *t
148
+ a
149
+ # => 1
150
+ c
151
+ # => 3
152
+ t[2]
153
+ # => 2
154
+ ```
155
+
156
+ # Other useful links
157
+
158
+ * https://github.com/kumar91gopi/Algorithms-and-Data-Structures-in-Ruby/
159
+ * https://github.com/sagivo/algorithms
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2009 Kanwei Li
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CString"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,68 @@
1
+ #include "ruby.h"
2
+
3
+ long min_three(long a, long b, long c) {
4
+ long min = a;
5
+ if (b < min)
6
+ min = b;
7
+ if( c < min)
8
+ min = c;
9
+ return min;
10
+ }
11
+
12
+ long levenshtein_distance(VALUE str1, VALUE str2) {
13
+ long i, j, s1_len, s2_len, *d;
14
+ char * s = RSTRING_PTR(str1);
15
+ char * t = RSTRING_PTR(str2);
16
+ s1_len = RSTRING_LEN(str1);
17
+ s2_len = RSTRING_LEN(str2);
18
+
19
+ if (s1_len == 0) {
20
+ return s2_len;
21
+ } else if (s2_len == 0) {
22
+ return s1_len;
23
+ }
24
+
25
+ // We need one extra col and row for the matrix for starting values
26
+ s1_len++;
27
+ s2_len++;
28
+
29
+ d = xmalloc(sizeof(typeof(d)) * s1_len * s2_len);
30
+
31
+ for (i = 0; i < s1_len; i++) {
32
+ d[i] = i; // d[i, 0] = i
33
+ }
34
+ for (j = 0; j < s2_len; j++) {
35
+ d[j*s1_len] = j; // d[0, j] = j
36
+ }
37
+
38
+ for (i = 1; i < s1_len; i++) {
39
+ for (j = 1; j < s2_len; j++) {
40
+ if (s[i-1] == t[j-1]) {
41
+ d[j * s1_len + i] = d[(j-1) * s1_len + (i-1)];
42
+ } else {
43
+ d[j * s1_len + i] = 1 + min_three(
44
+ d[j * s1_len + (i-1)],
45
+ d[(j-1) * s1_len + i],
46
+ d[(j-1) * s1_len + (i-1)]
47
+ );
48
+ }
49
+ }
50
+ }
51
+ i = d[s1_len * s2_len -1];
52
+ xfree(d);
53
+ return i;
54
+ }
55
+
56
+ static VALUE lev_dist(VALUE self, VALUE str1, VALUE str2) {
57
+ return LONG2FIX(levenshtein_distance( str1, str2 ));
58
+ }
59
+
60
+ static VALUE mAlgorithms;
61
+ static VALUE mString;
62
+
63
+ void Init_CString() {
64
+ mAlgorithms = rb_define_module("Algorithms");
65
+ mString = rb_define_module_under(mAlgorithms, "String");
66
+ rb_define_singleton_method(mString, "levenshtein_dist", lev_dist, 2);
67
+ }
68
+
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2009 Kanwei Li
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,247 @@
1
+ #include "ruby.h"
2
+
3
+ typedef struct struct_bst_node {
4
+ VALUE key;
5
+ VALUE value;
6
+ struct struct_bst_node *left;
7
+ struct struct_bst_node *right;
8
+ struct struct_bst_node *parent;
9
+ } bst_node;
10
+
11
+ typedef struct struct_bst {
12
+ bst_node *root;
13
+ int (*compare_function)(VALUE key1, VALUE key2);
14
+ unsigned int size;
15
+ } bst;
16
+
17
+ static VALUE bst_initialize(VALUE self) {
18
+ return self;
19
+ }
20
+
21
+ static bst* get_bst_from_self(VALUE self) {
22
+ bst *tree;
23
+ Data_Get_Struct(self, bst, tree);
24
+ return tree;
25
+ }
26
+
27
+ static bst* bst_each_node(bst *tree, bst_node *node, void (*each)(bst *tree_, bst_node *node_, void* args), void* arguments) {
28
+ if (!node)
29
+ return NULL;
30
+
31
+ if (node->left)
32
+ bst_each_node(tree, node->left, each, arguments);
33
+
34
+ (*each)(tree, node, arguments);
35
+
36
+ if (node->right)
37
+ bst_each_node(tree, node->right, each, arguments);
38
+ return tree;
39
+ }
40
+
41
+ static bst* bst_each(bst *tree, void (*each)(bst *tree, bst_node *node, void *args), void* arguments) {
42
+ if (tree->root)
43
+ bst_each_node(tree, tree->root, each, arguments);
44
+ return tree;
45
+ }
46
+
47
+ static VALUE id_compare_operator;
48
+
49
+ static int bst_compare_function(VALUE a, VALUE b) {
50
+ if (a == b) return 0;
51
+ if (FIXNUM_P(a) && FIXNUM_P(b)) {
52
+ long x = FIX2LONG(a), y = FIX2LONG(b);
53
+ if (x == y) return 0;
54
+ if (x > y) return 1;
55
+ return -1;
56
+ }
57
+ if (TYPE(a) == T_STRING && rb_obj_is_kind_of(a, rb_cString) &&
58
+ TYPE(b) == T_STRING && rb_obj_is_kind_of(b, rb_cString)) {
59
+ return rb_str_cmp(a, b);
60
+ }
61
+ return FIX2INT(rb_funcall((VALUE) a, id_compare_operator, 1, (VALUE) b));
62
+ }
63
+
64
+ static void insert_element(bst *tree, bst_node **t,bst_node *newElement) {
65
+ int cmp;
66
+ bst_node *y = NULL;
67
+ bst_node *x = *t;
68
+ while (x != NULL) {
69
+ y = x;
70
+ cmp = tree->compare_function(newElement->key, x->key);
71
+ if (cmp < 0) x = x->left;
72
+ else x = x->right;
73
+ }
74
+ newElement->parent = y;
75
+ if (y == NULL) *t = newElement;
76
+ else {
77
+ cmp = tree->compare_function(newElement->key, y->key);
78
+ if (cmp < 0)
79
+ y->left = newElement;
80
+ else
81
+ y->right = newElement;
82
+ }
83
+ }
84
+
85
+
86
+ static bst_node* create_node(VALUE key_value,VALUE value) {
87
+ bst_node *new_node = ALLOC(bst_node);
88
+ new_node->value = value;
89
+ new_node->key = key_value;
90
+ new_node->left = NULL;
91
+ new_node->right = NULL;
92
+ new_node->parent = NULL;
93
+ return new_node;
94
+ }
95
+
96
+ static bst_node* tree_minimum (bst_node *tree) {
97
+ bst_node *x = tree;
98
+ while (x->left) x = x->left;
99
+ return x;
100
+ }
101
+
102
+ static bst_node* tree_maximum (bst_node *tree) {
103
+ bst_node *x = tree;
104
+ while (x->right) x = x->right;
105
+ return x;
106
+ }
107
+
108
+ static bst_node* node_successor (bst_node *tree,bst_node *x) {
109
+ if (x->right) return tree_minimum(x->right);
110
+ bst_node *y = x->parent;
111
+ while (y && x == y->right) {
112
+ x = y;
113
+ y = x->parent;
114
+ }
115
+ return y;
116
+ }
117
+
118
+
119
+ static bst_node* delete_node (bst_node **tree,bst_node *tobeDeleted) {
120
+ bst_node *y,*x;
121
+
122
+ if ((tobeDeleted->left == NULL) || (tobeDeleted->right == NULL)) y = tobeDeleted;
123
+ else y = node_successor(*tree,tobeDeleted);
124
+
125
+ if (y->left) x = y->left;
126
+ else x = y->right;
127
+
128
+ if (x) x->parent = y->parent;
129
+
130
+ if (y->parent == NULL) {
131
+ *tree = x;
132
+ return y;
133
+ } else if (y == y->parent->left) {
134
+ y->parent->left = x;
135
+ } else {
136
+ y->parent->right = x;
137
+ }
138
+
139
+ if (tobeDeleted != y) tobeDeleted->key = y->key;
140
+ return y;
141
+ }
142
+
143
+ static bst_node* search_node(bst *tree, bst_node *node, VALUE key) {
144
+ bst_node *x = node;
145
+ int cmp;
146
+
147
+ while(x) {
148
+ cmp = tree->compare_function(key, x->key);
149
+ if (cmp == 0) return x;
150
+ else if (cmp < 0) { x = x->left; }
151
+ else { x = x->right; }
152
+ }
153
+ return NULL;
154
+ }
155
+
156
+ static void recursively_mark_nodes(bst_node *node) {
157
+ if(node) {
158
+ rb_gc_mark(node->key);
159
+ rb_gc_mark(node->value);
160
+ recursively_mark_nodes(node->left);
161
+ recursively_mark_nodes(node->right);
162
+ }
163
+ }
164
+
165
+ static void bst_mark(bst *tree) {
166
+ if (tree) {
167
+ recursively_mark_nodes(tree->root);
168
+ }
169
+ }
170
+
171
+ static void recursively_free_nodes(bst_node *node) {
172
+ if(node) {
173
+ recursively_free_nodes(node->left);
174
+ recursively_free_nodes(node->right);
175
+ xfree(node);
176
+ }
177
+ }
178
+
179
+ static void bst_free(bst *tree) {
180
+ if (tree) {
181
+ recursively_free_nodes(tree->root);
182
+ }
183
+ }
184
+
185
+ static bst* create_bst(int (*compare_function)(VALUE, VALUE)) {
186
+ bst *tree = ALLOC(bst);
187
+ tree->compare_function = compare_function;
188
+ tree->root = NULL;
189
+ tree->size = 0;
190
+ return tree;
191
+ }
192
+
193
+ static VALUE bst_alloc(VALUE klass) {
194
+ bst *tree = create_bst(&bst_compare_function);
195
+ return Data_Wrap_Struct(klass, bst_mark, bst_free, tree);
196
+ }
197
+
198
+ static VALUE rb_bst_push_value(VALUE self, VALUE key, VALUE value) {
199
+ bst *tree = get_bst_from_self(self);
200
+ insert_element(tree, &(tree->root), create_node(key,value));
201
+ tree->size++;
202
+ return self;
203
+ }
204
+
205
+ static void bst_each_helper(bst *tree, bst_node *node, void *args) {
206
+ rb_yield(rb_ary_new3(2, node->key, node->value));
207
+ };
208
+
209
+ static VALUE rb_bst_each(VALUE self) {
210
+ bst *tree = get_bst_from_self(self);
211
+ bst_each(tree, &bst_each_helper, NULL);
212
+ return self;
213
+ }
214
+
215
+ static VALUE rb_bst_delete(VALUE self, VALUE key) {
216
+ bst *tree = get_bst_from_self(self);
217
+ bst_node *tobeDeleted = search_node(tree, tree->root, key);
218
+ if(tobeDeleted) {
219
+ tree->size -= 1;
220
+ bst_node *deletedNode = delete_node(&(tree->root),tobeDeleted);
221
+ return deletedNode->value;
222
+ }
223
+ return Qnil;
224
+ }
225
+
226
+ static VALUE rb_bst_size(VALUE self) {
227
+ bst *tree;
228
+ Data_Get_Struct(self,bst,tree);
229
+ return INT2FIX(tree->size);
230
+ }
231
+
232
+ static VALUE CBst;
233
+ static VALUE mContainers;
234
+
235
+ void Init_CBst() {
236
+ id_compare_operator = rb_intern("<=>");
237
+
238
+ mContainers = rb_define_module("Containers");
239
+ CBst = rb_define_class_under(mContainers, "CBst", rb_cObject);
240
+ rb_define_alloc_func(CBst, bst_alloc);
241
+ rb_define_method(CBst, "initialize", bst_initialize, 0);
242
+ rb_define_method(CBst, "push", rb_bst_push_value, 2);
243
+ rb_define_alias(CBst, "[]=", "push");
244
+ rb_define_method(CBst, "each", rb_bst_each, 0);
245
+ rb_define_method(CBst, "delete", rb_bst_delete, 1);
246
+ rb_define_method(CBst, "size", rb_bst_size, 0);
247
+ }
@@ -0,0 +1,4 @@
1
+ require 'mkmf'
2
+ extension_name = "CBst"
3
+ dir_config(extension_name)
4
+ create_makefile(extension_name)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2009 Kanwei Li
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.