hinekure.net が http://hspdev-wiki.net/ から自動クローリングした結果を表示しています。画像やリソースなどのリンクが切れています。予めご了承ください。
ラボ/双方向リンクリスト - HSP開発wiki
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS

ラボ

双方向リンクリスト

データ構造

リスト構造の一種で要素の並びをその要素の前の要素と次の要素それぞれを指すポインタ(pointer:指す)でリンク(link:連結) させたデータ構造。
片方向リンクリストが直前の要素へのポインタを持たないため、リスト先頭から検索するしかなかった点を改良し、要素に前のポインタを 持たせることで片方向リンクリストより容易に直前の要素を得ることが可能となる。

双方向リンクリストの内部状態
インデックス0123456789
_value--?23516351244?--
_next4851672391
_prev8367024518

head

new

tail

リンクリストに対する操作は主に3つある。

探索
指定した要素のリスト中の位置を求める?
挿入
指定した要素をリストに挿入する
削除
指定した要素をリストから削除する

実装例

fileDLinkedListAryNocmt[sp].hsp
Everything is expanded.Everything is shortened.
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
!
-
|
|
|
|
|
|
|
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
!
-
|
|
|
|
|
|
|
|
!
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
-
|
!
-
|
!
 
 
 
 
 
 
 
 
-
|
|
!
 
 
 
 
 
 
 
-
|
|
|
!
 
 
-
|
|
|
!
 
 
 
 
 
/*
################################################################################
#                                                                              #
#    データ構造:双方向リンクリスト(Double Linked List)                        #
#    リスト構造の一種で直前の要素と直後の要素へのポインタをもたせ、            #
#    リストの先頭、末尾どちらからでも要素を参照できるようにしたデータ構造。    #
#                                                                              #
################################################################################
*/
#module "DLinkedListAry"
    /*--------------------------------------------------------------------*
     *                     双方向リンクリストの初期化                     *
     *--------------------------------------------------------------------*/
    #deffunc DLink_init int i
        mref res,64
        if i < 1 : res = -1 : goto *@f
 
        n = i
 
        dim _value  , n+2
        dim _next   , n+2
        dim _prev   , n+2
 
        repeat n+1
            _next(cnt) = cnt+1
            _prev(cnt) = -1 + cnt
        loop
 
        head        = 0
        tail        = head
        new         = _next(head)
 
        _next(n+1)  = 1
        _prev(head) = n
        _prev(n+1)  = n
 
        res         = n
*@
        return
    /*--------------------------------------------------------------------*
     *リンクリストに要素を挿入*
     *--------------------------------------------------------------------*/
    #deffunc DLink_add int i
        if new = (n+1) : res = -1 : goto *@f
 
        p = _next(head)
        repeat
            if (p = new)|(i < _value(p)) : break
            p = _next(p)
        loop
 
        _value(new) = i
 
        if p = new{
            tail = p
        }
        else{
            _next(tail)         = _next(new)
            _prev(_next(tail))  = tail
 
            _next(_prev(p)) = new
            _next(new)      = p
            _prev(new)      = _prev(p)
            _prev(p)        = new
        }
 
        new = _next(tail)
 
        res = p
*@
        return
    /*--------------------------------------------------------------------*
     *リンクリストから要素を削除*
     *--------------------------------------------------------------------*/
    #deffunc DLink_del int i
        if tail = head : res = -1 : goto *@f
 
        p = _next(head)
        repeat
            if (p = new)|(i = _value(p)) : break
            p = _next(p)
        loop
 
        if p = new : res = -1 : goto *@f
 
        if p = tail{
            tail = _prev(p)
        }
        else{
            _next(_prev(p)) = _next(p)
            _prev(_next(p)) = _prev(p)
 
            _next(p)    = _next(tail)
            _next(tail) = p
 
            _prev(p)    = _prev(new)
            _prev(new)  = p
        }
 
        new = p
 
        res = p
