単方向リスト(カーソル版)
ポインタではなく配列を利用した単方向リスト。
空き領域の管理が面白かった。
#linkedlist by cursor class Node attr_reader :data attr_accessor :next def initialize(obj) @data = obj @next = nil end end class LinkedList attr_reader :size def initialize(size) @list = Array.new(size) @head = nil @tail = nil @size = 0 @free = Array.new(0) (size - 1).step(0, -1){|i| @free << i } end def showFields printf "@size={#@size} @head={#@head} @tail={#@tail}\n" end def insertFront(node) if @size == 0 #初回追加時 @head = @free.pop @tail = @head @list[@head] = node @size += 1 else #2回目以降 return nil unless newHead = @free.pop node.next = @head @list[newHead] = node @head = newHead @size += 1 end end def insertRear(node) if @size == 0 #初回追加 @head = @free.pop @tail = @head @list[@tail] = node @size += 1 else #2回目以降 return nil unless newTail = @free.pop @list[@tail].next = newTail @list[newTail] = node @tail = newTail @size += 1 end end def removeFront if @size > 0 @tail = nil if @size == 1 @free.push(@head) newHead = @list[@head].next @list[@head] = nil @head = newHead @size -= 1 end end def clear until @size == 0 do removeFront end end def removeRear if @size == 1 removeFront elsif @size > 1 targetIndex = @list[@head].next prevTail = @head until targetIndex == @tail do prevTail = targetIndex targetIndex = @list[prevTail].next end @list[@tail] = nil @list[prevTail].next = nil @free.push(@tail) @tail = prevTail @size -= 1 end end def to_s string = String.new currentIndex = @head until currentIndex == nil do string = string + @list[currentIndex].data.to_s + " " currentIndex = @list[currentIndex].next end return string end def get(index) node = nil if 0 <= index && index < @size c = 0 node = @list[@head] until c == index do node = @list[node.next] c += 1 end end return node end def remove(index) if index < 0 return elsif index == 0 removeFront elsif index == @list.size - 1 removeRear else c = 1 prevIndex = @head targetIndex = @list[@head].next #対象のindexまで進む until c == index do prevIndex = targetIndex targetIndex = @list[prevIndex].next c += 1 end #前のノードのnextを削除対象ノードのnextにする @list[prevIndex].next = @list[targetIndex].next #削除対象ノードをリストからクリア @list[targetIndex] = nil #フリースタックに削除indexをpush @free.push(targetIndex) @size -= 1 end end end
実装→バグ取り・確認で合計6時間ほど。
時間がかかった理由としては、
「自分のなかでどういう動作のものを作るのかというのがはっきりしていなかった」から。
また、「テストをしっかり行えていなかった」ことも原因となった。
両者ともに、配列、変数の値のトレースで解決した。