data-struct 0.0.10 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9afef8d83b99609e9b5b7198f2c74d6f8f60df31
4
- data.tar.gz: 7e8812d7bf78a9678feb71371149ba352f197f35
3
+ metadata.gz: c437ac066dcec6997b160235477be36c58441660
4
+ data.tar.gz: 053bae6faad59521f3ce8169d1e39ca1cf82db85
5
5
  SHA512:
6
- metadata.gz: dd8f19a9af0523dfe9176108d549882aedf4610cde4bcaeadf730254392a2bbabae73c4da7c123a8f5f041fb723d02aaef87935c79ec0121c36d833ac9328e7e
7
- data.tar.gz: 7100ff534e0f5dd748c03ed0d8a865c6fc15754f5b0e5141a24a3aea47875c93adc3abd0e3ef09d6202c39744d280d35faac1db874126e258a0d67efd68cb7db
6
+ metadata.gz: 055ccbb07e98d24aa728034e4d28b674b045c71aa354bbee01610bb19f0a2cff3f1a11dd60c452482da2656ff67261622aff975246db03eaac89cd158a16013f
7
+ data.tar.gz: ca1608ee961b31799490719f028bc8936c9bdbeeb8a0045a1a1f657f35d8b03ae3ce978173061b001e2222c7dae949fe38dfe7ddb9db229c05eda669ee135ad7
data/lib/bin_heap.rb CHANGED
@@ -27,67 +27,68 @@ class BinHeap
27
27
  end
28
28
 
29
29
  protected
30
- attr_writer :prc, :store
30
+
31
+ attr_writer :prc, :store
31
32
 
32
33
  public
33
- def self.heapify_up(store, child_idx, &prc)
34
- prc = prc || Proc.new { |el1, el2| el1 <=> el2 }
35
- return store if child_idx == 0
36
-
37
- parent_idx = find_parent(child_idx)
38
-
39
- if prc.call(store[child_idx], store[parent_idx]) == -1
40
- store[child_idx], store[parent_idx] = store[parent_idx], store[child_idx]
41
- heapify_up(store, parent_idx, &prc)
42
- else
43
- return store
44
- end
45
- end
46
34
 
47
- def self.heapify_down(store, parent_idx, &prc)
48
- prc = prc || Proc.new { |el1, el2| el1 <=> el2 }
49
-
50
- children_idx = find_children(store.length - 1, parent_idx)
51
-
52
- c0_idx = children_idx[0]
53
- c1_idx = children_idx[1]
35
+ def self.heapify_up(store, child_idx, &prc)
36
+ prc = prc || Proc.new { |el1, el2| el1 <=> el2 }
37
+ return store if child_idx == 0
54
38
 
55
- children = []
56
- children << store[c0_idx] if c0_idx
57
- children << store[c1_idx] if c1_idx
39
+ parent_idx = find_parent(child_idx)
40
+
41
+ if prc.call(store[child_idx], store[parent_idx]) == -1
42
+ store[child_idx], store[parent_idx] = store[parent_idx], store[child_idx]
43
+ heapify_up(store, parent_idx, &prc)
44
+ else
45
+ return store
46
+ end
47
+ end
58
48
 
59
- parent = store[parent_idx]
49
+ def self.heapify_down(store, parent_idx, &prc)
50
+ prc = prc || Proc.new { |el1, el2| el1 <=> el2 }
51
+
52
+ children_idx = find_children(store.length - 1, parent_idx)
53
+
54
+ c0_idx = children_idx[0]
55
+ c1_idx = children_idx[1]
60
56
 
61
- #When the parent index is where it's supposed to be
62
- if children.all? { |child| prc.call(child, parent) >= 0}
63
- return store
64
- end
57
+ children = []
58
+ children << store[c0_idx] if c0_idx
59
+ children << store[c1_idx] if c1_idx
65
60
 
66
- if store.length == 1
67
- swap_idx = c0_idx
68
- else
69
- swap_idx = prc.call(children[0], children[1]) == 1 ? c1_idx : c0_idx
70
- end
61
+ parent = store[parent_idx]
71
62
 
72
- store[swap_idx], store[parent_idx] = parent, store[swap_idx]
63
+ # When the parent index is where it's supposed to be
64
+ if children.all? { |child| prc.call(child, parent) >= 0 }
65
+ return store
66
+ end
73
67
 
74
- heapify_down(store, swap_idx, &prc)
68
+ if store.length == 1
69
+ swap_idx = c0_idx
70
+ else
71
+ swap_idx = prc.call(children[0], children[1]) == 1 ? c1_idx : c0_idx
75
72
  end
76
73
 
77
- def self.find_children(last_idx, parent_idx)
78
- child1 = (parent_idx * 2) + 1
79
- child2 = (parent_idx * 2) + 2
74
+ store[swap_idx], store[parent_idx] = parent, store[swap_idx]
80
75
 
76
+ heapify_down(store, swap_idx, &prc)
77
+ end
81
78
 
82
- return [child1, child2].select{ |idx| idx <= last_idx }
83
- end
79
+ def self.find_children(last_idx, parent_idx)
80
+ child1 = (parent_idx * 2) + 1
81
+ child2 = (parent_idx * 2) + 2
84
82
 
85
- def self.find_parent(child_idx)
86
- if child_idx == 0
87
- raise "Out of bounds"
88
- else
89
- return (child_idx - 1) / 2
90
- end
83
+ return [child1, child2].select{ |idx| idx <= last_idx }
84
+ end
85
+
86
+ def self.find_parent(child_idx)
87
+ if child_idx == 0
88
+ raise "Out of bounds"
89
+ else
90
+ return (child_idx - 1) / 2
91
91
  end
92
+ end
92
93
  end
93
94
 
@@ -16,57 +16,42 @@ class BinarySearchTree
16
16
  end
17
17
  end
18
18
 
19
- def children
20
- count = 0
21
- count += 1 if left.class == BinarySearchTree
22
- count += 1 if right.class == BinarySearchTree
23
-
24
- count
25
- end
26
-
27
19
  def left_rotate
20
+ #
28
21
  # A B
29
22
  # / \ / \
30
- # D B <=> A' C
23
+ # D B <=> A C
31
24
  # / \ / \
32
25
  # E C D E
33
26
  #
34
27
 
35
- # KW: still need to refactor this, unnecessary creation of new node
36
- # reassign parent
37
- new_left = BinarySearchTree.new(value) # A'
28
+ new_left = BinarySearchTree.new(value) # A'
29
+
30
+ new_left.left, left.parent = left, new_left # A' <-> D
31
+ new_left.right, right.left.parent = right.left, new_left # A' <-> E
32
+ new_left.parent = self # A' <- A
38
33
 
39
- new_left.left = left # A' -> D
40
- left.parent = new_left # D <- A'
41
- new_left.right = right.left # A' -> E
42
- right.left.parent = new_left # E <- A'
43
- new_left.parent = self # A' <- A
34
+ new_right, new_right.parent = right.right, self # C <-> A
44
35
 
45
- new_right = right.right # C
46
- new_right.parent = self # C <- A
47
-
48
36
  @value, @left, @right = right.value, new_left, new_right
49
37
  end
50
38
 
51
39
  def right_rotate
52
40
  new_right = BinarySearchTree.new(value)
53
41
 
54
- new_right.right = right
55
- right.parent = new_right
56
- new_right.left = left.right
57
- left.right.parent = new_right
42
+ new_right.right, right.parent = right, new_right
43
+ new_right.left, left.right.parent = left.right, new_right
58
44
  new_right.parent = self
59
45
 
60
- new_left = left.left
61
- new_left.parent = self
46
+ new_left, new_left.parent = left.left, self
62
47
 
63
48
  @value, @left, @right = left.value, new_left, new_right
64
49
  end
65
50
 
66
51
  def insert(val)
67
52
  case val <=> value
68
- when -1 then insert_left(val)
69
- when 1 then insert_right(val)
53
+ when -1 then insert_at(val, left, -1)
54
+ when 1 then insert_at(val, right, 1)
70
55
  when 0 then false
71
56
  end
72
57
 
@@ -92,50 +77,40 @@ class BinarySearchTree
92
77
  def recalculate_depth_and_balance
93
78
  @depth = ([left.depth, right.depth].max + 1)
