algorithms 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{History.txt → CHANGELOG.markdown} +11 -0
- data/Manifest +9 -1
- data/Rakefile +5 -23
- data/algorithms.gemspec +20 -16
- data/ext/algorithms/string/extconf.rb +4 -0
- data/ext/algorithms/string/string.c +68 -0
- data/ext/containers/bst/bst.c +247 -0
- data/ext/containers/bst/extconf.rb +4 -0
- data/lib/algorithms.rb +3 -6
- data/lib/algorithms/string.rb +8 -0
- data/lib/containers/heap.rb +16 -0
- data/spec/bst_gc_mark_spec.rb +25 -0
- data/spec/bst_spec.rb +25 -0
- data/spec/deque_spec.rb +2 -2
- data/spec/heap_spec.rb +5 -0
- data/spec/rb_tree_map_spec.rb +2 -2
- data/spec/splay_tree_map_spec.rb +2 -2
- data/spec/string_spec.rb +13 -0
- metadata +69 -36
@@ -1,3 +1,14 @@
|
|
1
|
+
=== April 19, 2012
|
2
|
+
|
3
|
+
* Pulled in fix for ruby 1.9 compilation error (sorry!!)
|
4
|
+
* Fix specs that broke with new rspec
|
5
|
+
* Migration to rubygems.org
|
6
|
+
* 0.4.0 release
|
7
|
+
|
8
|
+
=== Jan 3, 2009
|
9
|
+
|
10
|
+
* Levenshtein distance in C
|
11
|
+
|
1
12
|
=== April 3, 2009
|
2
13
|
|
3
14
|
* Finished C refactorization of SplayTree
|
data/Manifest
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
CHANGELOG.markdown
|
2
2
|
Manifest
|
3
3
|
README.markdown
|
4
4
|
Rakefile
|
@@ -6,6 +6,10 @@ algorithms.gemspec
|
|
6
6
|
benchmarks/deque.rb
|
7
7
|
benchmarks/sorts.rb
|
8
8
|
benchmarks/treemaps.rb
|
9
|
+
ext/algorithms/string/extconf.rb
|
10
|
+
ext/algorithms/string/string.c
|
11
|
+
ext/containers/bst/bst.c
|
12
|
+
ext/containers/bst/extconf.rb
|
9
13
|
ext/containers/deque/deque.c
|
10
14
|
ext/containers/deque/extconf.rb
|
11
15
|
ext/containers/rbtree_map/extconf.rb
|
@@ -15,6 +19,7 @@ ext/containers/splaytree_map/splaytree.c
|
|
15
19
|
lib/algorithms.rb
|
16
20
|
lib/algorithms/search.rb
|
17
21
|
lib/algorithms/sort.rb
|
22
|
+
lib/algorithms/string.rb
|
18
23
|
lib/containers/deque.rb
|
19
24
|
lib/containers/heap.rb
|
20
25
|
lib/containers/kd_tree.rb
|
@@ -25,6 +30,8 @@ lib/containers/splay_tree_map.rb
|
|
25
30
|
lib/containers/stack.rb
|
26
31
|
lib/containers/suffix_array.rb
|
27
32
|
lib/containers/trie.rb
|
33
|
+
spec/bst_gc_mark_spec.rb
|
34
|
+
spec/bst_spec.rb
|
28
35
|
spec/deque_gc_mark_spec.rb
|
29
36
|
spec/deque_spec.rb
|
30
37
|
spec/heap_spec.rb
|
@@ -39,5 +46,6 @@ spec/search_spec.rb
|
|
39
46
|
spec/sort_spec.rb
|
40
47
|
spec/splay_tree_map_spec.rb
|
41
48
|
spec/stack_spec.rb
|
49
|
+
spec/string_spec.rb
|
42
50
|
spec/suffix_array_spec.rb
|
43
51
|
spec/trie_spec.rb
|
data/Rakefile
CHANGED
@@ -4,28 +4,10 @@ require 'echoe'
|
|
4
4
|
Echoe.new('algorithms') do |p|
|
5
5
|
p.author = 'Kanwei Li'
|
6
6
|
p.email = 'kanwei@gmail.com'
|
7
|
-
p.summary = 'A library of algorithms and containers.'
|
8
|
-
p.url = '
|
9
|
-
p.version = "0.
|
7
|
+
p.summary = 'A library of algorithms and data structures (containers).'
|
8
|
+
p.url = 'https://rubygems.org/gems/algorithms'
|
9
|
+
p.version = "0.4.0"
|
10
|
+
p.retain_gemspec = true
|
10
11
|
p.runtime_dependencies = []
|
12
|
+
p.development_dependencies = ["rspec", "echoe"]
|
11
13
|
end
|
12
|
-
|
13
|
-
task :default => :spec
|
14
|
-
|
15
|
-
task :spec do
|
16
|
-
sh "spec spec/*.rb --color"
|
17
|
-
end
|
18
|
-
|
19
|
-
task :push do
|
20
|
-
sh "git push" # Rubyforge
|
21
|
-
sh "git push --tags" # Rubyforge
|
22
|
-
sh "git push gh" # Github
|
23
|
-
sh "git push gh --tags" # Github
|
24
|
-
end
|
25
|
-
|
26
|
-
task :hanna do
|
27
|
-
sh "rm -fr doc"
|
28
|
-
sh "hanna -SN lib/ -m Algorithms"
|
29
|
-
sh "scp -rq doc/* kanwei@rubyforge.org:/var/www/gforge-projects/algorithms"
|
30
|
-
end
|
31
|
-
|
data/algorithms.gemspec
CHANGED
@@ -1,32 +1,36 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
|
-
s.name =
|
5
|
-
s.version = "0.
|
4
|
+
s.name = "algorithms"
|
5
|
+
s.version = "0.4.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Kanwei Li"]
|
9
|
-
s.date =
|
10
|
-
s.description =
|
11
|
-
s.email =
|
12
|
-
s.extensions = ["ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/splaytree_map/extconf.rb"]
|
13
|
-
s.extra_rdoc_files = ["README.markdown", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb"]
|
14
|
-
s.files = ["
|
15
|
-
s.
|
16
|
-
s.homepage = %q{http://rubyforge.org/projects/algorithms/}
|
9
|
+
s.date = "2012-04-19"
|
10
|
+
s.description = "A library of algorithms and data structures (containers)."
|
11
|
+
s.email = "kanwei@gmail.com"
|
12
|
+
s.extensions = ["ext/algorithms/string/extconf.rb", "ext/containers/bst/extconf.rb", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/splaytree_map/extconf.rb"]
|
13
|
+
s.extra_rdoc_files = ["CHANGELOG.markdown", "README.markdown", "ext/algorithms/string/extconf.rb", "ext/algorithms/string/string.c", "ext/containers/bst/bst.c", "ext/containers/bst/extconf.rb", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/algorithms/string.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb"]
|
14
|
+
s.files = ["CHANGELOG.markdown", "Manifest", "README.markdown", "Rakefile", "algorithms.gemspec", "benchmarks/deque.rb", "benchmarks/sorts.rb", "benchmarks/treemaps.rb", "ext/algorithms/string/extconf.rb", "ext/algorithms/string/string.c", "ext/containers/bst/bst.c", "ext/containers/bst/extconf.rb", "ext/containers/deque/deque.c", "ext/containers/deque/extconf.rb", "ext/containers/rbtree_map/extconf.rb", "ext/containers/rbtree_map/rbtree.c", "ext/containers/splaytree_map/extconf.rb", "ext/containers/splaytree_map/splaytree.c", "lib/algorithms.rb", "lib/algorithms/search.rb", "lib/algorithms/sort.rb", "lib/algorithms/string.rb", "lib/containers/deque.rb", "lib/containers/heap.rb", "lib/containers/kd_tree.rb", "lib/containers/priority_queue.rb", "lib/containers/queue.rb", "lib/containers/rb_tree_map.rb", "lib/containers/splay_tree_map.rb", "lib/containers/stack.rb", "lib/containers/suffix_array.rb", "lib/containers/trie.rb", "spec/bst_gc_mark_spec.rb", "spec/bst_spec.rb", "spec/deque_gc_mark_spec.rb", "spec/deque_spec.rb", "spec/heap_spec.rb", "spec/kd_expected_out.txt", "spec/kd_test_in.txt", "spec/kd_tree_spec.rb", "spec/map_gc_mark_spec.rb", "spec/priority_queue_spec.rb", "spec/queue_spec.rb", "spec/rb_tree_map_spec.rb", "spec/search_spec.rb", "spec/sort_spec.rb", "spec/splay_tree_map_spec.rb", "spec/stack_spec.rb", "spec/string_spec.rb", "spec/suffix_array_spec.rb", "spec/trie_spec.rb"]
|
15
|
+
s.homepage = "https://rubygems.org/gems/algorithms"
|
17
16
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Algorithms", "--main", "README.markdown"]
|
18
17
|
s.require_paths = ["lib", "ext"]
|
19
|
-
s.rubyforge_project =
|
20
|
-
s.rubygems_version =
|
21
|
-
s.summary =
|
18
|
+
s.rubyforge_project = "algorithms"
|
19
|
+
s.rubygems_version = "1.8.15"
|
20
|
+
s.summary = "A library of algorithms and data structures (containers)."
|
22
21
|
|
23
22
|
if s.respond_to? :specification_version then
|
24
|
-
|
25
|
-
s.specification_version = 2
|
23
|
+
s.specification_version = 3
|
26
24
|
|
27
|
-
if Gem::Version.new(Gem::
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
27
|
+
s.add_development_dependency(%q<echoe>, [">= 0"])
|
28
28
|
else
|
29
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
30
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
29
31
|
end
|
30
32
|
else
|
33
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
34
|
+
s.add_dependency(%q<echoe>, [">= 0"])
|
31
35
|
end
|
32
36
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
int min(int a, int b, int c) {
|
4
|
+
int min = a;
|
5
|
+
if (b < min)
|
6
|
+
min = b;
|
7
|
+
if( c < min)
|
8
|
+
min = c;
|
9
|
+
return min;
|
10
|
+
}
|
11
|
+
|
12
|
+
int levenshtein_distance(VALUE str1, VALUE str2) {
|
13
|
+
int 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 = malloc(sizeof(int) * (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] = min(
|
44
|
+
d[j * s1_len + (i-1)],
|
45
|
+
d[(j-1) * s1_len + i],
|
46
|
+
d[(j-1) * s1_len + (i-1)]
|
47
|
+
) + 1;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
}
|
51
|
+
i = d[s1_len * s2_len -1];
|
52
|
+
free(d);
|
53
|
+
return i;
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE lev_dist(VALUE self, VALUE str1, VALUE str2) {
|
57
|
+
return INT2FIX(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,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 int 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
|
+
free(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
|
+
}
|
data/lib/algorithms.rb
CHANGED
@@ -43,19 +43,16 @@
|
|
43
43
|
- Shell sort - Algorithms::Sort.shell_sort
|
44
44
|
- Quicksort - Algorithms::Sort.quicksort
|
45
45
|
- Mergesort - Algorithms::Sort.mergesort
|
46
|
+
* String algorithms
|
47
|
+
- Levenshtein distance - Algorithms::String.levenshtein_dist
|
46
48
|
=end
|
47
49
|
|
48
50
|
module Algorithms; end
|
49
51
|
module Containers; end
|
50
52
|
|
51
|
-
begin
|
52
|
-
require 'CBst'
|
53
|
-
Containers::Bst = Containers::CBst
|
54
|
-
rescue LoadError # C Version could not be found
|
55
|
-
end
|
56
|
-
|
57
53
|
require 'algorithms/search'
|
58
54
|
require 'algorithms/sort'
|
55
|
+
require 'algorithms/string'
|
59
56
|
require 'containers/heap'
|
60
57
|
require 'containers/stack'
|
61
58
|
require 'containers/deque'
|
data/lib/containers/heap.rb
CHANGED
@@ -117,6 +117,22 @@ class Containers::Heap
|
|
117
117
|
@next && @next.value
|
118
118
|
end
|
119
119
|
|
120
|
+
# call-seq:
|
121
|
+
# next_key -> key
|
122
|
+
# next_key -> nil
|
123
|
+
#
|
124
|
+
# Returns the key associated with the next item in heap order, but does not remove the value.
|
125
|
+
#
|
126
|
+
# Complexity: O(1)
|
127
|
+
#
|
128
|
+
# minheap = MinHeap.new
|
129
|
+
# minheap.push(1, :a)
|
130
|
+
# minheap.next_key #=> 1
|
131
|
+
#
|
132
|
+
def next_key
|
133
|
+
@next && @next.key
|
134
|
+
end
|
135
|
+
|
120
136
|
# call-seq:
|
121
137
|
# clear -> nil
|
122
138
|
#
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
|
+
# require 'algorithms'
|
3
|
+
#
|
4
|
+
# if defined? Containers::CBst
|
5
|
+
# describe "CBst" do
|
6
|
+
# it "should mark ruby object references" do
|
7
|
+
# anon_key_class = Class.new do
|
8
|
+
# attr :value
|
9
|
+
# def initialize(x); @value = x; end
|
10
|
+
# def <=>(other); value <=> other.value; end
|
11
|
+
# end
|
12
|
+
# anon_val_class = Class.new
|
13
|
+
# @bst = Containers::CBst.new
|
14
|
+
# 100.times { |x| @bst.push(anon_key_class.new(x), anon_val_class.new) }
|
15
|
+
# # Mark and sweep
|
16
|
+
# ObjectSpace.garbage_collect
|
17
|
+
# # Check if any instances were swept
|
18
|
+
# count = 0
|
19
|
+
# ObjectSpace.each_object(anon_key_class) { |x| count += 1 }
|
20
|
+
# count.should eql(100)
|
21
|
+
# ObjectSpace.each_object(anon_val_class) { |x| count += 1 }
|
22
|
+
# count.should eql(200)
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
# end
|
data/spec/bst_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# $: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
|
+
# require "algorithms"
|
3
|
+
#
|
4
|
+
# begin
|
5
|
+
# Containers::CBst
|
6
|
+
# describe "binary search tree" do
|
7
|
+
# it "should let user push new elements with key" do
|
8
|
+
# @bst = Containers::CBst.new
|
9
|
+
# 100.times { |x| @bst.push(x, "hello : #{x}") }
|
10
|
+
# @bst.size.should eql(100)
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# it "should allow users to delete elements" do
|
14
|
+
# @bst = Containers::CBst.new
|
15
|
+
# @bst.push(10, "hello world")
|
16
|
+
# @bst.push(11, "hello world")
|
17
|
+
# @bst.delete(11)
|
18
|
+
# @bst.size.should eql(1)
|
19
|
+
# @bst.delete(10)
|
20
|
+
# @bst.size.should eql(0)
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# end
|
24
|
+
# rescue Exception
|
25
|
+
# end
|
data/spec/deque_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
2
|
require 'algorithms'
|
3
3
|
|
4
|
-
|
4
|
+
shared_examples "(empty deque)" do
|
5
5
|
it "should return nil when popping objects" do
|
6
6
|
@deque.pop_front.should be_nil
|
7
7
|
@deque.pop_back.should be_nil
|
@@ -31,7 +31,7 @@ describe "(empty deque)", :shared => true do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
shared_examples "(non-empty deque)" do
|
35
35
|
before(:each) do
|
36
36
|
@deque.push_back(10)
|
37
37
|
@deque.push_back("10")
|
data/spec/heap_spec.rb
CHANGED
@@ -46,6 +46,11 @@ describe Containers::Heap do
|
|
46
46
|
@heap.size.should eql(@num_items)
|
47
47
|
end
|
48
48
|
|
49
|
+
it "should have a next value" do
|
50
|
+
@heap.next.should be_true
|
51
|
+
@heap.next_key.should be_true
|
52
|
+
end
|
53
|
+
|
49
54
|
it "should delete random keys" do
|
50
55
|
@heap.delete(@random_array[0]).should eql(@random_array[0])
|
51
56
|
@heap.delete(@random_array[1]).should eql(@random_array[1])
|
data/spec/rb_tree_map_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
2
|
require 'algorithms'
|
3
3
|
|
4
|
-
|
4
|
+
shared_examples "empty rbtree" do
|
5
5
|
it "should let you push stuff in" do
|
6
6
|
100.times { |x| @tree[x] = x }
|
7
7
|
@tree.size.should eql(100)
|
@@ -31,7 +31,7 @@ describe "empty rbtree", :shared => true do
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
|
34
|
+
shared_examples "non-empty rbtree" do
|
35
35
|
before(:each) do
|
36
36
|
@num_items = 1000
|
37
37
|
@random_array = Array.new(@num_items) { rand(@num_items) }
|
data/spec/splay_tree_map_spec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
2
|
require 'algorithms'
|
3
3
|
|
4
|
-
|
4
|
+
shared_examples "empty splaytree" do
|
5
5
|
it "should let you push stuff in" do
|
6
6
|
100.times { |x| @tree[x] = x }
|
7
7
|
@tree.size.should eql(100)
|
@@ -25,7 +25,7 @@ describe "empty splaytree", :shared => true do
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
|
28
|
+
shared_examples "non-empty splaytree" do
|
29
29
|
before(:each) do
|
30
30
|
@num_items = 100
|
31
31
|
@random_array = []
|
data/spec/string_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
$: << File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib')
|
2
|
+
require 'algorithms'
|
3
|
+
|
4
|
+
describe "string algorithms" do
|
5
|
+
it "should do levenshtein distance" do
|
6
|
+
Algorithms::String.levenshtein_dist("Hello", "Hel").should eql(2)
|
7
|
+
Algorithms::String.levenshtein_dist("Hello", "").should eql(5)
|
8
|
+
Algorithms::String.levenshtein_dist("", "Hello").should eql(5)
|
9
|
+
Algorithms::String.levenshtein_dist("Hello", "Hello").should eql(0)
|
10
|
+
Algorithms::String.levenshtein_dist("Hello", "ello").should eql(1)
|
11
|
+
Algorithms::String.levenshtein_dist("Hello", "Mello").should eql(1)
|
12
|
+
end
|
13
|
+
end
|
metadata
CHANGED
@@ -1,28 +1,54 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: algorithms
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.4.0
|
5
|
+
prerelease:
|
5
6
|
platform: ruby
|
6
|
-
authors:
|
7
|
+
authors:
|
7
8
|
- Kanwei Li
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
date: 2012-04-19 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &70335276597400 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70335276597400
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: echoe
|
27
|
+
requirement: &70335276596820 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70335276596820
|
36
|
+
description: A library of algorithms and data structures (containers).
|
17
37
|
email: kanwei@gmail.com
|
18
38
|
executables: []
|
19
|
-
|
20
|
-
|
39
|
+
extensions:
|
40
|
+
- ext/algorithms/string/extconf.rb
|
41
|
+
- ext/containers/bst/extconf.rb
|
21
42
|
- ext/containers/deque/extconf.rb
|
22
43
|
- ext/containers/rbtree_map/extconf.rb
|
23
44
|
- ext/containers/splaytree_map/extconf.rb
|
24
|
-
extra_rdoc_files:
|
45
|
+
extra_rdoc_files:
|
46
|
+
- CHANGELOG.markdown
|
25
47
|
- README.markdown
|
48
|
+
- ext/algorithms/string/extconf.rb
|
49
|
+
- ext/algorithms/string/string.c
|
50
|
+
- ext/containers/bst/bst.c
|
51
|
+
- ext/containers/bst/extconf.rb
|
26
52
|
- ext/containers/deque/deque.c
|
27
53
|
- ext/containers/deque/extconf.rb
|
28
54
|
- ext/containers/rbtree_map/extconf.rb
|
@@ -32,6 +58,7 @@ extra_rdoc_files:
|
|
32
58
|
- lib/algorithms.rb
|
33
59
|
- lib/algorithms/search.rb
|
34
60
|
- lib/algorithms/sort.rb
|
61
|
+
- lib/algorithms/string.rb
|
35
62
|
- lib/containers/deque.rb
|
36
63
|
- lib/containers/heap.rb
|
37
64
|
- lib/containers/kd_tree.rb
|
@@ -42,8 +69,8 @@ extra_rdoc_files:
|
|
42
69
|
- lib/containers/stack.rb
|
43
70
|
- lib/containers/suffix_array.rb
|
44
71
|
- lib/containers/trie.rb
|
45
|
-
files:
|
46
|
-
-
|
72
|
+
files:
|
73
|
+
- CHANGELOG.markdown
|
47
74
|
- Manifest
|
48
75
|
- README.markdown
|
49
76
|
- Rakefile
|
@@ -51,6 +78,10 @@ files:
|
|
51
78
|
- benchmarks/deque.rb
|
52
79
|
- benchmarks/sorts.rb
|
53
80
|
- benchmarks/treemaps.rb
|
81
|
+
- ext/algorithms/string/extconf.rb
|
82
|
+
- ext/algorithms/string/string.c
|
83
|
+
- ext/containers/bst/bst.c
|
84
|
+
- ext/containers/bst/extconf.rb
|
54
85
|
- ext/containers/deque/deque.c
|
55
86
|
- ext/containers/deque/extconf.rb
|
56
87
|
- ext/containers/rbtree_map/extconf.rb
|
@@ -60,6 +91,7 @@ files:
|
|
60
91
|
- lib/algorithms.rb
|
61
92
|
- lib/algorithms/search.rb
|
62
93
|
- lib/algorithms/sort.rb
|
94
|
+
- lib/algorithms/string.rb
|
63
95
|
- lib/containers/deque.rb
|
64
96
|
- lib/containers/heap.rb
|
65
97
|
- lib/containers/kd_tree.rb
|
@@ -70,6 +102,8 @@ files:
|
|
70
102
|
- lib/containers/stack.rb
|
71
103
|
- lib/containers/suffix_array.rb
|
72
104
|
- lib/containers/trie.rb
|
105
|
+
- spec/bst_gc_mark_spec.rb
|
106
|
+
- spec/bst_spec.rb
|
73
107
|
- spec/deque_gc_mark_spec.rb
|
74
108
|
- spec/deque_spec.rb
|
75
109
|
- spec/heap_spec.rb
|
@@ -84,39 +118,38 @@ files:
|
|
84
118
|
- spec/sort_spec.rb
|
85
119
|
- spec/splay_tree_map_spec.rb
|
86
120
|
- spec/stack_spec.rb
|
121
|
+
- spec/string_spec.rb
|
87
122
|
- spec/suffix_array_spec.rb
|
88
123
|
- spec/trie_spec.rb
|
89
|
-
|
90
|
-
|
124
|
+
homepage: https://rubygems.org/gems/algorithms
|
125
|
+
licenses: []
|
91
126
|
post_install_message:
|
92
|
-
rdoc_options:
|
127
|
+
rdoc_options:
|
93
128
|
- --line-numbers
|
94
129
|
- --inline-source
|
95
130
|
- --title
|
96
131
|
- Algorithms
|
97
132
|
- --main
|
98
133
|
- README.markdown
|
99
|
-
require_paths:
|
134
|
+
require_paths:
|
100
135
|
- lib
|
101
136
|
- ext
|
102
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
138
|
+
none: false
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
|
+
none: false
|
145
|
+
requirements:
|
146
|
+
- - ! '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '1.2'
|
114
149
|
requirements: []
|
115
|
-
|
116
150
|
rubyforge_project: algorithms
|
117
|
-
rubygems_version: 1.
|
151
|
+
rubygems_version: 1.8.15
|
118
152
|
signing_key:
|
119
|
-
specification_version:
|
120
|
-
summary: A library of algorithms and containers.
|
153
|
+
specification_version: 3
|
154
|
+
summary: A library of algorithms and data structures (containers).
|
121
155
|
test_files: []
|
122
|
-
|