Skip to content

Instantly share code, notes, and snippets.

@mustafaturan
Last active June 8, 2021 21:07
Show Gist options
  • Save mustafaturan/455aedc73c5cdb1b4542 to your computer and use it in GitHub Desktop.
Save mustafaturan/455aedc73c5cdb1b4542 to your computer and use it in GitHub Desktop.
Ruby Stack Implementation With Linked List
# Mustafa Turan
# coded at 30.11.2015 with NO LICENSE
# Feel free to use/modify/distribute/reimplement
# node.rb
class Node
attr_accessor :node_ref
attr_reader :val
def initialize(node_ref, val)
@node_ref = node_ref
@val = val
end
end
# stack.rb
class Stack
attr_reader :init_node
def push(val)
@init_node = Node.new(@init_node, val)
end
def pop
if @init_node
@init_node, pop_val = @init_node.node_ref, @init_node.val
return pop_val
end
raise StandardError, 'Stack is empty!'
end
def top
@init_node.val
end
end
# stack_spec.rb
require 'spec_helper'
describe Stack do
let(:stack) { Stack.new }
describe '#push' do
it 'adds new node to stack' do
expect(stack.init_node).to eql nil
node_1 = Node.new(nil, 1)
node_2 = Node.new(node_1, 2)
node_3 = Node.new(node_2, 3)
expect(stack.push(1).val).to eql node_1.val
expect(stack.push(2).node_ref.val).to eql node_2.node_ref.val
expect(stack.push(3).val).to eql node_3.val
end
end
describe '#pop' do
it 'pops always last element' do
stack.push 1
stack.push 2
stack.push 3
expect(stack.pop).to eql 3
expect(stack.pop).to eql 2
expect(stack.pop).to eql 1
end
it 'can not pop when stack empty' do
expect { stack.pop }.to raise_error(StandardError)
stack.push 1
expect(stack.pop).to eql 1
expect { stack.pop }.to raise_error(StandardError)
end
end
describe '#top' do
it 'return always last element' do
stack.push 1
expect(stack.top).to eql 1
stack.push 2
expect(stack.top).to eql 2
stack.pop
expect(stack.top).to eql 1
end
end
end
@mikhailov
Copy link

hey @mustafaturan, how about slightly different naming for variables and also using Struct to define Node's structure rather than class?

# MIT license
Node = Struct.new(:next, :data)

class Stack
  def push(data)
    @head = Node.new(@head, data)
  end

  def pop
    if @head.nil?
      return
    end

    data = @head.data
    @head = @head.next
    return data
  end

  def head
    @head.data
  end
end

require 'minitest/autorun'
class StackTest < Minitest::Test
  def setup
    @stack = Stack.new
  end

  def test_stack_push_1
    @stack.push('first')
    assert_equal 'first', @stack.head
  end

  def test_stack_push_2
    @stack.push('first')
    @stack.push('second')
    assert_equal 'second', @stack.head
  end

  def test_stack_pop_1
    assert_nil @stack.pop
  end

  def test_stack_pop_2
    @stack.push('first')
    assert_equal 'first', @stack.pop
  end

  def test_stack_pop_3
    @stack.push('first')
    @stack.push('second')
    assert_equal 'second', @stack.pop
  end
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment