algorithms 0.6.1-java
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.
- data/CHANGELOG.markdown +193 -0
- data/Gemfile +9 -0
- data/Manifest +51 -0
- data/README.markdown +84 -0
- data/Rakefile +18 -0
- data/algorithms.gemspec +23 -0
- data/benchmarks/deque.rb +17 -0
- data/benchmarks/sorts.rb +34 -0
- data/benchmarks/treemaps.rb +51 -0
- 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/ext/containers/deque/deque.c +247 -0
- data/ext/containers/deque/extconf.rb +4 -0
- data/ext/containers/rbtree_map/extconf.rb +4 -0
- data/ext/containers/rbtree_map/rbtree.c +498 -0
- data/ext/containers/splaytree_map/extconf.rb +4 -0
- data/ext/containers/splaytree_map/splaytree.c +419 -0
- data/lib/algorithms.rb +65 -0
- data/lib/algorithms/search.rb +84 -0
- data/lib/algorithms/sort.rb +238 -0
- data/lib/algorithms/string.rb +9 -0
- data/lib/containers/deque.rb +171 -0
- data/lib/containers/heap.rb +502 -0
- data/lib/containers/kd_tree.rb +110 -0
- data/lib/containers/priority_queue.rb +113 -0
- data/lib/containers/queue.rb +68 -0
- data/lib/containers/rb_tree_map.rb +398 -0
- data/lib/containers/splay_tree_map.rb +269 -0
- data/lib/containers/stack.rb +67 -0
- data/lib/containers/suffix_array.rb +68 -0
- data/lib/containers/trie.rb +182 -0
- data/spec/bst_gc_mark_spec.rb +25 -0
- data/spec/bst_spec.rb +25 -0
- data/spec/deque_gc_mark_spec.rb +18 -0
- data/spec/deque_spec.rb +108 -0
- data/spec/heap_spec.rb +131 -0
- data/spec/kd_expected_out.txt +10000 -0
- data/spec/kd_test_in.txt +10000 -0
- data/spec/kd_tree_spec.rb +34 -0
- data/spec/map_gc_mark_spec.rb +29 -0
- data/spec/priority_queue_spec.rb +75 -0
- data/spec/queue_spec.rb +61 -0
- data/spec/rb_tree_map_spec.rb +123 -0
- data/spec/search_spec.rb +28 -0
- data/spec/sort_spec.rb +28 -0
- data/spec/splay_tree_map_spec.rb +106 -0
- data/spec/stack_spec.rb +60 -0
- data/spec/string_spec.rb +15 -0
- data/spec/suffix_array_spec.rb +40 -0
- data/spec/trie_spec.rb +59 -0
- metadata +106 -0
@@ -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 = malloc(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
|
+
free(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,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
|
+
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
|
+
}
|
@@ -0,0 +1,247 @@
|
|
1
|
+
#include "ruby.h"
|
2
|
+
|
3
|
+
#define FALSE 0
|
4
|
+
#define TRUE 1
|
5
|
+
|
6
|
+
typedef struct struct_deque_node {
|
7
|
+
VALUE obj;
|
8
|
+
struct struct_deque_node *left;
|
9
|
+
struct struct_deque_node *right;
|
10
|
+
} deque_node;
|
11
|
+
|
12
|
+
typedef struct {
|
13
|
+
unsigned int size;
|
14
|
+
deque_node *front;
|
15
|
+
deque_node *back;
|
16
|
+
} deque;
|
17
|
+
|
18
|
+
void free_nodes(deque_node *node) {
|
19
|
+
deque_node *next;
|
20
|
+
while(node) {
|
21
|
+
next = node->right;
|
22
|
+
free(node);
|
23
|
+
node = next;
|
24
|
+
}
|
25
|
+
return;
|
26
|
+
}
|
27
|
+
|
28
|
+
void clear_deque(deque *a_deque) {
|
29
|
+
if(a_deque->front)
|
30
|
+
free_nodes(a_deque->front);
|
31
|
+
a_deque->size = 0;
|
32
|
+
a_deque->front = NULL;
|
33
|
+
a_deque->back = NULL;
|
34
|
+
return;
|
35
|
+
}
|
36
|
+
|
37
|
+
static deque* get_deque_from_self(VALUE self) {
|
38
|
+
deque *a_deque;
|
39
|
+
Data_Get_Struct(self, deque, a_deque);
|
40
|
+
return a_deque;
|
41
|
+
}
|
42
|
+
|
43
|
+
static deque* create_deque() {
|
44
|
+
deque *a_deque = ALLOC(deque);
|
45
|
+
a_deque->size = 0;
|
46
|
+
a_deque->front = NULL;
|
47
|
+
a_deque->back = NULL;
|
48
|
+
return a_deque;
|
49
|
+
}
|
50
|
+
|
51
|
+
static deque_node* create_node(VALUE obj) {
|
52
|
+
deque_node *node = ALLOC(deque_node);
|
53
|
+
node->obj = obj;
|
54
|
+
node->left = NULL;
|
55
|
+
node->right = NULL;
|
56
|
+
return node;
|
57
|
+
}
|
58
|
+
|
59
|
+
static void deque_mark(void *ptr) {
|
60
|
+
if (ptr) {
|
61
|
+
deque *deque = ptr;
|
62
|
+
deque_node *node = deque->front;
|
63
|
+
while(node) {
|
64
|
+
rb_gc_mark(node->obj);
|
65
|
+
node = node->right;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
static void deque_free(void *ptr) {
|
71
|
+
if (ptr) {
|
72
|
+
deque *deque = ptr;
|
73
|
+
free_nodes(deque->front);
|
74
|
+
free(deque);
|
75
|
+
}
|
76
|
+
}
|
77
|
+
|
78
|
+
static VALUE deque_alloc(VALUE klass) {
|
79
|
+
deque *deque = create_deque();
|
80
|
+
return Data_Wrap_Struct(klass, deque_mark, deque_free, deque);
|
81
|
+
}
|
82
|
+
|
83
|
+
static VALUE deque_push_front(VALUE self, VALUE obj) {
|
84
|
+
deque *deque = get_deque_from_self(self);
|
85
|
+
deque_node *node = create_node(obj);
|
86
|
+
if(deque->front) {
|
87
|
+
node->right = deque->front;
|
88
|
+
deque->front->left = node;
|
89
|
+
deque->front = node;
|
90
|
+
}
|
91
|
+
else {
|
92
|
+
deque->front = node;
|
93
|
+
deque->back = node;
|
94
|
+
}
|
95
|
+
deque->size++;
|
96
|
+
return obj;
|
97
|
+
}
|
98
|
+
|
99
|
+
static VALUE deque_push_back(VALUE self, VALUE obj) {
|
100
|
+
deque *deque = get_deque_from_self(self);
|
101
|
+
deque_node *node = create_node(obj);
|
102
|
+
if(deque->back) {
|
103
|
+
node->left = deque->back;
|
104
|
+
deque->back->right = node;
|
105
|
+
deque->back = node;
|
106
|
+
}
|
107
|
+
else {
|
108
|
+
deque->front = node;
|
109
|
+
deque->back = node;
|
110
|
+
}
|
111
|
+
deque->size++;
|
112
|
+
return obj;
|
113
|
+
}
|
114
|
+
|
115
|
+
static VALUE deque_pop_front(VALUE self) {
|
116
|
+
deque *deque = get_deque_from_self(self);
|
117
|
+
VALUE obj;
|
118
|
+
if(!deque->front)
|
119
|
+
return Qnil;
|
120
|
+
deque_node *node = deque->front;
|
121
|
+
obj = node->obj;
|
122
|
+
if(deque->size == 1) {
|
123
|
+
clear_deque(deque);
|
124
|
+
return obj;
|
125
|
+
}
|
126
|
+
deque->front->right->left = NULL;
|
127
|
+
deque->front = deque->front->right;
|
128
|
+
deque->size--;
|
129
|
+
return obj;
|
130
|
+
}
|
131
|
+
|
132
|
+
static VALUE deque_front(VALUE self) {
|
133
|
+
deque *deque = get_deque_from_self(self);
|
134
|
+
if(deque->front)
|
135
|
+
return deque->front->obj;
|
136
|
+
|
137
|
+
return Qnil;
|
138
|
+
}
|
139
|
+
|
140
|
+
static VALUE deque_back(VALUE self) {
|
141
|
+
deque *deque = get_deque_from_self(self);
|
142
|
+
if(deque->back)
|
143
|
+
return deque->back->obj;
|
144
|
+
|
145
|
+
return Qnil;
|
146
|
+
}
|
147
|
+
|
148
|
+
static VALUE deque_pop_back(VALUE self) {
|
149
|
+
deque *deque = get_deque_from_self(self);
|
150
|
+
VALUE obj;
|
151
|
+
if(!deque->back)
|
152
|
+
return Qnil;
|
153
|
+
deque_node *node = deque->back;
|
154
|
+
obj = node->obj;
|
155
|
+
if(deque->size == 1) {
|
156
|
+
clear_deque(deque);
|
157
|
+
return obj;
|
158
|
+
}
|
159
|
+
deque->back->left->right = NULL;
|
160
|
+
deque->back = deque->back->left;
|
161
|
+
deque->size--;
|
162
|
+
return obj;
|
163
|
+
}
|
164
|
+
|
165
|
+
static VALUE deque_clear(VALUE self) {
|
166
|
+
deque *deque = get_deque_from_self(self);
|
167
|
+
clear_deque(deque);
|
168
|
+
return Qnil;
|
169
|
+
}
|
170
|
+
|
171
|
+
static VALUE deque_size(VALUE self) {
|
172
|
+
deque *deque = get_deque_from_self(self);
|
173
|
+
return INT2NUM(deque->size);
|
174
|
+
}
|
175
|
+
|
176
|
+
static VALUE deque_is_empty(VALUE self) {
|
177
|
+
deque *deque = get_deque_from_self(self);
|
178
|
+
return (deque->size == 0) ? Qtrue : Qfalse;
|
179
|
+
}
|
180
|
+
|
181
|
+
static VALUE deque_each_forward(VALUE self) {
|
182
|
+
deque *deque = get_deque_from_self(self);
|
183
|
+
deque_node *node = deque->front;
|
184
|
+
while(node) {
|
185
|
+
rb_yield(node->obj);
|
186
|
+
node = node->right;
|
187
|
+
}
|
188
|
+
return self;
|
189
|
+
}
|
190
|
+
|
191
|
+
static VALUE deque_each_backward(VALUE self) {
|
192
|
+
deque *deque = get_deque_from_self(self);
|
193
|
+
deque_node *node = deque->back;
|
194
|
+
while(node) {
|
195
|
+
rb_yield(node->obj);
|
196
|
+
node = node->left;
|
197
|
+
}
|
198
|
+
return self;
|
199
|
+
}
|
200
|
+
|
201
|
+
static VALUE deque_init(int argc, VALUE *argv, VALUE self)
|
202
|
+
{
|
203
|
+
long len, i;
|
204
|
+
VALUE ary;
|
205
|
+
|
206
|
+
if(argc == 0) {
|
207
|
+
return self;
|
208
|
+
}
|
209
|
+
else if(argc > 1) {
|
210
|
+
rb_raise(rb_eArgError, "wrong number of arguments");
|
211
|
+
}
|
212
|
+
else {
|
213
|
+
ary = rb_check_array_type(argv[0]);
|
214
|
+
if(!NIL_P(ary)) {
|
215
|
+
len = RARRAY_LEN(ary);
|
216
|
+
for (i = 0; i < len; i++) {
|
217
|
+
deque_push_back(self, RARRAY_PTR(ary)[i]);
|
218
|
+
}
|
219
|
+
}
|
220
|
+
}
|
221
|
+
return self;
|
222
|
+
}
|
223
|
+
|
224
|
+
static VALUE cDeque;
|
225
|
+
static VALUE mContainers;
|
226
|
+
|
227
|
+
void Init_CDeque() {
|
228
|
+
mContainers = rb_define_module("Containers");
|
229
|
+
cDeque = rb_define_class_under(mContainers, "CDeque", rb_cObject);
|
230
|
+
rb_define_alloc_func(cDeque, deque_alloc);
|
231
|
+
rb_define_method(cDeque, "initialize", deque_init, -1);
|
232
|
+
rb_define_method(cDeque, "push_front", deque_push_front, 1);
|
233
|
+
rb_define_method(cDeque, "push_back", deque_push_back, 1);
|
234
|
+
rb_define_method(cDeque, "clear", deque_clear, 0);
|
235
|
+
rb_define_method(cDeque, "front", deque_front, 0);
|
236
|
+
rb_define_method(cDeque, "back", deque_back, 0);
|
237
|
+
rb_define_method(cDeque, "pop_front", deque_pop_front, 0);
|
238
|
+
rb_define_method(cDeque, "pop_back", deque_pop_back, 0);
|
239
|
+
rb_define_method(cDeque, "size", deque_size, 0);
|
240
|
+
rb_define_alias(cDeque, "length", "size");
|
241
|
+
rb_define_method(cDeque, "empty?", deque_is_empty, 0);
|
242
|
+
rb_define_method(cDeque, "each_forward", deque_each_forward, 0);
|
243
|
+
rb_define_method(cDeque, "each_backward", deque_each_backward, 0);
|
244
|
+
rb_define_alias(cDeque, "each", "each_forward");
|
245
|
+
rb_define_alias(cDeque, "reverse_each", "each_backward");
|
246
|
+
rb_include_module(cDeque, rb_eval_string("Enumerable"));
|
247
|
+
}
|