ds 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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +13 -0
- data/doc/Array.html +264 -0
- data/doc/DS.html +292 -0
- data/doc/DS/Array2D.html +345 -0
- data/doc/DS/BinaryHeap.html +493 -0
- data/doc/DS/BinarySearchTree.html +313 -0
- data/doc/DS/BinaryTree.html +433 -0
- data/doc/DS/CompleteBinaryTree.html +550 -0
- data/doc/DS/CyclicList.html +234 -0
- data/doc/DS/Digraph.html +299 -0
- data/doc/DS/Edge.html +283 -0
- data/doc/DS/ExpandableArray.html +316 -0
- data/doc/DS/Graph.html +739 -0
- data/doc/DS/GraphAsList.html +361 -0
- data/doc/DS/GraphAsMatrix.html +633 -0
- data/doc/DS/GraphAsTriMatrix.html +274 -0
- data/doc/DS/List.html +1263 -0
- data/doc/DS/ListElement.html +344 -0
- data/doc/DS/Queue.html +517 -0
- data/doc/DS/Ring.html +323 -0
- data/doc/DS/Stack.html +407 -0
- data/doc/DS/Tree.html +770 -0
- data/doc/DS/TreeWalker.html +561 -0
- data/doc/DS/TriMatrix.html +338 -0
- data/doc/created.rid +25 -0
- data/doc/ds/graphs/digraph_rb.html +52 -0
- data/doc/ds/graphs/edge_rb.html +52 -0
- data/doc/ds/graphs/graph_as_list_rb.html +52 -0
- data/doc/ds/graphs/graph_as_matrix_rb.html +52 -0
- data/doc/ds/graphs/graph_as_tri_matrix_rb.html +52 -0
- data/doc/ds/graphs/graph_rb.html +52 -0
- data/doc/ds/lists/cyclic_list_rb.html +52 -0
- data/doc/ds/lists/list_element_rb.html +52 -0
- data/doc/ds/lists/list_rb.html +52 -0
- data/doc/ds/lists/ring_rb.html +52 -0
- data/doc/ds/matrixes/array_2d_rb.html +52 -0
- data/doc/ds/matrixes/expandable_array_rb.html +52 -0
- data/doc/ds/matrixes/tri_matrix_rb.html +52 -0
- data/doc/ds/queues/queue_rb.html +52 -0
- data/doc/ds/stacks/stack_rb.html +52 -0
- data/doc/ds/trees/binary_heap_rb.html +52 -0
- data/doc/ds/trees/binary_search_tree_rb.html +52 -0
- data/doc/ds/trees/binary_tree_rb.html +52 -0
- data/doc/ds/trees/complete_binary_tree_rb.html +52 -0
- data/doc/ds/trees/tree_rb.html +52 -0
- data/doc/ds/trees/tree_walker_rb.html +52 -0
- data/doc/ds/version_rb.html +52 -0
- data/doc/ds_rb.html +98 -0
- data/doc/ext/ext_rb.html +52 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +375 -0
- data/doc/js/darkfish.js +116 -0
- data/doc/js/jquery.js +32 -0
- data/doc/js/quicksearch.js +114 -0
- data/doc/js/thickbox-compressed.js +10 -0
- data/doc/rdoc.css +763 -0
- data/ds.gemspec +20 -0
- data/lib/ds.rb +38 -0
- data/lib/ds/graphs/digraph.rb +20 -0
- data/lib/ds/graphs/edge.rb +15 -0
- data/lib/ds/graphs/graph.rb +107 -0
- data/lib/ds/graphs/graph_as_list.rb +48 -0
- data/lib/ds/graphs/graph_as_matrix.rb +114 -0
- data/lib/ds/graphs/graph_as_tri_matrix.rb +25 -0
- data/lib/ds/lists/cyclic_list.rb +21 -0
- data/lib/ds/lists/list.rb +303 -0
- data/lib/ds/lists/list_element.rb +26 -0
- data/lib/ds/lists/ring.rb +42 -0
- data/lib/ds/matrixes/array_2d.rb +35 -0
- data/lib/ds/matrixes/expandable_array.rb +37 -0
- data/lib/ds/matrixes/tri_matrix.rb +30 -0
- data/lib/ds/queues/queue.rb +53 -0
- data/lib/ds/stacks/stack.rb +39 -0
- data/lib/ds/trees/binary_heap.rb +71 -0
- data/lib/ds/trees/binary_search_tree.rb +32 -0
- data/lib/ds/trees/binary_tree.rb +65 -0
- data/lib/ds/trees/complete_binary_tree.rb +52 -0
- data/lib/ds/trees/tree.rb +117 -0
- data/lib/ds/trees/tree_walker.rb +179 -0
- data/lib/ds/version.rb +3 -0
- data/lib/ext/ext.rb +15 -0
- data/test/help.rb +8 -0
- data/test/test_array2d.rb +51 -0
- data/test/test_binary_heap.rb +35 -0
- data/test/test_binary_search_tree.rb +32 -0
- data/test/test_binary_tree.rb +51 -0
- data/test/test_complete_binary_tree.rb +30 -0
- data/test/test_digraph.rb +134 -0
- data/test/test_expandable_array.rb +26 -0
- data/test/test_graph.rb +71 -0
- data/test/test_list.rb +138 -0
- data/test/test_list_element.rb +56 -0
- data/test/test_queue.rb +110 -0
- data/test/test_ring.rb +28 -0
- data/test/test_stack.rb +87 -0
- data/test/test_tree.rb +48 -0
- data/test/test_tree_walker.rb +69 -0
- data/test/test_tri_matrix.rb +22 -0
- metadata +184 -0
data/ds.gemspec
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
|
3
|
+
require "ds/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |s|
|
|
6
|
+
s.name = "ds"
|
|
7
|
+
s.version = DS::VERSION
|
|
8
|
+
s.authors = ["knife"]
|
|
9
|
+
s.email = ["satre@o2.pl"]
|
|
10
|
+
s.homepage = ""
|
|
11
|
+
s.summary = %q{Some common data structures.}
|
|
12
|
+
s.description = %q{Data structures (lists,stacks, trees, heaps, graphs..) in pure Ruby.}
|
|
13
|
+
|
|
14
|
+
s.rubyforge_project = "ds"
|
|
15
|
+
|
|
16
|
+
s.files = `git ls-files`.split("\n")
|
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
|
19
|
+
s.require_paths = ["lib"]
|
|
20
|
+
end
|
data/lib/ds.rb
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
require "ds/version"
|
|
2
|
+
|
|
3
|
+
require "ext/ext"
|
|
4
|
+
|
|
5
|
+
require "ds/matrixes/expandable_array"
|
|
6
|
+
require "ds/matrixes/array_2d"
|
|
7
|
+
require "ds/matrixes/tri_matrix"
|
|
8
|
+
|
|
9
|
+
require "ds/graphs/edge"
|
|
10
|
+
require "ds/graphs/graph_as_list"
|
|
11
|
+
require "ds/graphs/graph_as_matrix"
|
|
12
|
+
require "ds/graphs/graph_as_tri_matrix"
|
|
13
|
+
require "ds/graphs/graph"
|
|
14
|
+
require "ds/graphs/digraph"
|
|
15
|
+
|
|
16
|
+
require "ds/trees/tree"
|
|
17
|
+
require "ds/trees/tree_walker"
|
|
18
|
+
require "ds/trees/binary_tree"
|
|
19
|
+
require "ds/trees/binary_search_tree"
|
|
20
|
+
require "ds/trees/complete_binary_tree"
|
|
21
|
+
require "ds/trees/binary_heap"
|
|
22
|
+
|
|
23
|
+
require "ds/lists/list_element"
|
|
24
|
+
require "ds/lists/list"
|
|
25
|
+
require "ds/lists/cyclic_list"
|
|
26
|
+
require "ds/lists/ring"
|
|
27
|
+
|
|
28
|
+
require "ds/stacks/stack"
|
|
29
|
+
require "ds/queues/queue"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
class Digraph < Graph
|
|
3
|
+
|
|
4
|
+
def self.create(args)
|
|
5
|
+
new(args,:matrix)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
#Returns number of incoming edges to given vertex.
|
|
10
|
+
def in_degree x
|
|
11
|
+
@g.degree x, :in
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
#Returns number of outcoming edges to given vertex.
|
|
15
|
+
def out_degree x
|
|
16
|
+
@g.degree x, :out
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
class Graph
|
|
3
|
+
|
|
4
|
+
Infinity = 1 << 64
|
|
5
|
+
|
|
6
|
+
#Create new graph from array of edges. Second parameter determines
|
|
7
|
+
#graph internal implementation: :list (Adjency List), :tri_matrix (Triangular
|
|
8
|
+
#Matrix), :matrix (Matrix).
|
|
9
|
+
def initialize(edges,store = :list)
|
|
10
|
+
case store
|
|
11
|
+
when :matrix
|
|
12
|
+
@g = GraphAsMatrix.new(edges)
|
|
13
|
+
when :tri_matrix
|
|
14
|
+
@g = GraphAsTriMatrix.new(edges)
|
|
15
|
+
else
|
|
16
|
+
@g = GraphAsList.new(edges)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
#Create new graph from array of edges. Internally graph will be represented
|
|
21
|
+
#by Triangular Matrix.
|
|
22
|
+
def self.create(edges)
|
|
23
|
+
new(edges,:tri_matrix)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def add(x,y)
|
|
27
|
+
@g.add(x,y)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def remove(x,y)
|
|
31
|
+
@g.remove(x,y)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def each_vertex &block
|
|
35
|
+
@g.each_vertex &block
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def each_edge &block
|
|
39
|
+
@g.each_edge &block
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def neighbors v
|
|
43
|
+
@g.neighbors v
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def bfs s
|
|
47
|
+
colors = {}
|
|
48
|
+
parents = {}
|
|
49
|
+
res = []
|
|
50
|
+
d = {}
|
|
51
|
+
q = Queue.new
|
|
52
|
+
|
|
53
|
+
@g.each_vertex do |v|
|
|
54
|
+
colors[v] = :white
|
|
55
|
+
parents[v] = nil
|
|
56
|
+
d[v] = Infinity
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
colors[s] = :white
|
|
60
|
+
parents[s] = nil
|
|
61
|
+
d[s] = 0
|
|
62
|
+
|
|
63
|
+
q.enqueue s
|
|
64
|
+
|
|
65
|
+
while !q.empty?
|
|
66
|
+
u = q.dequeue
|
|
67
|
+
@g.neighbors(u).each do |v|
|
|
68
|
+
if colors[v] === :white
|
|
69
|
+
colors[v] = :grey
|
|
70
|
+
d[v] = d[u] + 1
|
|
71
|
+
parents[v] = u
|
|
72
|
+
q.enqueue v
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
colors[u] = :black
|
|
76
|
+
res << u
|
|
77
|
+
end
|
|
78
|
+
res
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def add_edges(edges)
|
|
82
|
+
@g.add_edges(edges)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
#Returns vertex degree. Second parameter determines direction - :in incoming
|
|
86
|
+
#edges, :out - outcoming edges, :all - incoming and outcoming edges.
|
|
87
|
+
def degree x
|
|
88
|
+
@g.degree x
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def edge? x,y
|
|
92
|
+
@g.edge? x,y
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def get_edge x, y
|
|
96
|
+
@g.get_edge x,y
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def vertex_size
|
|
100
|
+
@g.vertex_size
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def edge_size
|
|
104
|
+
@g.vmax+1
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
class GraphAsList
|
|
3
|
+
|
|
4
|
+
def initialize
|
|
5
|
+
@store = {} # the graph // {node => { edge1 => weight, edge2 => weight}, node2 => ...
|
|
6
|
+
@nodes = Array.new
|
|
7
|
+
@INFINITY = 1 << 64
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def add_edge(x,y,w=nil) # s= source, t= target, w= weight
|
|
11
|
+
if (not @store.has_key?(x))
|
|
12
|
+
@store[x] = {y=>w}
|
|
13
|
+
else
|
|
14
|
+
@store[x][y] = w
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Begin code for non directed graph (inserts the other edge too)
|
|
18
|
+
|
|
19
|
+
if (not @store.has_key?(y))
|
|
20
|
+
@store[y] = {x=>w}
|
|
21
|
+
else
|
|
22
|
+
@store[y][x] = w
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# End code for non directed graph (ie. deleteme if you want it directed)
|
|
26
|
+
|
|
27
|
+
if (not @nodes.include?(x))
|
|
28
|
+
@nodes << x
|
|
29
|
+
end
|
|
30
|
+
if (not @nodes.include?(y))
|
|
31
|
+
@nodes << y
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def add_edges(edges)
|
|
36
|
+
for e in edges
|
|
37
|
+
add(e.from,e.to)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def each_vertex
|
|
42
|
+
@adj_matrix.keys.each do |vertex|
|
|
43
|
+
yield vertex
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
class GraphAsMatrix
|
|
3
|
+
|
|
4
|
+
def initialize(edges)
|
|
5
|
+
@store = Array2D.new
|
|
6
|
+
@max = 0
|
|
7
|
+
|
|
8
|
+
@v = 0 #vertex count
|
|
9
|
+
|
|
10
|
+
@map = [] #maps objects to matrix indexes.
|
|
11
|
+
|
|
12
|
+
add_edges(edges)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
#Checks if two elements are connected.
|
|
16
|
+
def edge? x,y
|
|
17
|
+
v1 = @map.index(x)
|
|
18
|
+
v2 = @map.index(y)
|
|
19
|
+
@store[v1,v2] > 0
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
#Adds new edges to graph.
|
|
23
|
+
def add_edges(edges)
|
|
24
|
+
for e in edges
|
|
25
|
+
x = @map.push_uniq e.from
|
|
26
|
+
y = @map.push_uniq e.to
|
|
27
|
+
|
|
28
|
+
@store[x,y] = e.weight
|
|
29
|
+
@max = [@max, x, y].max
|
|
30
|
+
@v = @v + 1
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#Returns all neighbors for given vertex.
|
|
35
|
+
def neighbors(v)
|
|
36
|
+
n = []
|
|
37
|
+
v = @map.index(v)
|
|
38
|
+
0.upto @max do |i|
|
|
39
|
+
n << @map[i] if @store[v,i] > 0
|
|
40
|
+
end
|
|
41
|
+
n
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
#Removes conection between vertex x and y.
|
|
45
|
+
def remove(x,y)
|
|
46
|
+
v1 = @map.index(x)
|
|
47
|
+
v2 = @map.index(y)
|
|
48
|
+
|
|
49
|
+
@store[v1,v2] = 0
|
|
50
|
+
if (degree @map[@max]) == 0
|
|
51
|
+
@max -= 1
|
|
52
|
+
end
|
|
53
|
+
@v -= 1
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
#Returns Edge(x,y) if exist.
|
|
57
|
+
def get_edge x,y
|
|
58
|
+
s = @map.index x
|
|
59
|
+
t = @map.index y
|
|
60
|
+
if @store[s,t] > 0
|
|
61
|
+
Edge.new(@map[s], @map[t], @store[s,t])
|
|
62
|
+
else
|
|
63
|
+
nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def vmax
|
|
68
|
+
@max
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#Returns vertex counter.
|
|
72
|
+
def vertex_size
|
|
73
|
+
@v
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
#Returns vertex degree. Second parameter determines direction - :in incoming
|
|
78
|
+
#edges, :out - outcoming edges, :all - incoming and outcoming edges.
|
|
79
|
+
def degree(x,direction=:all)
|
|
80
|
+
x = @map.index(x)
|
|
81
|
+
sum_in = 0
|
|
82
|
+
sum_out = 0
|
|
83
|
+
0.upto @max do |i|
|
|
84
|
+
sum_in += 1 if @store[i,x] and @store[i,x] > 0
|
|
85
|
+
sum_out += 1 if @store[x,i] and @store[x,i] > 0
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
case direction
|
|
89
|
+
when :all
|
|
90
|
+
sum_in+sum_out
|
|
91
|
+
when :in
|
|
92
|
+
sum_in
|
|
93
|
+
when :out
|
|
94
|
+
sum_out
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
#Vertex iterator
|
|
100
|
+
def each_vertex
|
|
101
|
+
(0..@max).each {|v| yield @map[v]}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
#Edge iterator
|
|
105
|
+
def each_edge
|
|
106
|
+
for v0 in 0..@max
|
|
107
|
+
for v1 in 0..v0-1
|
|
108
|
+
yield Edge.new(@map[v0],@map[v1],@store[v0,v1]) if @store[v0,v1] > 0
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
class GraphAsTriMatrix < GraphAsMatrix
|
|
3
|
+
|
|
4
|
+
def initialize(edges)
|
|
5
|
+
@store = TriMatrix.new(0)
|
|
6
|
+
@max = 0
|
|
7
|
+
@map = []
|
|
8
|
+
@v = 0
|
|
9
|
+
|
|
10
|
+
add_edges(edges)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
#Returns vertex degree.
|
|
14
|
+
def degree(x)
|
|
15
|
+
x = @map.index(x)
|
|
16
|
+
sum = 0
|
|
17
|
+
0.upto @max do |i|
|
|
18
|
+
sum += @store[x,i] if @store[x,i]
|
|
19
|
+
end
|
|
20
|
+
sum
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
|
|
3
|
+
#Class represent list with cycle.
|
|
4
|
+
class CyclicList < List
|
|
5
|
+
|
|
6
|
+
#Returns cycle size. If list has no cycles returns 0.
|
|
7
|
+
def cycle_size
|
|
8
|
+
counter = 0
|
|
9
|
+
if start = self.joint
|
|
10
|
+
counter = 1
|
|
11
|
+
elem = joint.next
|
|
12
|
+
while elem != start
|
|
13
|
+
elem = elem.next
|
|
14
|
+
counter += 1
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
counter
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
module DS
|
|
2
|
+
|
|
3
|
+
#Implements simple list data structure.
|
|
4
|
+
class List
|
|
5
|
+
|
|
6
|
+
include Enumerable
|
|
7
|
+
|
|
8
|
+
attr_accessor :head, :tail
|
|
9
|
+
|
|
10
|
+
#Creates new list.
|
|
11
|
+
def initialize(x=nil)
|
|
12
|
+
@head = ListElement.new(x)
|
|
13
|
+
@tail = @head
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
#Creates list from array.
|
|
17
|
+
def self.from_array(arr)
|
|
18
|
+
list = new(arr.shift)
|
|
19
|
+
tail = list.head
|
|
20
|
+
arr.each{ |e| tail = tail.append(e) }
|
|
21
|
+
list.tail = tail
|
|
22
|
+
list
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
#Appends new element to list.
|
|
26
|
+
def append(x)
|
|
27
|
+
last_elem = self.tail
|
|
28
|
+
if !empty?
|
|
29
|
+
@tail = last_elem.append(x)
|
|
30
|
+
else
|
|
31
|
+
@head = ListElement.new(x)
|
|
32
|
+
@tail = @head
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
alias :<< :append
|
|
37
|
+
|
|
38
|
+
#Prepends new element to list.
|
|
39
|
+
def prepend(x)
|
|
40
|
+
el = ListElement.new(x)
|
|
41
|
+
el.next = @head
|
|
42
|
+
@head = el
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
#Removes element x from list.
|
|
46
|
+
def remove(x)
|
|
47
|
+
if x == head
|
|
48
|
+
self.head = head.next
|
|
49
|
+
x.next = nil
|
|
50
|
+
else
|
|
51
|
+
|
|
52
|
+
el = head
|
|
53
|
+
while el and el != x
|
|
54
|
+
prev = el
|
|
55
|
+
el = el.next
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
raise "Element not found" unless el
|
|
59
|
+
|
|
60
|
+
prev.next = el.next
|
|
61
|
+
el.next = nil
|
|
62
|
+
end
|
|
63
|
+
x
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
#Removes list head.
|
|
67
|
+
def shift
|
|
68
|
+
remove(head).data
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#Inserts element x after another element.
|
|
72
|
+
def insert_after(x,rel)
|
|
73
|
+
x = ListElement.new(x)
|
|
74
|
+
|
|
75
|
+
el = head
|
|
76
|
+
while el and el != rel
|
|
77
|
+
el = el.next
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
raise "Element not found" unless el
|
|
81
|
+
|
|
82
|
+
x.next = el.next
|
|
83
|
+
el.next = x
|
|
84
|
+
|
|
85
|
+
if x.tail?
|
|
86
|
+
self.tail = x
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
#Inserts element x before another element.
|
|
91
|
+
def insert_before(x,rel)
|
|
92
|
+
x = ListElement.new(x)
|
|
93
|
+
|
|
94
|
+
#inserting at the beginnig of the list
|
|
95
|
+
if rel == head
|
|
96
|
+
x.next = head
|
|
97
|
+
self.head = x
|
|
98
|
+
|
|
99
|
+
#inserting in the tail of the list
|
|
100
|
+
else
|
|
101
|
+
el = head
|
|
102
|
+
prev = head
|
|
103
|
+
while el and el != rel
|
|
104
|
+
prev = el
|
|
105
|
+
el = el.next
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
if el.nil?
|
|
109
|
+
raise "List element not found"
|
|
110
|
+
else
|
|
111
|
+
prev.next = x
|
|
112
|
+
x.next = el
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
#Checks if list is empty.
|
|
119
|
+
def empty?
|
|
120
|
+
head.data.nil?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
#Returns last element of the list.
|
|
124
|
+
def last
|
|
125
|
+
tail.data
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def first
|
|
129
|
+
head.data
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
#Returns length of the list.
|
|
133
|
+
def length
|
|
134
|
+
count
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
#Checks if list is linked at the end with other list.
|
|
138
|
+
def zip?(other)
|
|
139
|
+
tail.equal? other.tail
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
#Returns joint element if exists, otherwise returns nil.
|
|
143
|
+
def joint
|
|
144
|
+
elem = head
|
|
145
|
+
elem2 = elem.next
|
|
146
|
+
|
|
147
|
+
while elem and elem2
|
|
148
|
+
|
|
149
|
+
#traversing by 1
|
|
150
|
+
elem = elem.next
|
|
151
|
+
|
|
152
|
+
#traversing by 2
|
|
153
|
+
elem2 = elem2.next
|
|
154
|
+
elem2 = elem2.next if elem2
|
|
155
|
+
|
|
156
|
+
if elem2.equal? elem
|
|
157
|
+
return elem
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
nil
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
#Returns true if list has cycle.
|
|
165
|
+
def looped?
|
|
166
|
+
!!joint
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
#Orderize list by evaluating block. Block should evaluate to one of these
|
|
171
|
+
#values: 1,0,-1 (same as Comparable).
|
|
172
|
+
def orderize
|
|
173
|
+
|
|
174
|
+
zero = List.new
|
|
175
|
+
plus = List.new
|
|
176
|
+
minus = List.new
|
|
177
|
+
|
|
178
|
+
el = self.head
|
|
179
|
+
|
|
180
|
+
while el
|
|
181
|
+
case yield el.data
|
|
182
|
+
when 0
|
|
183
|
+
zero_tail = zero.append(el.data)
|
|
184
|
+
when 1
|
|
185
|
+
plus_tail = plus.append(el.data)
|
|
186
|
+
when -1
|
|
187
|
+
minus_tail = minus.append(el.data)
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
el = el.next
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
minus_tail.next = zero.head
|
|
194
|
+
zero_tail.next = plus.head
|
|
195
|
+
return minus
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
# Removes elements that exists on the other list.
|
|
200
|
+
def remove!(other)
|
|
201
|
+
a = head
|
|
202
|
+
b = other.head
|
|
203
|
+
|
|
204
|
+
while a and b
|
|
205
|
+
|
|
206
|
+
while a.data < b.data
|
|
207
|
+
prev = a
|
|
208
|
+
a = a.next
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
while b.data < a.data
|
|
212
|
+
b = b.next
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
a = a.next
|
|
216
|
+
prev.next = a
|
|
217
|
+
b = b.next
|
|
218
|
+
end
|
|
219
|
+
self
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Merge list with other list.
|
|
223
|
+
def merge(other)
|
|
224
|
+
|
|
225
|
+
a = self.head
|
|
226
|
+
b = other.head
|
|
227
|
+
|
|
228
|
+
if a.data < b.data
|
|
229
|
+
result = List.new(a.data)
|
|
230
|
+
a = a.next
|
|
231
|
+
else
|
|
232
|
+
result = List.new(b.data)
|
|
233
|
+
b = b.next
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
while a and b
|
|
237
|
+
if a.data < b.data
|
|
238
|
+
result.append(a.data)
|
|
239
|
+
a = a.next
|
|
240
|
+
else
|
|
241
|
+
result.append(b.data)
|
|
242
|
+
b = b.next
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
if !b
|
|
246
|
+
result.tail.next = a
|
|
247
|
+
result.tail = self.tail
|
|
248
|
+
elsif !a
|
|
249
|
+
result.tail.next = b
|
|
250
|
+
result.tail = other.tail
|
|
251
|
+
end
|
|
252
|
+
result
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
#Reverses list.
|
|
256
|
+
def reverse!
|
|
257
|
+
@tail = self.head
|
|
258
|
+
prev = self.head
|
|
259
|
+
elem = prev.next
|
|
260
|
+
prev.next = nil
|
|
261
|
+
while elem
|
|
262
|
+
nxt = elem.next
|
|
263
|
+
elem.next = prev
|
|
264
|
+
prev = elem
|
|
265
|
+
elem = nxt
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
@head = prev
|
|
269
|
+
self
|
|
270
|
+
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
#Prints list.
|
|
274
|
+
def print
|
|
275
|
+
each { |e| p }
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
#Converts list to array.
|
|
279
|
+
def to_a
|
|
280
|
+
map { |e| e}
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
#Default list iterator.
|
|
284
|
+
def each
|
|
285
|
+
elem = @head
|
|
286
|
+
while elem
|
|
287
|
+
yield elem.data
|
|
288
|
+
elem = elem.next
|
|
289
|
+
end
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
def each_with_index
|
|
293
|
+
elem = @head
|
|
294
|
+
i = 0
|
|
295
|
+
while elem
|
|
296
|
+
yield elem,i
|
|
297
|
+
elem = elem.next
|
|
298
|
+
i = i + 1
|
|
299
|
+
end
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
end
|
|
303
|
+
end
|