{"id":18669958,"url":"https://github.com/blahah/datastructures","last_synced_at":"2025-10-08T23:34:57.659Z","repository":{"id":10125700,"uuid":"12196163","full_name":"blahah/datastructures","owner":"blahah","description":"A collection of data structures in Ruby for my data structures challenge","archived":false,"fork":false,"pushed_at":"2014-08-17T10:43:37.000Z","size":2104,"stargazers_count":55,"open_issues_count":0,"forks_count":15,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-10-07T15:38:21.084Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://rik.smith-unna.com/2013/08/18/data-structures-challenge","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blahah.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-08-18T14:09:06.000Z","updated_at":"2024-11-01T07:46:00.000Z","dependencies_parsed_at":"2022-08-30T14:23:06.669Z","dependency_job_id":null,"html_url":"https://github.com/blahah/datastructures","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/blahah/datastructures","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blahah%2Fdatastructures","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blahah%2Fdatastructures/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blahah%2Fdatastructures/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blahah%2Fdatastructures/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blahah","download_url":"https://codeload.github.com/blahah/datastructures/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blahah%2Fdatastructures/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000728,"owners_count":26082862,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-08T02:00:06.501Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T08:49:19.981Z","updated_at":"2025-10-08T23:34:57.631Z","avatar_url":"https://github.com/blahah.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"datastructures\n==============\n\nA collection of data structures in Ruby, made for my [data structures challenge](http://blahah.net/2013/08/18/data-structures-challenge/)\n\n[![Gem Version](https://badge.fury.io/rb/datastructures.png)][gem]\n[![Build Status](https://secure.travis-ci.org/Blahah/datastructures.png?branch=master)][travis]\n[![Dependency Status](https://gemnasium.com/Blahah/datastructures.png?travis)][gemnasium]\n[![Code Climate](https://codeclimate.com/github/Blahah/datastructures.png)][codeclimate]\n[![Coverage Status](https://coveralls.io/repos/Blahah/datastructures/badge.png?branch=master)][coveralls]\n\n[gem]: https://badge.fury.io/rb/datastructures\n[travis]: https://travis-ci.org/Blahah/datastructures\n[gemnasium]: https://gemnasium.com/Blahah/datastructures\n[codeclimate]: https://codeclimate.com/github/Blahah/datastructures\n[coveralls]: https://coveralls.io/r/Blahah/datastructures\n\n## Installation\n\n`gem install datastructures`\n\n## List of data structures\n\n1. queue\n2. stack\n3. tree\n4. linked list\n5. adjacency list (graph)\n6. deque\n7. priority queue\n8. priority deque\n9. binary tree\n\n## Day 1: Queue\n\nA queue is a simple container-based structure that mimics a real-life queue (e.g. waiting in line at the bank). It is FIFO (first-in-first-out), meaning that when you retrieve items from the queue, they are returned in the order in which they entered. Ruby Arrays provide methods that make Queue implementation trivially easy, but having them named appropriately and contained in a convenience class is worth it to see how they are implemented, and because other structures will inherit from this one. An alternate implementation could be done using a linked list.\n\nUsage:\n\n```ruby\nrequire 'datastructures'\nqueue = DataStructures::Queue.new\nqueue.enqueue('first')\nqueue.enqueue('second')\nqueue.size # =\u003e 2\nqueue.empty? # =\u003e false\nqueue.front # =\u003e 'first'\nqueue.back # =\u003e 'second'\nqueue.dequeue # =\u003e 'first'\nqueue.dequeue # =\u003e 'second'\nqueue.dequeue # =\u003e RuntimeError, \"Queue underflow: nothing to dequeue\"\n```\n\n## Day 2: Stack\n\nThe stack is the sibling of the queue. It mimicks a real-life stack (e.g. of paper). It is FILO (first-in-last-out), so that when items are retrieved from the stack, they are returned in the reverse of the order in which they were added. Again, Ruby Arrays provide a perfect container. As with the Queue, it could also be implemented using a linked list.\n\nUsage:\n\n```ruby\nrequire 'datastructures'\nstack = DataStructures::Stack.new\nstack.push('first')\nstack.push('second')\nstack.size # =\u003e 2\nstack.empty? # =\u003e false\nstack.top # =\u003e 'second'\nstack.bottom # =\u003e 'first'\nstack.pop # =\u003e 'second'\nstack.pop # =\u003e 'first'\nstack.pop # =\u003e RuntimeError, \"Stack underflow: nothing to pop\"\n```\n\n## Day 3: Tree\n\nA tree is a directed graph where any two nodes are connected by only one edge, and there is a specified 'root' node, away from which all edges are directed. For any edge, the node that it points from is the *parent*, and the node it points to is the *child*. This implementation is currently very crude, and I hope to expand it by:\n\n- separating the node and tree classes\n- including search and shortest path algorithms\n- include more traversal algorithms\n\nCurrently the implementation offers the ability to construct a tree and traverse it manually using family methods (*parent*, *child*, *siblings*, *descendents*). Nodes can have associated data.\n\n```ruby\nrequire 'datastructures'\n\n# start with a root TreeNode\ntree = DataStructures::TreeNode.new('root node')\ntree.is_root? # =\u003e true\ntree.is_leaf? # =\u003e true\n\n# children are also TreeNodes\nchild1 = DataStructures::TreeNode.new('child')\ntree.add_child(child1)\ntree.child_count # =\u003e 1\ntree.add_child(DataStructures::TreeNode.new('another child'))\ntree.child_count # =\u003e 2\ntree.is_root? # =\u003e true\ntree.is_leaf? # =\u003e false\nchild1.is_leaf? # =\u003e true\n\n# we can traverse by querying the family\ntree.siblings # =\u003e []\nchild1.siblings.map{ |sibling| sibling.data } # =\u003e [\"another child\"]\n\nchild1.parent == tree # =\u003e true\nchild1.parent == child.siblings.first.parent # =\u003e true\n\ntree.descendents.map { |d| d.data } # =\u003e [\"child\", \"another child\"]\n```\n\n## Day 4: Linked List\n\nA linked list is a group of items which are ordered, and where the ordering is determined solely by the information each item contains about its neighbours.\n\nThis implementation is a doubly-linked list, which means that each item retains a reference to the *next* and *previous* items in the list.\n\nThe advantage of a linked list over a traditional array is that elements can be inserted and deleted efficiently.\n\n```ruby\nll = DataStructures::LinkedList.new('one')\nll.first.data # =\u003e 'one'\nll[0] # =\u003e 'one'\nll \u003c\u003c 'two' # =\u003e [\"one\", \"two\"]\nll.size # =\u003e 2\nll.length # =\u003e 2\nll.last.data # =\u003e 'two'\nll[ll.size - 1] # =\u003e 'two'\n\n# linked lists can act as stacks\nll.push 'three' # =\u003e [\"one\", \"two\", \"three\"]\nll.size # =\u003e 3\nll.pop # =\u003e \"three\"\nll.size # =\u003e 2\nputs ll # =\u003e [\"one\", \"two\"]\n\n# or as queues\nll.push 'three' # =\u003e [\"one\", \"two\", \"three\"]\nll.shift # =\u003e 'one'\nll.size # =\u003e 2\nll.first.data 'two'\n\n# we can insert and delete\nll.insert(1, 'one point five') # =\u003e [\"two\", \"one point five\", \"three\"]\nll.delete(1)\nll.to_s # =\u003e ['two', 'three']\n```\n\n## Day 5: Adjacency List\n\nAn adjacency list is a structure for representing a graph. Nodes are named; the name can be any hashable object. Data can be stored in nodes, but not edges. The graph can be traversed manually by querying the neighbours of a node.\n\nThe implementation is currently basic. I plan to improve it by:\n\n* implementing depth- and breadth-first search\n* implementing Dijkstra's algorithm for finding the shortest path between two nodes\n* visualise the graph (maybe d3.js)\n\n```ruby\nrequire 'datastructures'\n\nal = DataStructures::AdjacencyList.new\n\nal.add('one', 1, [2])\nal.add('two', 2, [3])\nal.add('three', 3, [1])\nal.add('four', 4, [2])\n\nal.get_node_value(1) # =\u003e 'one'\nal.set_node_value(1, 'new value')\n\nal.neighbours(1) # =\u003e [2]\nal.adjacent?(2, 3) # =\u003e true\nal.adjacent?(1, 4) # =\u003e false\n\nal.add_edge(1, 4)\nal.adjacent?(1, 4) # =\u003e true\n\nal.delete_edge(2, 3)\nal.adjacent?(2, 3) # =\u003e false\n\nal.to_s\n# 1 (new value) =\u003e [2, 4]\n# 2 (two) =\u003e []\n# 3 (three) =\u003e [1]\n# 4 (four) =\u003e [2]\n\n```\n\n## Day 6: Deque\n\nA Deque is a queue which allows adding and removing items at both ends.\n\n```ruby\nrequire 'datastructures'\n\ndq = DataStructures::Dequeue.new\ndq.enqueue('first') # =\u003e ['first']\ndq.enqueue('second') # =\u003e ['first', 'second']\ndq.front_enqueue('third') # =\u003e ['third', 'first', 'second']\ndq.size # =\u003e 3\ndq.empty? # =\u003e false\ndq.front # =\u003e 'third'\ndq.back # =\u003e 'second'\ndq.dequeue # =\u003e 'third'\ndq.back_dequeue # =\u003e 'second'\ndq.dequeue # =\u003e RuntimeError, \"Queue underflow: nothing to dequeue\"\n```\n\n## Day 7: Priority Queue\n\nA Priority Queue is a queue where items can be added at arbitrary positions in the queue.\nDequeuing always returns the item with the highest priority.\n\n```ruby\npq = DataStructures::PriorityQueue.new\npq.enqueue('first', 0) # =\u003e ['first']\npq.enqueue('second', 1) # =\u003e ['second', 'first']\npq.enqueue('third', 0) # =\u003e ['second', 'first', 'third']\n\n# if priority is omitted, defaults to 0 (so items get added to the back of the queue)\npq.enqueue('fourth') # =\u003e ['second', 'first', 'third', 'fourth']\n```\n\n## Day 8: Priority Deque\n\nA Priority Deque is a deque where items can be added at arbitrary positions in the queue.\nDequeueing can return either the highest or lowest priority item depending on the method used.\n\n```ruby\npd = DataStructures::PriorityDeque.new\npd.enqueue(1, 0) # =\u003e [1]\npd.enqueue(2).enqueue(3).enqueue(4) # =\u003e [1, 2, 3, 4]\npd.enqueue(5, 2) # =\u003e [5, 1, 2, 3, 4]\npd.dequeue # =\u003e 5\npq.back_dequeue # =\u003e 4\n```\n\n## Day 9: Binary Tree\n\nA binary tree is a tree in which each node can have a maximum of two children. The children are designated _left_ and _right_. All TreeNode methods are available except _:add_child_ and _:remove_child!_.\n\n```ruby\nbt = DataStructures::BinaryTreeNode\nroot = bt.new(1)\nleftchild = bt.new(2)\nrightchild = bt.new(3)\nroot.add_left_child leftchild\nroot.add_right_child rightchild\nroot.children # =\u003e [2, 3]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblahah%2Fdatastructures","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblahah%2Fdatastructures","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblahah%2Fdatastructures/lists"}