リスト

4月 17th, 2008 admin Posted in Ruby, アルゴリズムとデータ構造 |

久しぶりの「アルゴリズムとデータ構造シリーズ」です。今回はリスト構造についてです。

C言語では配列を使うときは配列のサイズを宣言する必要があります。しかし配列のサイズがあらかじめわかる場合はいいのですが、いくつ入力があるかわからないときは困ったことになります。そこでリストというデータ構造を使って無限に要素数を増やせる配列のようなものを作ります。

C言語でも一つ増やすときに今よりひとつ大きいサイズの配列を確保してそちらに引っ越すという方法がありますが、あまり効率とは言えません。

データ構造

リストの要素(ノードとかいう)を「データ・次のノードへのポインタ・前のノードへのポインタ」という形式で用意して、ノード同士がそれぞれの前後のデータの場所を記憶しておくというデータ構造。

誰が前の人で、誰が後ろの人かは知っている。だけど全体は(そのサイズすら)しらない。
町内の回覧板みたいなシステムですね。

次の人だけを知っているリストを「単方向リスト」、前後の人を知っているリストを「双方向リスト」と言います。

コード

Rubyなのでデータをオブジェクト、ポインタは参照で表現しました。

RUBY:
  1. class Node
  2.   attr_accessor :prev,:next,:data
  3.  
  4.   def initialize(data)
  5.     @data = data
  6.   end
  7. end
  8.  
  9. firstnode = lastnode = nil
  10.  
  11.  
  12. datas = [1,2,3,4,5,6,7,8,9]
  13. datas.each do |x|
  14.   node = Node.new(x)
  15.   node.next = nil
  16.  
  17.   unless lastnode.nil?
  18.     lastnode.next = node
  19.     node.prev = lastnode
  20.     lastnode = node
  21.   else
  22.     firstnode = lastnode = node
  23.     node.prev = nil
  24.   end
  25. end
  26.  
  27.  
  28. p firstnode.next.next.prev.data

出力

2

まとめ

配列というと僕の場合は入門書とかにでてくる分別できるゴミ箱みたいなのが頭に浮かぶ。2次元配列になったとしても思い浮かぶのは玉子のパックだ。だけどリストを思い浮かべてみるとかなりカッコいい!頭に浮かぶのはイタリアのマフィア。自分の部下とボスは知っているがボスのボスは知らないし(知れない)、自分の部下がどんな部下を使っているのかも知らない(知る必要がない)。組織のサイズも知らないし関係ない。とにかくボスの命令を遂行するだけ・・・単にJOJO脳になってるだけですね。はい。

ちなみに僕の家の回覧板の場合は、誰が持ってくるか知らないので単方向リストです。いつも勝手にポストにはいってます。

※このシリーズは私がRubyでアルゴリズムとデータ構造を基礎から学ぶ記録です。全体の目次はこちらへ。

6 Responses to “リスト”

  1. [...] リスト はてなに追加 MyYahoo!に追加 del.icio.usに追加 livedoorClipに追加 5 Responses to “Rubyでアルゴリズムとデータ構造” [...]

  2. 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

  3. ナイスすぎるコメント
    次回からはコードと書いたらきちんと検証します。
    有難う御座います

  4. [...] ツリー構造とは樹形図のようになったデータ構造のことです。Windowsのファイル構造はツリー構造ですね。 難しそうに感じますが、以前やったリスト構造では、データが次のノードへのポインタを一つしかもっていなかったものを複数にするというだけで実現できます。 [...]

  5. Ruby でデータ構造の勉強をしようと思ったらこちらにたどり着きました。

    > ポインタは参照で表現しました。
    とはどういう意味ですか?コードの中のどの部分に表れていますか?

  6. >class Node
    > attr_accessor :prev,:next,:data
    本のなかでは、この前と後ろのノードのアドレスを示すprevとnextはC言語のポインタを使っていますが、Rubyにはポインタはないので参照を使ったという意味です。

    ポインタと参照は同じものではありませんが、今回は参照でも同じ機能を果たせるので参照を使用しています。

Leave a Reply