EfficientFIFO
This commit is contained in:
parent
981cdc92b8
commit
313374d58e
@ -17,3 +17,20 @@ describe "FIFO" do
|
||||
fifo.data.should eq([5, 4] of Int32)
|
||||
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
|
||||
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
|
||||
list = DoubleLinkedList(Int32).new
|
||||
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.
|
||||
#
|
||||
# Each time a value is added, it is put in a FIFO structure.
|
||||
@ -46,6 +48,40 @@ end
|
||||
|
||||
# TODO: this is a draft.
|
||||
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)
|
||||
@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
|
||||
|
32
src/list.cr
32
src/list.cr
@ -88,7 +88,37 @@ class DoubleLinkedList(V)
|
||||
new_node
|
||||
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.
|
||||
#
|
||||
# ```
|
||||
# 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)
|
||||
if index == 0
|
||||
shift
|
||||
@ -204,7 +234,7 @@ class DoubleLinkedList(V)
|
||||
@size += 1
|
||||
new_node
|
||||
else
|
||||
push(value)
|
||||
push value
|
||||
end
|
||||
end
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user