EfficientFIFO
parent
981cdc92b8
commit
313374d58e
|
@ -17,3 +17,20 @@ describe "FIFO" do
|
||||||
fifo.data.should eq([5, 4] of Int32)
|
fifo.data.should eq([5, 4] of Int32)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "EfficientFIFO" do
|
||||||
|
it "add and remove values" do
|
||||||
|
fifo = EfficientFIFO(Int32).new 3 # Only 3 allowed entries.
|
||||||
|
(fifo << 1).should be_nil # there is still room in the fifo
|
||||||
|
(fifo << 2).should be_nil # there is still room in the fifo
|
||||||
|
(fifo << 3).should be_nil # last entry without exceeding the allowed size
|
||||||
|
(fifo << 4).should eq 1 # -> 1 (least recently used data)
|
||||||
|
(fifo << 4).should be_nil # -> nil (already in the fifo)
|
||||||
|
(fifo << 2).should be_nil # -> nil (already in the fifo)
|
||||||
|
(fifo << 5).should eq 3 # -> 3 (least recently used data)
|
||||||
|
fifo.list.to_s.should eq "[ 5, 2, 4 ]"
|
||||||
|
|
||||||
|
fifo.delete 2
|
||||||
|
fifo.list.to_s.should eq "[ 5, 4 ]"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -94,6 +94,19 @@ describe "DoubleLinkedList" do
|
||||||
list.shift.value.should eq 4
|
list.shift.value.should eq 4
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "unshift" do
|
||||||
|
list = DoubleLinkedList(Int32).new
|
||||||
|
list.unshift 1
|
||||||
|
list.unshift 2
|
||||||
|
list.unshift 3
|
||||||
|
list.unshift 4
|
||||||
|
list.pop
|
||||||
|
node = list.unshift 4
|
||||||
|
list.to_s.should eq "[ 4, 4, 3, 2 ]"
|
||||||
|
list.delete node
|
||||||
|
list.to_s.should eq "[ 4, 3, 2 ]"
|
||||||
|
end
|
||||||
|
|
||||||
it "peek" do
|
it "peek" do
|
||||||
list = DoubleLinkedList(Int32).new
|
list = DoubleLinkedList(Int32).new
|
||||||
list << 1 << 2 << 3 << 4
|
list << 1 << 2 << 3 << 4
|
||||||
|
|
36
src/fifo.cr
36
src/fifo.cr
|
@ -1,3 +1,5 @@
|
||||||
|
require "./list.cr"
|
||||||
|
|
||||||
# This class enables to keep track of used data.
|
# This class enables to keep track of used data.
|
||||||
#
|
#
|
||||||
# Each time a value is added, it is put in a FIFO structure.
|
# Each time a value is added, it is put in a FIFO structure.
|
||||||
|
@ -46,6 +48,40 @@ end
|
||||||
|
|
||||||
# TODO: this is a draft.
|
# TODO: this is a draft.
|
||||||
class EfficientFIFO(V)
|
class EfficientFIFO(V)
|
||||||
|
# This array is used as the *fifo structure*.
|
||||||
|
property list : DoubleLinkedList(V)
|
||||||
|
property hash : Hash(V, DoubleLinkedList::Node(V))
|
||||||
|
|
||||||
def initialize(@max_entries : UInt32)
|
def initialize(@max_entries : UInt32)
|
||||||
|
@list = DoubleLinkedList(V).new
|
||||||
|
@hash = Hash(V, DoubleLinkedList::Node(V)).new
|
||||||
|
end
|
||||||
|
|
||||||
|
# Pushes a value in the FIFO and gets the oldest value whether it exceeds the allowed number of entries.
|
||||||
|
# NOTE: `#<<(v : V)` is (almost) the only function since it's enough for the intended use, feel free to improve this.
|
||||||
|
def <<(v : V) : V?
|
||||||
|
if node = hash[v]?
|
||||||
|
list.delete node
|
||||||
|
end
|
||||||
|
|
||||||
|
# push as the first value of the structure
|
||||||
|
node = @list.unshift v
|
||||||
|
hash[v] = node
|
||||||
|
|
||||||
|
# remove least recently used entry if `@list` is too big
|
||||||
|
if list.size > @max_entries
|
||||||
|
node = @list.pop
|
||||||
|
hash.delete node.value
|
||||||
|
node.value
|
||||||
|
else
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Removes a value.
|
||||||
|
def delete(v : V)
|
||||||
|
if node = hash[v]?
|
||||||
|
list.delete node
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
32
src/list.cr
32
src/list.cr
|
@ -88,7 +88,37 @@ class DoubleLinkedList(V)
|
||||||
new_node
|
new_node
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Removes an entry.
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# list = DoubleLinkedList(Int32).new
|
||||||
|
# list << 1 << 2 << 3 << 4 # -> [ 1, 2, 3, 4 ]
|
||||||
|
# list.delete_at 2 # -> [ 1, 2, 4 ]
|
||||||
|
# ```
|
||||||
|
def delete(n : Node(V)) : Node(V)
|
||||||
|
if n == @first
|
||||||
|
@first = n.next
|
||||||
|
end
|
||||||
|
if n == @last
|
||||||
|
@last = n.previous
|
||||||
|
end
|
||||||
|
if prev_node = n.previous
|
||||||
|
prev_node.next = n.next
|
||||||
|
end
|
||||||
|
if next_node = n.next
|
||||||
|
next_node.previous = n.previous
|
||||||
|
end
|
||||||
|
@size -= 1
|
||||||
|
n
|
||||||
|
end
|
||||||
|
|
||||||
# Removes an entry at an index.
|
# Removes an entry at an index.
|
||||||
|
#
|
||||||
|
# ```
|
||||||
|
# list = DoubleLinkedList(Int32).new
|
||||||
|
# list << 1 << 2 << 3 << 4 # -> [ 1, 2, 3, 4 ]
|
||||||
|
# list.delete_at 2 # -> [ 1, 2, 4 ]
|
||||||
|
# ```
|
||||||
def delete_at(index : Int32) : Node(V)
|
def delete_at(index : Int32) : Node(V)
|
||||||
if index == 0
|
if index == 0
|
||||||
shift
|
shift
|
||||||
|
@ -204,7 +234,7 @@ class DoubleLinkedList(V)
|
||||||
@size += 1
|
@size += 1
|
||||||
new_node
|
new_node
|
||||||
else
|
else
|
||||||
push(value)
|
push value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue