data-struct 0.0.10 → 0.0.12

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.
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: []