リスト
4月 17th, 2008 admin Posted in Ruby, アルゴリズムとデータ構造 |
久しぶりの「アルゴリズムとデータ構造シリーズ」です。今回はリスト構造についてです。
C言語では配列を使うときは配列のサイズを宣言する必要があります。しかし配列のサイズがあらかじめわかる場合はいいのですが、いくつ入力があるかわからないときは困ったことになります。そこでリストというデータ構造を使って無限に要素数を増やせる配列のようなものを作ります。
C言語でも一つ増やすときに今よりひとつ大きいサイズの配列を確保してそちらに引っ越すという方法がありますが、あまり効率とは言えません。
データ構造
リストの要素(ノードとかいう)を「データ・次のノードへのポインタ・前のノードへのポインタ」という形式で用意して、ノード同士がそれぞれの前後のデータの場所を記憶しておくというデータ構造。
誰が前の人で、誰が後ろの人かは知っている。だけど全体は(そのサイズすら)しらない。
町内の回覧板みたいなシステムですね。
次の人だけを知っているリストを「単方向リスト」、前後の人を知っているリストを「双方向リスト」と言います。
コード
Rubyなのでデータをオブジェクト、ポインタは参照で表現しました。
-
class Node
-
attr_accessor :prev,:next,:data
-
-
def initialize(data)
-
@data = data
-
end
-
end
-
-
firstnode = lastnode = nil
-
-
-
datas = [1,2,3,4,5,6,7,8,9]
-
datas.each do |x|
-
node = Node.new(x)
-
node.next = nil
-
-
unless lastnode.nil?
-
lastnode.next = node
-
node.prev = lastnode
-
lastnode = node
-
else
-
firstnode = lastnode = node
-
node.prev = nil
-
end
-
end
-
-
-
p firstnode.next.next.prev.data
出力
2
まとめ
配列というと僕の場合は入門書とかにでてくる分別できるゴミ箱みたいなのが頭に浮かぶ。2次元配列になったとしても思い浮かぶのは玉子のパックだ。だけどリストを思い浮かべてみるとかなりカッコいい!頭に浮かぶのはイタリアのマフィア。自分の部下とボスは知っているがボスのボスは知らないし(知れない)、自分の部下がどんな部下を使っているのかも知らない(知る必要がない)。組織のサイズも知らないし関係ない。とにかくボスの命令を遂行するだけ・・・単にJOJO脳になってるだけですね。はい。
ちなみに僕の家の回覧板の場合は、誰が持ってくるか知らないので単方向リストです。いつも勝手にポストにはいってます。
※このシリーズは私がRubyでアルゴリズムとデータ構造を基礎から学ぶ記録です。全体の目次はこちらへ。
4月 17th, 2008 at 1:43:18
[...] リスト はてなに追加 MyYahoo!に追加 del.icio.usに追加 livedoorClipに追加 5 Responses to “Rubyでアルゴリズムとデータ構造” [...]
4月 18th, 2008 at 5:11:35
rubyでlistなんてシュールだねぇと一瞬思ったんだけど,
実際,自作listと組み込みArrayのどちらが速いのか
気になったので試してみた.
結果から言うと,listの方が速かった.
Arrayの使い方を多少変えても,大勢は変わらい.
まあ実際には,ランダムアクセスしなきゃならん
アルゴリズムなのかどうかも関係してくるし,
プログラムの作りやすさの方が大事な事もあるだろうから
一概には言えないけども.
以下に実行結果.
$ cat list.rb
class Node
attr_accessor :prev,:next,:data
def initialize(data)
@data = data
end
end
firstnode = lastnode = nil
datas = [1,2,3,4,5,6,7,8,9]
datas.each do |x|
node = Node.new(x)
node.next = nil
unless lastnode.nil?
lastnode.next = node
node.prev = lastnode
lastnode = node
else
firstnode = lastnode = node
node.prev = nil
end
end
n = firstnode
100000.times{
x = 0
8.times{
x += n.data
n = n.next
}
x += n.data
8.times{
x += n.data
n = n.prev
}
x += n.data
}
$ time ruby list.rb
real 0m1.680s
user 0m1.261s
sys 0m0.418s
$ cat array1.rb
datas = [1,2,3,4,5,6,7,8,9]
100000.times{
x = 0
datas.each{|data| x += data }
datas.reverse_each{|data| x += data}
}
$ time ruby array1.rb
real 0m2.274s
user 0m1.430s
sys 0m0.843s
$ cat array2.rb
datas = [1,2,3,4,5,6,7,8,9]
100000.times{
x = 0
datas.each{|data| x += data }
datas.each{|data| x += data }
}
$ time ruby array2.rb
real 0m2.127s
user 0m1.369s
sys 0m0.756s
$ cat array3.rb
datas = [1,2,3,4,5,6,7,8,9]
100000.times{
x = 0
9.times{|i| x += datas[i] }
9.times{|i| x += datas[i] }
}
$ time ruby array3.rb
real 0m2.396s
user 0m1.647s
sys 0m0.747s
4月 18th, 2008 at 17:23:38
ナイスすぎるコメント
次回からはコードと書いたらきちんと検証します。
有難う御座います
7月 6th, 2008 at 3:23:51
[...] ツリー構造とは樹形図のようになったデータ構造のことです。Windowsのファイル構造はツリー構造ですね。 難しそうに感じますが、以前やったリスト構造では、データが次のノードへのポインタを一つしかもっていなかったものを複数にするというだけで実現できます。 [...]
8月 8th, 2008 at 0:02:55
Ruby でデータ構造の勉強をしようと思ったらこちらにたどり着きました。
> ポインタは参照で表現しました。
とはどういう意味ですか?コードの中のどの部分に表れていますか?
8月 8th, 2008 at 23:11:33
>class Node
> attr_accessor :prev,:next,:data
本のなかでは、この前と後ろのノードのアドレスを示すprevとnextはC言語のポインタを使っていますが、Rubyにはポインタはないので参照を使ったという意味です。
ポインタと参照は同じものではありませんが、今回は参照でも同じ機能を果たせるので参照を使用しています。