94
79
  @balance = right.depth - left.depth
95
- # p "RECALULATED DEPTH = #{depth}: BALANCE = #{balance}"
96
80
  end
97
81
 
98
82
  def update_depth_and_balance
99
83
  # recursively update depth and balance, rebalances if needed and crawls up the tree
100
84
  recalculate_depth_and_balance
101
85
  rebalance if ([-2, 2].include?(@balance))
102
- # p "RECALULATED #{self.inspect} DEPTH = #{depth}: BALANCE = #{balance}"
103
86
  parent.update_depth_and_balance
104
87
  end
105
88
 
106
89
  private
107
90
 
108
- def insert_left(val)
109
- if (left.class != EmptyNode)
110
- left.insert(val)
111
- else
112
- new_node = BinarySearchTree.new(val)
113
- self.left, new_node.parent = new_node, self
114
- new_node.update_depth_and_balance
115
- end
116
- end
117
-
118
- def insert_right(val)
119
- if (right.class != EmptyNode)
120
- right.insert(val)
91
+ def insert_at(val, node, dir)
92
+ # dir: -1 => left, 1 => right
93
+ if (node.class != EmptyNode)
94
+ node.insert(val)
121
95
  else
122
96
  new_node = BinarySearchTree.new(val)
123
- self.right, new_node.parent = new_node, self
97
+ (dir == 1) ? self.right = new_node : self.left = new_node
98
+ new_node.parent = self
124
99
  new_node.update_depth_and_balance
125
100
  end
126
101
  end
127
102
 
128
103
  def rebalance
129
- if @balance == -2
104
+ case @balance
105
+ when -2
130
106
  left.left_rotate if left.balance == 1
131
107
  right_rotate
132
- elsif @balance == 2
108
+ when 2
133
109
  right.right_rotate if right.balance == -1
134
110
  left_rotate
135
111
  end
136
- right.recalculate_depth_and_balance
137
- left.recalculate_depth_and_balance
138
- recalculate_depth_and_balance
112
+
113
+ [right, left, self].each { |n| n.recalculate_depth_and_balance }
139
114
  end
140
115
  end
141
116
 
@@ -152,18 +127,10 @@ class EmptyNode
152
127
  false
153
128
  end
154
129
 
155
- def insert(*)
156
- false
157
- end
158
-
159
130
  def inspect
160
131
  "{}"
161
132
  end
162
133
 
163
- def recalculate_depth_and_balance
164
- true
165
- end
166
-
167
134
  def to_a
168
135
  []
169
136
  end
@@ -9,10 +9,12 @@ class LinkedList
9
9
 
10
10
  def pop
11
11
  last_link = @last_sentinel.prev
12
- val = last_link.val
12
+ return nil if last_link == @begin_sentinel
13
+
14
+ last_link.prev.next = @last_sentinel
13
15
  @last_sentinel.prev = last_link.prev
14
16
 
15
- val
17
+ last_link.val
16
18
  end
17
19
 
18
20
  def push(val)
@@ -23,7 +25,7 @@ class LinkedList
23
25
  else
24
26
  @begin_sentinel.next = link
25
27
  end
26
- @last_sentinel.prev = link
28
+ @last_sentinel.prev = link
27
29
 
28
30
  self
29
31
  end
@@ -44,7 +46,9 @@ class LinkedList
44
46
  def shift
45
47
  first_link = @begin_sentinel.next
46
48
  return nil if first_link.nil?
49
+
47
50
  @begin_sentinel.next = first_link.next
51
+ first_link.next.prev = @begin_sentinel
48
52
 
49
53
  first_link.val
50
54
  end
data/lib/dynamic_array.rb CHANGED
@@ -11,8 +11,8 @@ class DynamicArray
11
11
  end
12
12
 
13
13
  def empty?
14
- # will refactor to check num_items because I'm not testing that variable right now
15
- return @store.empty?
14
+ # not cheating by checking @store
15
+ return num_items == 0
16
16
  end
17
17
 
18
18
  def insert(val, idx)
@@ -38,6 +38,7 @@ class DynamicArray
38
38
 
39
39
  def pop
40
40
  # O(1)
41
+ raise "array is empty" if @num_items == 0
41
42
  @num_items -= 1