*@
        return
    /*--------------------------------------------------------------------*
     *リンクリストの要素を表示
     *--------------------------------------------------------------------*/
    #deffunc DLink_disp str cmd
        if (cmd ! "+") & (cmd ! "-") : res = -1 : goto *@f
 
        if cmd = "+" : p = _next(head) : else : p = tail
 
        s = "[ "
        repeat
            if ((cmd = "+") & (p = new)) | (p = head) : res = cnt : break
            s += "" + _value(p) + " "
            if cmd = "+" : p = _next(p) : else : p = _prev(p)
        loop
        s += "]:" + res + "/" + n
        mes s
*@
        return
#global
 
/******************************************************************************
 *                           S A M P L E                           *
 ******************************************************************************/
#define LISTSIZE    5
    randomize
    font "MS ゴシック",12
    cmd = ""
    input cmd,,,3
    DLink_init LISTSIZE
    if stat = -1{
        dialog "リストの初期化に失敗しました.",1,"終了確認" : end
    }
    else{
        title "リストサイズ=" + stat
    }
 
    onkey gosub *enter
    stop
 
*enter
    if iparam ! 13 : goto *@f
 
    getstr num,cmd,1
    if num = ""{
        cmd = "" : objprm 0,cmd
        goto *@f
    }
 
    num = int(num)
 
    c = peek(cmd,0)
 
    switch c
        case '+' :  DLink_add num
                    if stat ! -1{
                        title " "+num+" を挿入しました."
                        DLink_disp "+"
                        DLink_disp "-"
                    }
                    swbreak
        case '-' :  DLink_del num
                    if stat ! -1{
                        title " "+num+" を削除しました."
                        DLink_disp "+"
                        DLink_disp "-"
                    }
                    swbreak
    swend
    cmd = "" : objprm 0,cmd
*@
    return

リスト内の探索アリゴリズムについて、片方向リンクリストでは要素へのポインタを1つしか持っていなかったので、 リスト先頭からリニアサーチを用いて末尾に向かって探索を進めていくのが一般的だと思います。
しかし双方向リンクリストになってからは逆順でたどることが可能になりました。
スクリプト中では片方向リンクリスト同様にリスト先頭からのリニアサーチですが、目的の要素がリスト末尾だった場合、 探索時間は最悪になります。
改良策としては要素の平均値を保持しておき、探索する要素が平均未満(以下)であれば先頭から、以上(より上)であれば末尾から探索を進めると探索時間の最良と最悪との差も小さくなります。
またシェーカーソートを応用して先頭からと末尾からを交互に進めるというのも1つの手だと思います。

コメント

  • 挿入は出来たんですが、削除が難しい・・・。 -- kz3 2005-09-01 12:23:06 (木)
  • 双方向できたぜ^^v -- kz3 2005-09-03 11:34:44 (土)
  • 出来たのは嬉しいがタブスペが・・・汗。 -- kz3 2005-09-03 11:35:04 (土)
  • サンプルスクリプトを作ってます -- kz3 2005-09-03 11:38:59 (土)
  • 片方向リンクリストとの実行結果の違いは、リストの内容を表示するときに昇順、降順両方を表示するようにしています。
    片方向リンクリストでも降順は出来ますが先頭から表示する要素を探索するのにいくつものリンクをたどらなければならないので、効率が悪いです。
    その点双方向リンクリストはリンク1つたどれば直前の要素へアクセスできるので効率がいいわけです。 -- kz3 2005-09-03 12:41:26 (土)
  • ばしばし感想書いてください;; -- kz3 2005-09-03 16:17:40 (土)
  • ファイルの参照カウンタが増えていないなぁ・・・反応がないと寂しいなぁ;; -- kz3 2005-09-04 08:47:28 (日)

添付ファイル:
fileDLinkedListAryNocmt[sp].hsp
466件 [詳細]
トップ    編集凍結 差分バックアップ添付複製名前変更リロード   新規一覧単語検索最終更新   最終更新のRSS
Last-modified: 2008-07-07 (月) 18:58:32 (1979d)