Perlで学ぼう!文系プログラマのための、知識ゼロからのデータ構造と計算量

 Perlで学ぼう!文系プログラマのための、知識ゼロからのデータ構造と計算量

6521324f6ab5266cdcde1dd05945a27b?s=128

Shinpei Maruyama

August 21, 2015
Tweet

Transcript

  1. by しんぺい a.k.a. 猫型蓄音機 Perlで学ぼう! 文系プログラマのための 知識ゼロからの データ構造と計算量

  2. あんただれ • しんぺいとか猫型とかいう名前で呼 ばれています • rerakuという会社で働いてます • 仕事ではScala, Perl, Ruby

  3. あんただれ • Github:Shinpeim • process-book • 新潟非在住 Niigata.pm 主催です •

    趣味でバンド • 11/14高円寺ペンギンハウス
  4. ペンギンハウス

  5. ペンギンハウス

  6. 今日やること • データ構造と計算量について、簡単 に解説します • 基本的なことしかやりません • ハイレベルプログラマ諸氏は今すぐ 別の部屋で有意義な時間を過ごすん だ!!

  7. 事前準備

  8. Cの変数とメモリ

  9. 何がおきてる?

  10. int のメモリを確保 JOUB

  11. 1を代入 JOUB 

  12. bも同様に JOUB  JOUC 

  13. c も同様に JOUD  JOUB  JOUC 

  14. CPUが足し算してcに代入 JOUD  JOUB  JOUC 

  15. ポイント • 変数は箱ではない!!!!!! • メモリです • たくさん用意すれば用意するほどメ モリを消費する

  16. メモリとポインタ

  17. 何がおきてる?

  18. 実はメモリには番地があります B  10000番

  19. 番地を取得 B  10000番

  20. 番地を保存する4byte確保 TIPSU  C B  10000番

  21. 番地を代入 TIPSU C  B  10000番

  22. bの中身を10進数で表示 TIPSU C  B  10000番

  23. bの番地の指し示す先を見て 10000番 TIPSU C  B 

  24. short* なので2バイト読む TIPSU C  B 

  25. ポイント • ポインタの中には「メモリ上の位置」を 表す数字が入ってる • その数字の番地から、ポインタが示す型 のバイト数だけ読めばポインタの指す値 を読むことができる • こうやって「値につながる値」を作るこ

    とができる
  26. 練習問題 へんな値が出力されるのはなぜ?

  27. Perlの場合

  28. 何がおきてる?

  29. SVを確保 47

  30. AVを確保 47  "7 

  31. HVを確保 47  "7 47  )7  B

  32. SVを確保してSVの場所を代入 47  "7 47  )7  47 B

    47   47  SFG YGEEC  0x7f99d080db78
  33. 中身を表示 47  "7 47  )7  47 B

    47   47  SFG YGEEC 
  34. 中身の指し示すやつを取ってきて表示 47  "7 47  )7  47 B

    47   47  SFG YGEEC  0x7f99d080db78
  35. ポイント • 値はメモリに確保されてる • リファレンスにはそのメモリの場所 を示すものが入っている • ねっ、CもPerlも変わらないでしょ

  36. さまざまな データ構造

  37. エントリーナンバー1

  38. 配列

  39. なにがおきてる?

  40. short5個分を「連続して」確保  10000番    

  41. 変数名でアクセスすると番地が取れる  10000番    

  42. 添え字付きアクセス      10000 + short(2byte) *

    2 番地を読みに行くよ  10000番    
  43. 添え字付きアクセス     

  44. 配列の要素を増やしたい     

  45. エントリーナンバー2

  46. 単方向連結リスト

  47. 単方向連結リストの要素 a next element

  48. 単方向連結リスト

  49. 要素一個つくる 要素一個つくる

  50. 要素一個つくる )7  @WBMVF @OFYU@SFGVOEFG 1

  51. 要素一個つくる )7  @WBMVF @OFYU@SFGVOEFG FM@ &MFNFOU SFG  1

  52. ふたつめの要素作る )7  @WBMVF @OFYU@SFGVOEFG FM@ &MFNFOU SFG  )7

     @WBMVF @OFYU@SFG&MFNFOU SFG   FM@ &MFNFOU SFG  1 2
  53. $el_ 1もう出てこないので無視 )7  @WBMVF @OFYU@SFGVOEFG )7  @WBMVF @OFYU@SFG&MFNFOU

    SFG   FM@ &MFNFOU SFG  1 2
  54. 同様にみっつめの要素 )7  @WBMVF @OFYU@SFGVOEFG )7  @WBMVF @OFYU@SFG&MFNFOU SFG

      FM@ &MFNFOU SFG  )7  @WBMVF @OFYU@SFG&MFNFOU SFG   1 2 3
  55. Listの実装 コンストラクタ リストの先頭に 値を追加するメソッド

  56. 空のリストを作って )7  @pSTU@FMFNFOU VOEFG MJTU -JTU SFG

  57. 要素をひとつ挿入 )7  @pSTU@FMFNFOU VOEFG MJTU -JTU SFG )7 

    @WBMVF @OFYU@SFGVOEFG
  58. 要素をひとつ挿入 )7  @pSTU@FMFNFOU &MFNFOUSFG  MJTU -JTU SFG )7

     @WBMVF @OFYU@SFGVOEFG
  59. 2を挿入 MJTU -JTU SFG )7  @WBMVF @OFYU@SFGVOEFG )7 

    @pSTU@FMFNFOU &MFNFOUSFG  )7  @WBMVF @OFYU@SFG &MFNFOUSFG 
  60. 3つめの値を取得したい MJTU -JTU SFG )7  @WBMVF @OFYU@SFG &MFNFOUSFG 

    )7  @pSTU@FMFNFOU &MFNFOUSFG  )7  @WBMVF @OFYU@SFG &MFNFOUSFG  )7  @WBMVF @OFYU@SFGVOEFG
  61. MJTU -JTU SFG )7  @WBMVF @OFYU@SFG &MFNFOUSFG  )7

     @pSTU@FMFNFOU &MFNFOUSFG  )7  @WBMVF @OFYU@SFG &MFNFOUSFG  )7  @WBMVF @OFYU@SFGVOEFG 3つめの値を取得したい
  62. MJTU -JTU SFG )7  @WBMVF @OFYU@SFG &MFNFOUSFG  )7

     @pSTU@FMFNFOU &MFNFOUSFG  )7  @WBMVF @OFYU@SFG &MFNFOUSFG  )7  @WBMVF @OFYU@SFGVOEFG 3つめの値を取得したい
  63. MJTU -JTU SFG )7  @WBMVF @OFYU@SFG &MFNFOUSFG  )7

     @pSTU@FMFNFOU &MFNFOUSFG  )7  @WBMVF @OFYU@SFG &MFNFOUSFG  )7  @WBMVF @OFYU@SFGVOEFG 3つめの値を取得したい
  64. ポイント • メモリアドレスが飛び飛び • 「空いてるところ」にメモリ確保で きる • 先頭からの順々に辿らないといけな いので一発でアクセスできない

  65. 一発とか順々とか ちょっと ふわっとしてる もうちょっと ちゃんと言いたい

  66. ここで ちょっと寄り道 計算量の話

  67. オーダー法 • データの数がn個のとき、n回計算を しないといけないとき、O(n)という • 2n回計算しないといけない、とか、 2n + a回計算しないといけないとき もO(n)という

    • 要するに定数倍とか定数項は考えない
  68. 連結リストの計算量 • n個めの要素にアクセスしたい • 最初の要素へのアクセス + n - 1回辿 る必要がある

    = O(n) • リストの最初に値を挿入したい • 後ろにいくつ要素があっても、最初の要 素へのアクセス + 新しい要素を作って つなぐだけ = O(1)
  69. 配列の計算量 • n個めの要素にアクセスしたい • 計算で一発でメモリ番地が出せて、そこ を読むだけでよい • O(1)

  70. いろんな計算量を グラフでみると 特徴がわかる

  71. O(n) ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ

  72. O(n) ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ

  73. O(n^2) ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ

  74. O(n^2) ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ

  75. O(1) ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ

  76. O(log n)

  77. O(log n) ԣ࣠ɿσʔλͷݸ਺ ॎ࣠ɿܭࢉͷྔ

  78. ポイント • オーダー法は「正確な計算量」を導 かない • データの量に応じて、「データが増 えたときにどれくらい処理量が増え るか」をざっと知るための指標です

  79. データ構造の話に 戻ります

  80. 連結リストの特徴 • 探索の計算量がO(n)だった • 悪くないけどO(log n)だと嬉しい ですよねー

  81. エントリーナンバー3

  82. 2分木

  83. 2分木のnode a x<a a<x

  84. )7  @SPPUVOEFG USFF 5SFFSFG tree 空の2分木

  85. )7  @SPPUVOEFG USFF 5SFFSFG tree 2分木に最初の値:4を追加 

  86. 2分木に最初の値:4を追加 )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG )7  @SPPU/PEF SFG

     USFF 5SFFSFG  tree
  87. 2分木に2を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFSVOEFG )7  @SPPU/PEF

    SFG  USFF 5SFFSFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG tree 
  88. 2分木に2を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFSVOEFG )7  @SPPU/PEF

    SFG  USFF 5SFFSFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG tree 
  89. 2分木に2を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFSVOEFG )7  @SPPU/PEF

    SFG  USFF 5SFFSFG  V  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG tree
  90. 2分木に6を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFSVOEFG )7  @SPPU/PEF

    SFG  USFF 5SFFSFG  V  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG tree 
  91. 2分木に6を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFSVOEFG )7  @SPPU/PEF

    SFG  USFF 5SFFSFG  V  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG tree 
  92. 2分木に6を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFS/PEFSFG  )7 

    @SPPU/PEF SFG  USFF 5SFFSFG  V V  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG tree
  93. 2分木に3を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFS/PEFSFG  )7 

    @SPPU/PEF SFG  USFF 5SFFSFG  V V  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG tree 
  94. 2分木に3を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFS/PEFSFG  )7 

    @SPPU/PEF SFG  USFF 5SFFSFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG  V V   tree 
  95. 2分木に3を追加 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFS/PEFSFG  )7 

    @SPPU/PEF SFG  USFF 5SFFSFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFS/PEFSFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG  V V   V  tree
  96. 2分木から1を探索 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFS/PEFSFG  )7 

    @SPPU/PEF SFG  USFF 5SFFSFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFS/PEFSFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG  V V   V  tree
  97. 2分木から1を探索 )7  @WBMVF @TNBMMFS/PEFSFG  @MBSHFS/PEFSFG  )7 

    @SPPU/PEF SFG  USFF 5SFFSFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFS/PEFSFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG  V V   V  tree
  98. 2分木の探索 • 4つ要素があるけど2回で済んだ • こういう風にちゃんと「ばらけた」 木になってるとO(log n)になる

  99. 2分木から5を探索 )7  @WBMVF @TNBMMFSVOEFG @MBSHFS/PEFSFG  )7  @SPPU/PEF

    SFG  USFF 5SFFSFG )7  @WBMVF @TNBMMFSVOEFG @MBSHFS/PEFSFG   )7  @WBMVF @TNBMMFSVOEFG @MBSHFS/PEFSFG  )7  @WBMVF @TNBMMFSVOEFG @MBSHFSVOEFG   
  100. 2分木の探索 • 実質連結リスト • O(n)じゃん

  101. エントリーナンバー4

  102. B木

  103. B木のnode b a x<a a<x<b b<x

  104. 空のB木に7を追加 

  105. B木に3を追加  

  106. B木に9を追加    満員じゃん

  107. B木に9を追加    全員並べて

  108. B木に9を追加    nodeふたつに分けて

  109. B木に9を追加    nodeふたつに分けて

  110. B木に9を追加    真ん中の値の行き場がない

  111. B木に9を追加    新しいnode作る

  112. B木に9を追加    枝つなぐ

  113. B木に9を追加    見やすいように整列!

  114. B木に5を追加    

  115. B木に6を追加     満員じゃん 

  116. B木に6を追加      全員並べて

  117. B木に6を追加      nodeふたつに分けて

  118. B木に6を追加      真ん中は上に空きがあるのでそこに入れる

  119. B木に6を追加     

  120. B木に6を追加      枝つなぎ直す

  121. B木に6を追加      見やすいように整列!

  122.       B木に10を追加

  123.       B木に16を追加  満員じゃん

  124.      B木に16を追加   真ん中は上に

  125.      B木に16を追加   満員じゃん

  126.    B木に16を追加    

  127.     B木に16を追加    node分割して 枝つなぎ直す

  128.     B木に16を追加    新しいnode作って 枝つなぐ

  129.     B木に16を追加   

  130.     B木に16を追加    O(log n)

    O(m)
  131. エントリーナンバー5

  132. B+木

  133. B+木 • DBのインデックスとかに使われて る • B木の改良版 • 末端のnodeに全部のデータが入っ てる •

    node同士がlinkされてることが多い
  134.         B+木 

       
  135.         B+木から5を探索 

      select * from table where id > 5  
  136. まとめ

  137. まとめ • データ構造と計算量について簡単に 見てみました • この程度の理解でも、ふだんの業務 に活かせることは増えます • 今後の学習や業務に活かしていただ ければ幸いです

  138. 最後に • 11/14 高円寺ペンギンハウス • よろしくおねがいします

  139. おしまい