42
43
  idx = @start + @num_items
43
44
  val, @store[idx] = @store[idx], nil
@@ -74,6 +75,7 @@ class DynamicArray
74
75
 
75
76
  def shift
76
77
  # O(1)
78
+ raise "array is empty" if @num_items == 0
77
79
  val, @store[@start] = @store[@start], nil
78
80
  @num_items -= 1
79
81
  @start += 1
@@ -0,0 +1,73 @@
1
+
2
+ require "bin_heap"
3
+
4
+ class PriorityQueue
5
+ attr_reader :store
6
+
7
+ def initialize(&prc)
8
+ @store = Array.new
9
+ @prc = prc || Proc.new { |el1, el2| el1 <=> el2 }
10
+ end
11
+
12
+ def insert(val, priority)
13
+ @store << [val, priority]
14
+ self.heapify_up(@store.length - 1)
15
+ end
16
+
17
+ def extract
18
+ raise "PriorityQueue is empty" if @store.empty?
19
+
20
+ value, _ = @store[0]
21
+
22
+ if @store.length > 1
23
+ @store[0] = @store.pop
24
+ self.heapify_down(0)
25
+ else
26
+ @store.pop
27
+ end
28
+
29
+ value
30
+ end
31
+
32
+ def heapify_up(start_idx)
33
+ return true if start_idx == 0
34
+
35
+ parent_idx = find_parent(start_idx)
36
+
37
+ if @prc.call(@store[start_idx][1], @store[parent_idx][1]) == -1
38
+ @store[start_idx], @store[parent_idx] = @store[parent_idx], @store[start_idx]
39
+ heapify_up(parent_idx)
40
+ else
41
+ return true
42
+ end
43
+ end
44
+
45
+ def heapify_down(start_idx)
46
+ children_idx = find_children(start_idx)
47
+ children_idx.select! { |i| i < @store.length }
48
+
49
+ return true if children_idx.all? { |i| @prc.call(@store[i][1], @store[start_idx][1]) >= 0 }
50
+
51
+ if children_idx.length == 1
52
+ temp_idx = children_idx[0]
53
+ else
54
+ temp_idx = @prc.call(@store[children_idx[0]][1], @store[children_idx[1]][1]) == -1 ? children_idx[0] : children_idx[1]
55
+ end
56
+
57
+ @store[temp_idx], @store[start_idx] = @store[start_idx], @store[temp_idx]
58
+
59
+ heapify_down(temp_idx)
60
+ end
61
+
62
+ def find_parent(idx)
63
+ return false if idx == 0
64
+ return (idx - 1) / 2
65
+ end
66
+
67
+ def find_children(idx)
68
+ child_1 = (idx * 2) + 1
69
+ child_2 = (idx * 2) + 2
70
+
71
+ return [child_1, child_2].select { |i| i < @store.length }
72
+ end
73
+ end
metadata CHANGED
@@ -1,17 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data-struct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.10
4
+ version: 0.0.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Wang
8
8
  - Daniel Ng
9
9
  - Conan Tzou
10
10
  - Karen Ling
11
+ - Aaron Hong
11
12
  autorequire:
12
13
  bindir: bin
13
14
  cert_chain: []
14
- date: 2015-07-16 00:00:00.000000000 Z
15
+ date: 2015-09-09 00:00:00.000000000 Z
15
16
  dependencies: []
16
17
  description: A simple gem that provides several useful implementations of data structures.
17
18
  Contribute at github.com/kswang2400/data-struct
@@ -27,6 +28,7 @@ files:
27
28
  - lib/dynamic_array.rb
28
29
  - lib/max_stack.rb
29
30
  - lib/min_max_stack.rb
31
+ - lib/priority_queue.rb
30
32
  - lib/singly_linked_list.rb
31
33
  - lib/stack_queue.rb
32
34
  homepage: http://rubygems.org/gems/data-struct
@@ -52,5 +54,5 @@ rubyforge_project:
52
54
  rubygems_version: 2.4.3
53
55
  signing_key:
54
56
  specification_version: 4
55
- summary: Data structures, some up and running, not fully tested
57
+ summary: Data structures
56
58
  test_files: []