├── .gitignore ├── Gemfile ├── LICENSE ├── README.md ├── RELEASE_NOTES ├── Rakefile ├── RubyDataStructures.gemspec ├── lib ├── RubyDataStructures.rb └── RubyDataStructures │ ├── doubly_linked_list.rb │ ├── doubly_linked_list │ └── element.rb │ ├── fifo_stack.rb │ ├── macros.rb │ ├── max_heap.rb │ ├── multi_dimensional_array.rb │ ├── queue_as_array.rb │ ├── ruby_data_structures.rb │ ├── singly_linked_list.rb │ ├── singly_linked_list │ └── element.rb │ ├── stack_as_array.rb │ └── version.rb └── test ├── RubyDataStructureTest.rb ├── doubly_linked_list_element_test.rb ├── doubly_linked_list_test.rb ├── fifo_stack_test.rb ├── max_heap_test.rb ├── multi_dimensional_array_test.rb ├── queue_as_array_test.rb ├── singly_linked_list_element_test.rb ├── singly_linked_list_test.rb └── stack_as_array_test.rb /.gitignore: -------------------------------------------------------------------------------- 1 | nbproject 2 | *.gem 3 | .bundle 4 | Gemfile.lock 5 | pkg/* -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in RubyDataStructures.gemspec 4 | gemspec -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | == RubyDataStructures 2 | 3 | Put appropriate LICENSE for your project here. 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RubyDatStructures 2 | ============= 3 | 4 | `RubyDataStructures` gem is a `ruby` implementation of common data structures that are not by default supported by the Ruby programming language. 5 | The `RubyDatStructures` supports the following data structures: 6 | 7 | - Multi Dimensional Array 8 | - Stack (Implemented as an array) 9 | - Queue (Implemented as an array) 10 | - Singly Linked List 11 | - Doubly Linked List 12 | - Max Heap 13 | 14 | Installation 15 | ------------ 16 | 17 | gem install RubyDataStructures 18 | 19 | Usage 20 | ----- 21 | 22 | The `RubyDatStructures` library can be easily imported by running: 23 | 24 | require 'rubygems' 25 | require 'RubyDataStructures' 26 | 27 | The usage of each of the data structures is described below. 28 | 29 | You can enable macros to more conveniently create these data structures by: 30 | 31 | require 'RubyDataStructures/macros' 32 | 33 | @stack = stack(3) 34 | @fifo = fifo_stack(5) 35 | @arr = multi_array(1,2,3) 36 | ... 37 | 38 | ## Tests 39 | 40 | Run tests/specs from console: 41 | 42 | rake test 43 | 44 | ## Multi Dimensional Array 45 | 46 | A `multi dimensional array` can be initialized by running: 47 | 48 | RubyDataStructures::MultiDimensionalArray.new(n) 49 | 50 | where `n` is the number of dimensions of the multi dimensional array. 51 | 52 | The key at a particular index can be easily accessed by calling the array with the dimensions of the index. 53 | The key at the index with dimensions `(2,4,3)` of a multi dimensional array `mul_dim_array` can be access by calling: 54 | 55 | mul_dim_array[2,4,3] 56 | 57 | The key for an index can also be easily set by calling the setter with the dimensions of the index. 58 | The key at the index with dimensions `(2,4,3)` of a multi dimensional array `mul_dim_array` can be set to `36` by calling: 59 | 60 | mul_dim_array[2,4,3] = 36 61 | 62 | ## Stack 63 | 64 | A `Stack` can be initialized by running: 65 | 66 | RubyDataStructures::StackAsArray.new(n) 67 | 68 | where `n` is the max-size of stack. 69 | 70 | The following methods available on a `stack` are self explanatory: 71 | 72 | - empty? 73 | - full? 74 | - singleton? 75 | - push(`element`) 76 | - pop 77 | - reset 78 | 79 | Examples: 80 | 81 | my_stack = RubyDataStructures::StackAsArray.new(5) 82 | my_stack.empty? # Returns `true` 83 | my_stack.full? # Returns `false` 84 | my_stack.singleton? # Returns `false` 85 | my_stack.push(1) 86 | my_stack.push(2) 87 | my_stach.push(3) 88 | my_stack.pop # Return `3` 89 | 90 | *Notes:* 91 | Why not use the internal `#push` and `#pop` methods of Array that already makes an Array simulate a stack? Why create the initial array with the full max length? 92 | Perhaps make this a config option? 93 | 94 | ## Queue 95 | 96 | A `Queue` can be initialized by calling: 97 | 98 | RubyDataStructures::QueueAsArray.new(n) 99 | 100 | where `n` is the max-size of the queue. 101 | 102 | The following methods available on a `queue` are self explanatory: 103 | 104 | - empty? 105 | - full? 106 | - enqueue(`element`) 107 | - dequeue 108 | - reset 109 | 110 | Examples: 111 | 112 | my_queue = RubyDataStructures::QueueAsArray.new(5) 113 | my_queue.empty? # Returns `true` 114 | my_queue.full? # Returns `false` 115 | my_queue.enqueue(1) 116 | my_queue.enqueue(2) 117 | my_queue.enqueue(3) 118 | my_queue.dequeue # Returns `1` 119 | 120 | ## Singly Linked List 121 | 122 | A `singly linked list` can be initialized by running: 123 | 124 | RubyDataStructures::SinglyLinkedList.new 125 | 126 | The following methods available on a `singly linked list` are self explanatory: 127 | 128 | - head 129 | - empty? 130 | - insert(`item`) 131 | - search(`key`) 132 | - delete(`key`) 133 | - reset 134 | 135 | Examples: 136 | 137 | my_list = RubyDataStructures::SinglyLinkedList.new 138 | my_list.head # Returns `nil` 139 | my_list.empty? # Returns `true` 140 | my_list.insert(7) 141 | my_list.search(7) # Returns a `RubyDataStructures::SinglyLinkedList::Element` element, whose key is `7` 142 | my_list.delete(7) 143 | 144 | ## Doubly Linked List 145 | 146 | A `doubly linked list` can be intialized by running: 147 | 148 | RubyDataStructures::DoublyLinkedList.new 149 | 150 | The following methods available on a `doubly linked list` are self explanatory: 151 | 152 | - head 153 | - tail 154 | - empty? 155 | - insert(`item`) 156 | - search(`key`) 157 | - delete(`key`) 158 | - reset 159 | 160 | Examples: 161 | 162 | my_list = RubyDataStructures::DoublyLinkedList.new 163 | my_list.head # Returns a `RubyDataStructures::DoublyLinkedList::Element` element, whose key is nil 164 | my_list.tail # Returns a `RubyDataStructures::DoublyLinkedList::Element` element, whose key is nil 165 | my_list.empty? # Returns `true` 166 | my_list.insert(7) 167 | my_list.search(7) # Returns a `RubyDataStructures::DoublyLinkedList::Element` element, whose key is `7` 168 | my_list.delete(7) 169 | 170 | ## Max Heap 171 | 172 | `MaxHeap` inherits most of its functionality from `Array`. 173 | A `max heap` can be initialized by running: 174 | 175 | RubyDataStructures::MaxHeap.build(array) 176 | 177 | where `array` is an array, out of which we would like to build a max heap. 178 | 179 | For example, a heap can be built out of an array `[4, 1, 3, 2, 16, 9, 10, 14, 8, 7]` by running: 180 | 181 | heap = RubyDataStructures::MaxHeap.build([4, 1, 3, 2, 16, 9, 10, 14, 8, 7]) 182 | # Returns the MaxHeap: [16, 14, 10, 8, 7, 9, 3, 2, 4, 1] 183 | 184 | The `maximum` of the heap can be accessed by running: 185 | 186 | heap.maximum # Returns `16` 187 | 188 | The maximum of the heap can be extracted by running: 189 | 190 | heap.extract_maximum! 191 | 192 | The key of a particular element can be increased by running: 193 | 194 | heap.increase_key!(index, key) 195 | 196 | Example: 197 | 198 | heap.increase_key!(8, 15) 199 | 200 | A key can be inserted into a heap by running: 201 | 202 | heap.insert!(key) 203 | 204 | Example: 205 | 206 | heap.insert!(11) 207 | 208 | 209 | Author 210 | ------ 211 | 212 | B V Satyaram <[bvsatyaram.com](http://bvsatyaram.com)> -------------------------------------------------------------------------------- /RELEASE_NOTES: -------------------------------------------------------------------------------- 1 | = Announce: Ruby DataStructures Release 1.1.0 2 | 3 | - Added FifoStack. 4 | - Added macros 5 | - Extra Documentation 6 | - Rakefile for running tests 7 | 8 | = Announce: Ruby DataStructures Release 1.0.0 9 | 10 | Basic data structures in place 11 | 12 | = Announce: Ruby DataStructures Release 0.0.4 13 | Date Mar 5, 2011 14 | Release 0.0.4 is just a dummy release to fix some gem push issues. 15 | 16 | == Thanks 17 | 18 | -- Satyaram B V 19 | 20 | =========================================== 21 | 22 | = Announce: Ruby DataStructures Release 0.0.3 23 | Date Mar 5, 2011 24 | Release 0.0.3 adds new features. 25 | 26 | New features: 27 | 28 | * DoublyLinkedList 29 | 30 | Deprecation Notices: 31 | 32 | * None 33 | 34 | Bugs Fixed: 35 | 36 | * None 37 | 38 | Other Changes Include: 39 | 40 | * Fixed typo: sentinal => sentinel 41 | 42 | == Thanks 43 | 44 | -- Satyaram B V 45 | 46 | =========================================== 47 | 48 | = Announce: Ruby DataStructures Release 0.0.2 49 | Date Mar 5, 2011 50 | Release 0.0.2 adds new features. 51 | 52 | New features: 53 | 54 | * SinglyLinkedList 55 | 56 | Deprecation Notices: 57 | 58 | * None 59 | 60 | Bugs Fixed: 61 | 62 | * None 63 | 64 | Other Changes Include: 65 | 66 | * None 67 | 68 | == Thanks 69 | 70 | -- Satyaram B V 71 | 72 | =========================================== 73 | 74 | = Announce: RubyDatStructures Release 0.0.1 75 | Date: Mar 4, 2011 76 | Release 0.0.1 makes the project public. 77 | 78 | $ gem install RubyDataStructures 79 | 80 | New features: 81 | 82 | * MultiDimensionalArray 83 | * StackAsArray 84 | * QueueAsArray 85 | 86 | Deprecation Notices: 87 | 88 | * None 89 | 90 | Bugs Fixed: 91 | 92 | * None 93 | 94 | Other Changes Include: 95 | 96 | * None 97 | 98 | == Thanks 99 | 100 | -- Satyaram B V -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | Bundler::GemHelper.install_tasks 3 | 4 | require 'rake/testtask' 5 | 6 | Rake::TestTask.new do |t| 7 | t.libs << "test" 8 | t.test_files = FileList['test/*_test.rb'] 9 | t.verbose = true 10 | end -------------------------------------------------------------------------------- /RubyDataStructures.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | $:.push File.expand_path("../lib", __FILE__) 3 | require "RubyDataStructures/version" 4 | 5 | Gem::Specification.new do |s| 6 | s.name = "RubyDataStructures" 7 | s.version = Rubydatastructures::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ["Satyaram B V"] 10 | s.email = ["bvsatyaramATgmailDOTcom"] 11 | s.homepage = "http://bvsatyaram.com" 12 | s.summary = %q{Implementation of standard data structures in Ruby} 13 | s.description = %q{Implementation of standard data structures in Ruby} 14 | 15 | s.rubyforge_project = "RubyDataStructures" 16 | 17 | s.files = `git ls-files`.split("\n") 18 | s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") 19 | s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } 20 | s.require_paths = ["lib"] 21 | end -------------------------------------------------------------------------------- /lib/RubyDataStructures.rb: -------------------------------------------------------------------------------- 1 | # Abstract RubyDataStructure 2 | require 'RubyDataStructures/ruby_data_structures' 3 | 4 | # All RubyDataStructures 5 | require 'RubyDataStructures/multi_dimensional_array' 6 | require 'RubyDataStructures/stack_as_array' 7 | require 'RubyDataStructures/fifo_stack' 8 | require 'RubyDataStructures/queue_as_array' 9 | require 'RubyDataStructures/singly_linked_list' 10 | require 'RubyDataStructures/singly_linked_list/element' 11 | require 'RubyDataStructures/doubly_linked_list' 12 | require 'RubyDataStructures/doubly_linked_list/element' 13 | require 'RubyDataStructures/max_heap' -------------------------------------------------------------------------------- /lib/RubyDataStructures/doubly_linked_list.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::DoublyLinkedList < RubyDataStructures::SinglyLinkedList 2 | 3 | # Overrides the +initialize+ method in SinglyLinkedList 4 | # Initializes the DoublyLinkedList 5 | def initialize 6 | @sentinel = RubyDataStructures::DoublyLinkedList::Element.new(self, nil) 7 | self.reset 8 | end 9 | 10 | # Extends the +reset+ method in SinglyLinkedList to also set +previous+ 11 | # attribute to the sentinel 12 | def reset 13 | super 14 | @sentinel.previous = @sentinel 15 | end 16 | 17 | # Returns the last element of the linked list 18 | def tail 19 | @sentinel.previous 20 | end 21 | 22 | # Overrides the +insert+ method in SinglyLinkedList to also set/update 23 | # +previous+ attributes to the elements 24 | def insert(item) 25 | element = RubyDataStructures::DoublyLinkedList::Element.new(self, item) 26 | element.next = @sentinel.next 27 | @sentinel.next = element 28 | element.next.previous = element 29 | element.previous = @sentinel 30 | end 31 | 32 | # Overrides the +delete+ method in SinglyLinkedList to optimize the 33 | # implementation. 34 | def delete(key) 35 | element = search(key) 36 | 37 | if element == @sentinel 38 | raise "Argument Error - No element with the key found" 39 | else 40 | element.previous.next = element.next 41 | element.next.previous = element.previous 42 | end 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /lib/RubyDataStructures/doubly_linked_list/element.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::DoublyLinkedList::Element < RubyDataStructures::SinglyLinkedList::Element 2 | attr_accessor :previous 3 | end 4 | -------------------------------------------------------------------------------- /lib/RubyDataStructures/fifo_stack.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::FifoStack < RubyDataStructures::StackAsArray 2 | def push(element) 3 | 4 | if self.full? 5 | @array.shift 6 | @top -= 1 7 | end 8 | 9 | if self.empty? 10 | @top = 0 11 | else 12 | @top = @top + 1 13 | end 14 | 15 | @array[@top] = element 16 | end 17 | end -------------------------------------------------------------------------------- /lib/RubyDataStructures/macros.rb: -------------------------------------------------------------------------------- 1 | def fifo_stack size=1 2 | RubyDataStructures::FifoStack.new size 3 | end 4 | 5 | def stack size=1 6 | RubyDataStructures::Stack.new size 7 | end 8 | 9 | def multi_array(*dimensions) 10 | RubyDataStructures::MultiDimensionalArray.new(*dimensions) 11 | end 12 | 13 | def max_heap(*array) 14 | RubyDataStructures::MaxHeap.build(array.flatten) 15 | end 16 | 17 | def linked_list(type = :single) 18 | case type 19 | when :single 20 | RubyDataStructures::SinglyLinkedList.new 21 | when :double, :dbl 22 | RubyDataStructures::DoublyLinkedList.new 23 | else 24 | raise ArgumentError, "Unknown or unsupported kind of Linked List: #{type}, must be: :single or :double" 25 | end 26 | end 27 | 28 | def aqueue size 29 | RubyDataStructures::QueueAsArray.new size 30 | end -------------------------------------------------------------------------------- /lib/RubyDataStructures/max_heap.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::MaxHeap < Array 2 | Infinity = 1.0/0 3 | 4 | attr_accessor :heapsize 5 | 6 | # It is assumed that the binary trees rooted at left(i) and right(i) are max heaps, 7 | # but self[i] might be smaller than its children, thus violating the max-heap property. 8 | # max_heapify! lets the value at self[i] float down in the max-heap, 9 | # so that the subtree rooted at index i obeys the max-heap property 10 | def max_heapify!(i) 11 | l = left(i) 12 | r = right(i) 13 | 14 | if l < self.heapsize && self[l] > self[i] 15 | largest = l 16 | else 17 | largest = i 18 | end 19 | 20 | if r < self.heapsize && self[r] > self[largest] 21 | largest = r 22 | end 23 | 24 | if largest != i 25 | exchange(i, largest) 26 | max_heapify!(largest) 27 | end 28 | 29 | return self 30 | end 31 | 32 | # Builds a max-heap from an array 33 | def self.build(array) 34 | heap = self.new(array) 35 | heap.heapsize = array.size 36 | 37 | if heap.heapsize > 0 38 | ((heap.heapsize/2) - 1).downto(0) do |i| 39 | heap.max_heapify!(i) 40 | end 41 | end 42 | 43 | return heap 44 | end 45 | 46 | # Returns the maximum element of the heap 47 | def maximum 48 | return self[0] 49 | end 50 | 51 | # Extracts the maximum of the heap and max_heapifies the remaining heap. 52 | # Returns the maximum of the input heap 53 | def extract_maximum! 54 | raise "Heap Underflow - The heap is empty" if self.heapsize < 1 55 | 56 | max_value = self[0] 57 | self[0] = self[self.heapsize - 1] 58 | self.heapsize = self.heapsize - 1 59 | self.max_heapify!(0) 60 | 61 | return max_value 62 | end 63 | 64 | def increase_key!(i, key) 65 | raise "New key is smaller than the current key" if key < self[i] 66 | 67 | self[i] = key 68 | while (i > 0) && (self[parent(i)] < self[i]) 69 | exchange(i, parent(i)) 70 | i = parent(i) 71 | end 72 | 73 | return self 74 | end 75 | 76 | def insert!(key) 77 | self.heapsize = self.heapsize + 1 78 | self[self.heapsize - 1] = -Infinity 79 | self.increase_key!(self.heapsize - 1, key) 80 | end 81 | 82 | private 83 | 84 | def parent(i) 85 | return ((i+1)/2) - 1 86 | end 87 | 88 | def left(i) 89 | return (2*i) + 1 90 | end 91 | 92 | def right(i) 93 | return (2*i) + 2 94 | end 95 | 96 | def exchange(i, j) 97 | tmp = self[i] 98 | self[i] = self[j] 99 | self[j] = tmp 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /lib/RubyDataStructures/multi_dimensional_array.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::MultiDimensionalArray 2 | def initialize(*dimensions) 3 | @dimensions = Array.new(dimensions.length) 4 | @factors = Array.new(dimensions.length) 5 | product = 1 6 | i = dimensions.length - 1 7 | 8 | while i >= 0 9 | @dimensions[i] = dimensions[i] 10 | @factors[i] = product 11 | product *= dimensions[i] 12 | i -= 1 13 | end 14 | 15 | @data = Array.new(product) 16 | end 17 | 18 | def get_offset(indices) 19 | raise IndexError if indices.length != @dimensions.length 20 | 21 | offset = 0 22 | 23 | (0..(@dimensions.length - 1)).each do |i| 24 | 25 | raise IndexError if indices[i] < 0 || indices[i] >= @dimensions[i] 26 | 27 | offset += @factors[i]*indices[i] 28 | end 29 | 30 | return offset 31 | end 32 | 33 | def [](*indices) 34 | @data[self.get_offset(indices)] 35 | end 36 | 37 | def []=(*indices_and_value) 38 | value = indices_and_value.pop 39 | @data[self.get_offset(indices_and_value)] = value 40 | end 41 | end -------------------------------------------------------------------------------- /lib/RubyDataStructures/queue_as_array.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::QueueAsArray 2 | # Initializes a stack of size +size+ 3 | # The value of +head+ for a new stack is +nil+ 4 | # The value of +tail+ for a new stack is +0+ 5 | def initialize(size = 1) 6 | @length = size 7 | self.reset 8 | end 9 | 10 | # Returns +true+ if the queue is empty 11 | def empty? 12 | @head.nil? 13 | end 14 | 15 | # Returns +true+ if the queue is full 16 | def full? 17 | @head == @tail 18 | end 19 | 20 | # The queue is enqueued with +element+ 21 | def enqueue(element) 22 | raise "Queue Overflow - The queue is full" if self.full? 23 | 24 | @array[@tail] = element 25 | 26 | if @head.nil? 27 | @head = 0 28 | end 29 | 30 | if @tail == @length - 1 31 | @tail = 0 32 | else 33 | @tail = @tail + 1 34 | end 35 | end 36 | 37 | # The queue is dequeued 38 | def dequeue 39 | raise "Queue Underflow - The queue is empty" if self.empty? 40 | 41 | x = @array[@head] 42 | 43 | if @head == @length - 1 44 | @head = 0 45 | else 46 | @head = @head + 1 47 | end 48 | 49 | if @head == @tail 50 | self.reset 51 | end 52 | 53 | return x 54 | end 55 | 56 | # Resets the queue 57 | def reset 58 | @array = Array.new(@length) 59 | @head = nil 60 | @tail = 0 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /lib/RubyDataStructures/ruby_data_structures.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures 2 | 3 | end -------------------------------------------------------------------------------- /lib/RubyDataStructures/singly_linked_list.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::SinglyLinkedList 2 | # Initializes the SinglyLinkedList 3 | def initialize 4 | @sentinel = RubyDataStructures::SinglyLinkedList::Element.new(self, nil) 5 | self.reset 6 | end 7 | 8 | def head 9 | @sentinel.next 10 | end 11 | 12 | def empty? 13 | self.head == @sentinel 14 | end 15 | 16 | def reset 17 | @sentinel.next = @sentinel 18 | end 19 | 20 | # Splices an element onto the front of the linked list 21 | # Arguments: 22 | # *item* => Value to store in the element to be inserted 23 | def insert(item) 24 | element = RubyDataStructures::SinglyLinkedList::Element.new(self, item) 25 | element.next = @sentinel.next 26 | @sentinel.next = element 27 | end 28 | 29 | # Returns the first element with a given key 30 | # Arguments: 31 | # *key* => Key of the element to be searched for 32 | def search(key) 33 | element = self.head 34 | while (element != @sentinel) && (element.key != key) 35 | element = element.next 36 | end 37 | 38 | return element 39 | end 40 | 41 | # Removes the first element with a given key from the linked list 42 | # Arguments: 43 | # *key* => Key of the element to be removed 44 | def delete(key) 45 | element = self.head 46 | prev_element = @sentinel 47 | 48 | while (element != @sentinel) && (element.key != key) 49 | prev_element = element 50 | element = element.next 51 | end 52 | 53 | if element == @sentinel 54 | raise "Argument Error - No element with the key found" 55 | else 56 | prev_element.next = element.next 57 | end 58 | end 59 | end 60 | -------------------------------------------------------------------------------- /lib/RubyDataStructures/singly_linked_list/element.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::SinglyLinkedList::Element 2 | attr_accessor :key 3 | attr_accessor :next 4 | 5 | # Initializes an Element of SinglyLinkedList 6 | # Arguments: 7 | # *list* => Instance of SinglyLinkedList to which the element belongs to 8 | # *key* => Value to be stored in the element. 9 | def initialize(list, key) 10 | @list = list 11 | @key = key 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/RubyDataStructures/stack_as_array.rb: -------------------------------------------------------------------------------- 1 | class RubyDataStructures::StackAsArray 2 | attr_reader :length, :top 3 | 4 | # Initializes a stack of size +size+ 5 | # The value of +top+ for an empty stack is +nil+ 6 | def initialize(size = 1) 7 | @length = size 8 | self.reset 9 | end 10 | 11 | # Returns +true+ if the stack is empty 12 | def empty? 13 | @top.nil? 14 | end 15 | 16 | # Returns +true+ if the stack is full 17 | def full? 18 | @top == @length - 1 19 | end 20 | 21 | def singleton? 22 | @top == 0 23 | end 24 | 25 | # Pushes an element +element+ into the stack 26 | def push(element) 27 | 28 | raise "Stack Overflow - The stack is full" if self.full? 29 | 30 | if self.empty? 31 | @top = 0 32 | else 33 | @top = @top + 1 34 | end 35 | 36 | @array[@top] = element 37 | end 38 | 39 | # Pops the stack 40 | def pop 41 | raise "Stack Underflow - The stack is empty" if self.empty? 42 | 43 | x = @array[@top] 44 | if self.singleton? 45 | @top = nil 46 | else 47 | @top = @top - 1 48 | end 49 | 50 | return x 51 | end 52 | 53 | # Resets the stack 54 | def reset 55 | @array = Array.new(@length) 56 | @top = nil 57 | end 58 | alias_method :reset!, :reset 59 | 60 | def size 61 | @array.size 62 | end 63 | 64 | def first 65 | @array.first 66 | end 67 | 68 | def last 69 | @array[@top] 70 | end 71 | 72 | def each 73 | @array.each do 74 | yield 75 | end 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /lib/RubyDataStructures/version.rb: -------------------------------------------------------------------------------- 1 | module Rubydatastructures 2 | VERSION = "1.1.0" 3 | end -------------------------------------------------------------------------------- /test/RubyDataStructureTest.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | require 'rubygems' 3 | require 'ruby-debug' 4 | 5 | # Individual Test Cases 6 | 7 | require 'test/multi_dimensional_array_test' 8 | require 'test/stack_as_array_test' 9 | require 'test/queue_as_array_test' 10 | require 'test/singly_linked_list_test' 11 | require 'test/singly_linked_list_element_test' 12 | require 'test/doubly_linked_list_test' 13 | require 'test/doubly_linked_list_element_test' -------------------------------------------------------------------------------- /test/doubly_linked_list_element_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class DoublyLinkedListElementTest < Test::Unit::TestCase 7 | def setup 8 | @list = RubyDataStructures::SinglyLinkedList.new 9 | @element = RubyDataStructures::SinglyLinkedList::Element.new(@list, 9) 10 | end 11 | 12 | def test_initialize 13 | assert_equal 9, @element.key 14 | assert_nil @element.next 15 | end 16 | 17 | def test_key 18 | assert_equal 9, @element.key 19 | 20 | @element.key = 3 21 | assert_equal 3, @element.key 22 | end 23 | 24 | def test_next 25 | e1 = @element 26 | e2 = RubyDataStructures::SinglyLinkedList::Element.new(@list, 9) 27 | assert_nil e1.next 28 | assert_nil e2.next 29 | 30 | e1.next = e2 31 | assert_equal e2, e1.next 32 | assert_nil e2.next 33 | 34 | e2.next = e1 35 | assert_equal e2, e1.next 36 | assert_equal e1, e2.next 37 | 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/doubly_linked_list_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class DoublyLinkedListTest < Test::Unit::TestCase 7 | def setup 8 | @list = RubyDataStructures::DoublyLinkedList.new 9 | end 10 | 11 | def test_initialize 12 | assert_nil @list.head.key 13 | assert_nil @list.tail.key 14 | assert @list.empty? 15 | end 16 | 17 | def test_singly_linked_list 18 | assert @list.empty? 19 | assert_nil @list.head.key 20 | assert_nil @list.tail.key 21 | assert_nil @list.search(7).key 22 | assert_nil @list.search(9).key 23 | 24 | @list.insert(7) 25 | assert !@list.empty? 26 | assert_equal 7, @list.head.key 27 | assert_equal 7, @list.tail.key 28 | assert_equal 7, @list.search(7).key 29 | assert_nil @list.search(9).key 30 | 31 | @list.insert(9) 32 | assert !@list.empty? 33 | assert_equal 9, @list.head.key 34 | assert_equal 7, @list.tail.key 35 | assert_equal 7, @list.search(7).key 36 | assert_equal 9, @list.search(9).key 37 | 38 | @list.delete(7) 39 | assert !@list.empty? 40 | assert_equal 9, @list.head.key 41 | assert_equal 9, @list.tail.key 42 | assert_nil @list.search(7).key 43 | assert_equal 9, @list.search(9).key 44 | 45 | assert_raise RuntimeError, "Argument Error - No element with the key found" do 46 | @list.delete(7) 47 | end 48 | assert !@list.empty? 49 | assert_equal 9, @list.head.key 50 | assert_equal 9, @list.tail.key 51 | assert_nil @list.search(7).key 52 | assert_equal 9, @list.search(9).key 53 | 54 | @list.reset 55 | assert @list.empty? 56 | assert_nil @list.head.key 57 | assert_nil @list.tail.key 58 | assert_nil @list.search(7).key 59 | assert_nil @list.search(9).key 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /test/fifo_stack_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class AutoStackTest < Test::Unit::TestCase 7 | def test_fifo_stack 8 | stack = RubyDataStructures::FifoStack.new(2) 9 | 10 | assert stack.empty? 11 | assert !stack.singleton? 12 | assert !stack.full? 13 | assert stack.length == 2 14 | # assert stack.size == 0 15 | 16 | assert_raise RuntimeError, "Stack Underflow - The stack is empty" do 17 | stack.pop 18 | end 19 | 20 | stack.push(1) 21 | assert !stack.empty? 22 | assert stack.singleton? 23 | assert !stack.full? 24 | assert stack.first == 1 25 | assert stack.length == 2 26 | assert stack.last == 1 27 | # assert stack.size == 1 28 | 29 | stack.push(2) 30 | assert !stack.empty? 31 | assert !stack.singleton? 32 | assert stack.full? 33 | assert stack.first == 1 34 | assert stack.last == 2 35 | 36 | stack.push(3) 37 | assert !stack.empty? 38 | assert !stack.singleton? 39 | assert stack.full? 40 | assert stack.size == 2 41 | assert stack.first == 2 42 | assert stack.last == 3 43 | 44 | stack.push(4) 45 | assert !stack.empty? 46 | assert !stack.singleton? 47 | assert stack.full? 48 | assert stack.first == 3 49 | assert stack.last == 4 50 | assert stack.pop == 4 51 | assert !stack.full? 52 | assert stack.size == 2 53 | end 54 | end -------------------------------------------------------------------------------- /test/max_heap_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class MaxHeapTest < Test::Unit::TestCase 7 | def test_build 8 | assert_equal [16, 14, 10, 8, 7, 9, 3, 2, 4, 1], RubyDataStructures::MaxHeap.build([4, 1, 3, 2, 16, 9, 10, 14, 8, 7]) 9 | end 10 | 11 | def test_maximum 12 | array = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 13 | heap = RubyDataStructures::MaxHeap.build(array) 14 | 15 | assert_equal 16, heap.maximum 16 | end 17 | 18 | def test_extract_maximum 19 | array = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 20 | heap = RubyDataStructures::MaxHeap.build(array) 21 | 22 | assert_equal 10, heap.heapsize 23 | assert_equal 16, heap.extract_maximum! 24 | assert_equal 9, heap.heapsize 25 | assert_equal [14, 8, 10, 4, 7, 9, 3, 2, 1, 1], heap 26 | end 27 | 28 | def test_increase_key 29 | array = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 30 | heap = RubyDataStructures::MaxHeap.build(array) 31 | 32 | assert_equal [16, 15, 10, 14, 7, 9, 3, 2, 8, 1], heap.increase_key!(8, 15) 33 | end 34 | 35 | def test_insert 36 | array = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7] 37 | heap = RubyDataStructures::MaxHeap.build(array) 38 | 39 | assert_equal 10, heap.heapsize 40 | assert_equal 16, heap.extract_maximum! 41 | assert_equal 9, heap.heapsize 42 | assert_equal [14, 8, 10, 4, 7, 9, 3, 2, 1, 1], heap 43 | 44 | assert_equal [14, 11, 10, 4, 8, 9, 3, 2, 1, 7], heap.insert!(11) 45 | end 46 | end 47 | -------------------------------------------------------------------------------- /test/multi_dimensional_array_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class MultiDimensionalArrayTest < Test::Unit::TestCase 7 | def setup 8 | @mda = RubyDataStructures::MultiDimensionalArray.new(2,3,4) 9 | end 10 | 11 | def test_multi_dimensional_array 12 | assert_equal nil, @mda[1,2,3] 13 | 14 | @mda[1,2,3] = 5 15 | assert_equal 5, @mda[1,2,3] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /test/queue_as_array_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class QueueAsArrayTest < Test::Unit::TestCase 7 | def test_queue_as_array 8 | queue = RubyDataStructures::QueueAsArray.new(3) 9 | 10 | assert queue.empty? 11 | assert !queue.full? 12 | 13 | assert_raise RuntimeError, "Queue Underflow - The queue is empty" do 14 | queue.dequeue 15 | end 16 | 17 | queue.enqueue(1) 18 | assert !queue.empty? 19 | assert !queue.full? 20 | 21 | assert_equal 1, queue.dequeue 22 | assert queue.empty? 23 | assert !queue.full? 24 | 25 | queue.enqueue(1) 26 | assert !queue.empty? 27 | assert !queue.full? 28 | 29 | queue.enqueue(2) 30 | assert !queue.empty? 31 | assert !queue.full? 32 | 33 | queue.enqueue(3) 34 | assert !queue.empty? 35 | assert queue.full? 36 | 37 | assert_raise RuntimeError, "Queue Overflow - The queue is full" do 38 | queue.enqueue(4) 39 | end 40 | 41 | assert_equal 1, queue.dequeue 42 | assert !queue.empty? 43 | assert !queue.full? 44 | 45 | assert_equal 2, queue.dequeue 46 | assert !queue.empty? 47 | assert !queue.full? 48 | 49 | queue.enqueue(7) 50 | assert !queue.empty? 51 | assert !queue.full? 52 | 53 | assert_equal 3, queue.dequeue 54 | assert !queue.empty? 55 | assert !queue.full? 56 | 57 | assert_equal 7, queue.dequeue 58 | assert queue.empty? 59 | assert !queue.full? 60 | 61 | assert_raise RuntimeError, "Queue Underflow - The queue is empty" do 62 | queue.dequeue 63 | end 64 | end 65 | 66 | def test_queue_as_array_reset 67 | queue = RubyDataStructures::QueueAsArray.new(3) 68 | 69 | assert queue.empty? 70 | assert !queue.full? 71 | 72 | queue.enqueue(1) 73 | queue.enqueue(2) 74 | 75 | assert !queue.empty? 76 | assert !queue.full? 77 | 78 | queue.reset 79 | 80 | assert queue.empty? 81 | assert !queue.full? 82 | end 83 | end 84 | -------------------------------------------------------------------------------- /test/singly_linked_list_element_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class SinglyLinkedListElementTest < Test::Unit::TestCase 7 | def setup 8 | @list = RubyDataStructures::SinglyLinkedList.new 9 | @element = RubyDataStructures::SinglyLinkedList::Element.new(@list, 9) 10 | end 11 | 12 | def test_initialize 13 | assert_equal 9, @element.key 14 | assert_nil @element.next 15 | end 16 | 17 | def test_key 18 | assert_equal 9, @element.key 19 | 20 | @element.key = 3 21 | assert_equal 3, @element.key 22 | end 23 | 24 | def test_next 25 | e1 = @element 26 | e2 = RubyDataStructures::SinglyLinkedList::Element.new(@list, 9) 27 | assert_nil e1.next 28 | assert_nil e2.next 29 | 30 | e1.next = e2 31 | assert_equal e2, e1.next 32 | assert_nil e2.next 33 | 34 | e2.next = e1 35 | assert_equal e2, e1.next 36 | assert_equal e1, e2.next 37 | 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /test/singly_linked_list_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class SinglyLinkedListTest < Test::Unit::TestCase 7 | def setup 8 | @list = RubyDataStructures::SinglyLinkedList.new 9 | end 10 | 11 | def test_initialize 12 | assert_nil @list.head.key 13 | assert @list.empty? 14 | end 15 | 16 | def test_singly_linked_list 17 | assert @list.empty? 18 | assert_nil @list.head.key 19 | assert_nil @list.search(7).key 20 | assert_nil @list.search(9).key 21 | 22 | @list.insert(7) 23 | assert !@list.empty? 24 | assert_equal 7, @list.head.key 25 | assert_equal 7, @list.search(7).key 26 | assert_nil @list.search(9).key 27 | 28 | @list.insert(9) 29 | assert !@list.empty? 30 | assert_equal 9, @list.head.key 31 | assert_equal 7, @list.search(7).key 32 | assert_equal 9, @list.search(9).key 33 | 34 | @list.delete(7) 35 | assert !@list.empty? 36 | assert_equal 9, @list.head.key 37 | assert_nil @list.search(7).key 38 | assert_equal 9, @list.search(9).key 39 | 40 | assert_raise RuntimeError, "Argument Error - No element with the key found" do 41 | @list.delete(7) 42 | end 43 | assert !@list.empty? 44 | assert_equal 9, @list.head.key 45 | assert_nil @list.search(7).key 46 | assert_equal 9, @list.search(9).key 47 | 48 | @list.reset 49 | assert @list.empty? 50 | assert_nil @list.head.key 51 | assert_nil @list.search(7).key 52 | assert_nil @list.search(9).key 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /test/stack_as_array_test.rb: -------------------------------------------------------------------------------- 1 | $:.unshift File.join(File.dirname(__FILE__),'..','lib') 2 | 3 | require 'test/unit' 4 | require 'RubyDataStructures' 5 | 6 | class StackAsArrayTest < Test::Unit::TestCase 7 | def test_stack_as_array 8 | stack = RubyDataStructures::StackAsArray.new(3) 9 | 10 | assert stack.empty? 11 | assert !stack.singleton? 12 | assert !stack.full? 13 | 14 | assert_raise RuntimeError, "Stack Underflow - The stack is empty" do 15 | stack.pop 16 | end 17 | 18 | stack.push(1) 19 | assert !stack.empty? 20 | assert stack.singleton? 21 | assert !stack.full? 22 | 23 | stack.push(2) 24 | assert !stack.empty? 25 | assert !stack.singleton? 26 | assert !stack.full? 27 | 28 | stack.push(3) 29 | assert !stack.empty? 30 | assert !stack.singleton? 31 | assert stack.full? 32 | 33 | assert_raise RuntimeError, "Stack Overflow - The stack is full" do 34 | stack.push(4) 35 | end 36 | 37 | assert_equal 3, stack.pop 38 | assert !stack.empty? 39 | assert !stack.singleton? 40 | assert !stack.full? 41 | 42 | assert_equal 2, stack.pop 43 | assert !stack.empty? 44 | assert stack.singleton? 45 | assert !stack.full? 46 | 47 | stack.push(7) 48 | assert !stack.empty? 49 | assert !stack.singleton? 50 | assert !stack.full? 51 | 52 | assert_equal 7, stack.pop 53 | assert !stack.empty? 54 | assert stack.singleton? 55 | assert !stack.full? 56 | 57 | assert_equal 1, stack.pop 58 | assert stack.empty? 59 | assert !stack.singleton? 60 | assert !stack.full? 61 | 62 | assert_raise RuntimeError, "Stack Underflow - The stack is empty" do 63 | stack.pop 64 | end 65 | end 66 | 67 | def test_stack_as_array_reset 68 | stack = RubyDataStructures::StackAsArray.new(3) 69 | 70 | assert stack.empty? 71 | assert !stack.singleton? 72 | assert !stack.full? 73 | 74 | stack.push(1) 75 | stack.push(2) 76 | 77 | assert !stack.empty? 78 | assert !stack.full? 79 | 80 | stack.reset 81 | 82 | assert stack.empty? 83 | assert !stack.full? 84 | end 85 | end 86 | --------------------------------------------------------------------------------