(57)【要約】【課題】カップルドノードツリーを退避／復元する。【解決手段】カップルドノードツリーはルートノードと、隣接した記憶領域に配置されるブランチノードとリーフノードまたはブランチノード同士またはリーフノード同士のノード対からなる。ブランチノードはビット列検索を行う検索キーの弁別ビット位置とリンク先のノード対の一方のノードである代表ノードの位置を示す位置情報を含む。リーフノードは検索対象のビット列からなるインデックスキーを含む。カップルドノードツリーのノードは深さ優先探索順に退避される。退避された順にノードを読み出し、ノードを復元すべき位置の位置情報をスタックに格納し、ブランチノードが続く間は子ノードを順次復元し、リーフノードが読み出されたらリーフノードを復元して、スタックを遡って次に復元すべきノードを決定する処理の繰り返しにより、カップルドノードツリーは復元される。【選択図】図１０Ａ
2008269197.tif 000002
【特許請求の範囲】
【請求項１】
ルートノードと、隣接した記憶領域に配置されるブランチノードとリーフノードまたはブランチノード同士またはリーフノード同士のノード対、からなるビット列検索に用いるツリーであって、
前記ルートノードは、ツリーの始点を表すノードであって、該ツリーのノードが１つのときは前記リーフノード、ツリーのノードが２つ以上のときは前記ブランチノードであり、
前記ブランチノードは、ビット列検索を行う検索キーの弁別ビット位置とリンク先のノード対の一方のノードである代表ノードの位置を示す位置情報を含み、前記リーフノードは検索対象のビット列からなるインデックスキーを含み、
前記ツリーの任意のノードを検索開始ノードとして、前記ブランチノードにおいて該ブランチノードに含まれる弁別ビット位置の検索キーのビット値に応じてリンク先のノード対の代表ノードかあるいは該代表ノードと対になる非代表ノードにリンクすることを順次前記リーフノードに至るまで繰り返すことにより、前記リーフノードに格納されたインデックスキーを、前記検索開始ノードをルートノードとする前記ツリーの任意の部分木の前記検索キーによる検索の結果である検索結果キーとするように構成されたカップルドノードツリーの任意の部分木を、該カップルドノードツリーが配置されているのとは別の記憶領域に退避するカップルドノードツリーの退避方法であって、
退避しようとする前記部分木のルートノードを、ノードを退避する順序に対応する経路の開始点である巡回開始ノードとして指定し、
前記巡回開始ノードから、前記ノード対のうち代表ノードのみあるいは非代表ノードのみをリンクしてリーフノードに至るまで巡回しながら、前記巡回開始ノードから前記リーフノードに至る前記経路上の各ノードについて、当該ノードの位置を示す前記位置情報を順次スタックに格納するとともに当該ノードの内容を順次前記別の記憶領域に退避し、
代表ノードあるいは非代表ノードの位置情報が得られるまで前記スタックのポップ動作を繰り返し行って該スタックから該位置情報を読み出し、該位置情報が読み出された前記代表ノードあるいは前記非代表ノードとノード対をなす非代表ノードあるいは代表ノードを、新たな前記巡回開始ノードとして指定して前記ノードの巡回と退避を繰り返す、
ことを特徴とするカップルドノードツリーの退避方法。
【請求項２】
前記カップルドノードツリーは配列に記憶され、前記位置情報は、該位置情報に対応する前記ノードが格納された前記配列の配列要素の配列番号である、ことを特徴とする請求項１記載のカップルドノードツリーの退避方法。
【請求項３】
前記別の記憶領域に退避される前記内容には、前記ブランチノードを退避する場合は前記弁別ビット位置が含まれ、前記リーフノードを退避する場合は前記インデックスキーが含まれる、ことを特徴とする請求項１記載のカップルドノードツリーの退避方法。
【請求項４】
前記ブランチノードと前記リーフノードを区別する種別情報が前記ブランチノードと前記リーフノードの双方に含まれ、前記種別情報も退避されることを特徴とする請求項３記載のカップルドノードツリーの退避方法。
【請求項５】
前記ブランチノードに含まれる前記位置情報は退避されないことを特徴とする請求項３記載のカップルドノードツリーの退避方法。
【請求項６】
前記別の記憶領域は配列であることを特徴とする請求項１記載のカップルドノードツリーの退避方法。
【請求項７】
ルートノードと、隣接した記憶領域に配置されるブランチノードとリーフノードまたは
ブランチノード同士またはリーフノード同士のノード対、からなるビット列検索に用いるツリーであって、
前記ルートノードは、ツリーの始点を表すノードであって、該ツリーのノードが１つのときは前記リーフノード、ツリーのノードが２つ以上のときは前記ブランチノードであり、
前記ブランチノードは、ビット列検索を行う検索キーの弁別ビット位置とリンク先のノード対の一方のノードである代表ノードの位置を示す位置情報を含み、前記リーフノードは検索対象のビット列からなるインデックスキーを含み、
前記ツリーの任意のノードを検索開始ノードとして、前記ブランチノードにおいて該ブランチノードに含まれる弁別ビット位置の検索キーのビット値に応じてリンク先のノード対の代表ノードかあるいは該代表ノードと対になる非代表ノードにリンクすることを順次前記リーフノードに至るまで繰り返すことにより、前記リーフノードに格納されたインデックスキーを、前記検索開始ノードをルートノードとする前記ツリーの任意の部分木の前記検索キーによる検索の結果である検索結果キーとするように構成されたカップルドノードツリーの任意の部分木を、伝送媒体を介して外部装置に送信することによって該外部装置に退避するカップルドノードツリーの退避方法であって、
退避しようとする前記部分木のルートノードを、ノードを退避する順序に対応する経路の開始点である巡回開始ノードとして指定し、
前記巡回開始ノードから、前記ノード対のうち代表ノードのみあるいは非代表ノードのみをリンクしてリーフノードに至るまで巡回しながら、前記巡回開始ノードから前記リーフノードに至る前記経路上の各ノードについて、当該ノードの位置を示す前記位置情報を順次スタックに格納するとともに当該ノードの内容を順次前記伝送媒体を介して前記外部装置に送信し、
代表ノードあるいは非代表ノードの位置情報が得られるまで前記スタックのポップ動作を繰り返し行って該スタックから該位置情報を読み出し、該位置情報が読み出された前記代表ノードあるいは前記非代表ノードとノード対をなす非代表ノードあるいは代表ノードを、新たな前記巡回開始ノードとして指定して前記ノードの巡回と送信を繰り返す、
ことを特徴とするカップルドノードツリーの退避方法。
【請求項８】
請求項１記載のカップルドノードツリーの退避方法により前記別の記憶領域に退避された退避情報から、退避された順番で順次ノードを復元することによって前記カップルドノードツリーを復元するカップルドノードツリーの復元方法であって、
前記退避情報から順次ノードを読み出し、
復元しようとするカップルドノードツリーのルートノードが、復元される順番にあるときは、該ルートノード用の記憶領域を取得し、読み出したノードの内容を該記憶領域に格納することにより、該ルートノードを復元し、
読み出されたノードがブランチノードである間は順次、前記退避情報において該ブランチノードの次の順番にある子ノードを、該子ノードと対になるノード用の記憶領域も取得しながら、該子ノード用の記憶領域を取得して読み出した該子ノードの内容を前記記憶領域に格納することによって復元するとともに、該子ノードを含むノード対の代表ノードの前記記憶領域の位置情報を前記ブランチノードに書き込み、リーフノードが読み出されたら、復元中の前記カップルドノードツリーのツリー構造をルートノードに向かって遡って、取得済みだがノードの内容が格納されていない記憶領域を探索し、該探索により見つかった該記憶領域を、次に復元すべきノードの内容を格納すべき記憶領域として決定することを繰り返す、
ことを特徴とするカップルドノードツリーの復元方法。
【請求項９】
前記カップルドノードツリーは配列に復元され、復元された前記ブランチノードに書き込まれる前記位置情報は、該位置情報に対応する前記代表ノードを格納する配列要素の配列番号である、ことを特徴とする請求項８記載のカップルドノードツリーの復元方法。
【請求項１０】
前記退避情報において、前記ブランチノードを退避した前記内容には、前記弁別ビット位置が含まれるが前記位置情報が含まれず、前記リーフノードを退避した前記内容には前記インデックスキーが含まれることを特徴とする請求項８記載のカップルドノードツリーの復元方法。
【請求項１１】
復元しようとする前記カップルドノードツリーは、前記退避情報に退避された元の前記カップルドノードツリーの部分木に相当し、
該部分木の前記ルートノードよりも前の順番で前記退避情報に退避されたノードの内容をスキップし、該部分木の該ルートノードの前記内容から順次、前記退避情報を読み出し、
前記リーフノードが読み出されたときの前記探索の過程で、復元中の前記カップルドノードツリーのルートノードまで遡ったら、復元を終了する、
ことを特徴とする請求項８記載のカップルドノードツリーの復元方法。
【請求項１２】
前記退避情報は配列に格納されていることを特徴とする請求項８記載のカップルドノードツリーの復元方法。
【請求項１３】
請求項７記載のカップルドノードツリーの退避方法により前記外部装置に送信された退避情報を受信し、送信された順番で順次ノードを前記外部装置の記憶領域に復元することによって前記カップルドノードツリーを復元するカップルドノードツリーの復元方法であって、
前記退避情報から順次ノードを受信して読み取り、
復元しようとするカップルドノードツリーのルートノードが、復元される順番にあるときは、該ルートノード用の記憶領域を取得し、読み取ったノードの内容を該記憶領域に格納することにより、該ルートノードを復元し、
読み取られたノードがブランチノードである間は順次、前記退避情報において該ブランチノードの次の順番にある子ノードを、該子ノードと対になるノード用の記憶領域も取得しながら、該子ノード用の記憶領域を取得して読み取った該子ノードの内容を前記記憶領域に格納することによって復元するとともに、該子ノードを含むノード対の代表ノードの前記記憶領域の位置情報を前記ブランチノードに書き込み、リーフノードが読み取られたら、復元中の前記カップルドノードツリーのツリー構造をルートノードに向かって遡って、取得済みだがノードの内容が格納されていない記憶領域を探索し、該探索により見つかった該記憶領域を、次に復元すべきノードの内容を格納すべき記憶領域として決定することを繰り返す、
ことを特徴とするカップルドノードツリーの復元方法。
【請求項１４】
請求項１〜７のいずれか１項に記載のカップルドノードツリーの退避方法または請求項８〜１３のいずれか１項に記載のカップルドノードツリーの復元方法をコンピュータに実行させるためのプログラム。
【請求項１５】
請求項１記載のカップルドノードツリーの退避方法により前記別の記憶領域に退避されたカップルドノードツリーのノード列のデータ構造。
【請求項１６】
請求項８または１３記載のカップルドノードツリーの復元方法により前記カップルドノードツリーを復元可能なように構成されたデータ構造。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、ビット列を記憶するツリー状のデータ構造を用いてビット列の集合から所望のビット列を検索する技術に関するものであり、特に本出願人が特願２００６−１８７８２７において提案したカップルドノードツリーの退避／復元方法及びそのプログラムに関するものである。
【背景技術】
【０００２】
近年、社会の情報化が進展し、大規模なデータベースが各所で利用されるようになってきている。このような大規模なデータベースからレコードを検索するには、各レコードの記憶されたアドレスと対応づけられたレコード内の項目をインデックスキーとして検索をし、所望のレコードを探し出すことが通例である。また、全文検索における文字列も、文書のインデックスキーと見なすことができる。
【０００３】
そして、それらのインデックスキーはビット列で表現されることから、データベースの検索はビット列の検索に帰着されるということができる。
上記ビット列の検索を高速に行うために、ビット列を記憶するデータ構造を種々に工夫することが従来から行われている。このようなものの一つとして、パトリシアツリーという木構造が知られている。
【０００４】
図１６は、上述の従来の検索処理に用いられているパトリシアツリーの一例を示すものである。パトリシアツリーのノードは、インデックスキー、検索キーの検査ビット位置、左右のリンクポインタを含んで構成される。明示はされていないが、ノードにはインデックスキーに対応するレコードにアクセスするための情報が含まれていることは勿論である。
【０００５】
図１６の例では、インデックスキー“１０００１０”を保持するノード１７５０ａがルートノードとなっており、その検査ビット位置１７３０ａは０である。ノード１７５０ａの左リンク１７４０ａにはノード１７５０ｂが接続され、右リンク１７４１ａにはノード１７５０ｆが接続されている。
【０００６】
ノード１７５０ｂの保持するインデックスキーは“０１００１１”であり、検査ビット位置１７３０ｂは１である。ノード１７５０ｂの左リンク１７４０ｂにはノード１７５０ｃが、右リンク１７４１ｂにはノード１７５０ｄが接続されている。ノード１７５０ｃが保持するインデックスキーは“０００１１１”、検査ビット位置１７３０ｃは３である。ノード１７５０ｄが保持するインデックスキーは“０１１０１０”、検査ビット位置１７３０ｄは２である。
【０００７】
ノード１７５０ｃから実線で接続された部分はノード１７５０ｃの左右のリンクポインタを示すものであり、点線の接続されていない左ポインタ１７４０ｃは、その欄が空欄であることを示している。点線の接続された右ポインタ１７４１ｃの点線の接続先は、ポインタの示すアドレスを表しており、今の場合ノード１７５０ｃを右ポインタ１７４１ｃが指定していることを表している。
【０００８】
ノード１７５０ｄの右ポインタ１７４１ｄはノード１７５０ｄ自身を指しており、左リンク１７４０ｄにはノード１７５０ｅが接続されている。ノード１７５０ｅの保持するインデックスキーは“０１００１０”、検査ビット位置１７３０ｅは５である。ノード１７５０ｅの左ポインタ１７４０ｅはノード１７５０ｂを、右ポインタ１７４１ｅはノード１
７５０ｅを指している。
【０００９】
また、ノード１７５０ｆの保持するインデックスキーは“１０１０１１”であり、検査ビット位置１７３０ｆは２である。ノード１７５０ｆの左リンク１７４０ｆにはノード１７５０ｇが、右リンク１７４１ｆにはノード１７５０ｈが接続されている。
【００１０】
ノード１７５０ｇの保持するインデックスキーは“１０００１１”であり、検査ビット位置１７３０ｇは５である。ノード１７５０ｇの左ポインタ１７４０ｇはノード１７５０ａを、右ポインタ１７４１ｇはノード１７５０ｇを指している。
【００１１】
ノード１７５０ｈの保持するインデックスキーは“１０１１００”であり、検査ビット位置１７３０ｈは３である。ノード１７５０ｈの左ポインタ１７４０ｈはノード１７５０ｆを、右ポインタ１７４１ｈはノード１７５０ｈを指している。
【００１２】
図１６の例では、ルートノード１７５０ａからツリーを降りるにしたがって、各ノードの検査ビット位置が大きくなるように構成されている。
ある検索キーで検索を行うとき、ルートノードから順次各ノードに保持される検索キーの検査ビット位置を検査していき、検査ビット位置のビット値が１であるか０であるか判定を行い、１であれば右リンクをたどり、０であれば左リンクをたどる。そして、リンク先のノードの検査ビット位置がリンク元のノードの検査ビット位置より大きくなければ、すなわち、リンク先が下方でなく上方に戻れば（図１６において点線で示されたこの逆戻りのリンクをバックリンクという）、リンク先のノードのインデックスキーと検索キーの比較を行う。比較の結果、等しければ検索成功であり、等しくなければ検索失敗であることが保証されている。
【００１３】
上記のように、パトリシアツリーを用いた検索処理では、必要なビットの検査だけで検索できること、キー全体の比較は１回ですむことなどのメリットがあるが、各ノードからの２つのリンクが必ずあることにより記憶容量が増大することや、バックリンクの存在による判定処理の複雑化、バックリンクにより戻ることで初めてインデックスキーと比較することによる検索処理の遅延及び追加削除等データメンテナンスの困難性などの欠点がある。
【００１４】
これらのパトリシアツリーの欠点を解消しようとするものとして、例えば下記特許文献１に開示された技術がある。下記特許文献１に記載されたパトリシアツリーにおいては、下位の左右のノードは連続した領域に記憶することによりポインタの記憶容量を削減するとともに、次のリンクがバックリンクであるか否かを示すビットを各ノードに設けることにより、バックリンクの判定処理を軽減している。
【００１５】
しかしながら、下記特許文献１に開示されたものにおいても、１つのノードは必ずインデックスキーの領域とポインタの領域を占めること、下位の左右のノードを連続した領域に記憶するようにしてポインタを１つとしたため、例えば図１６に示したパトリシアツリーの最下段の部分である左ポインタ１７４０ｃ、右ポインタ１７４１ｈ等の部分にもノードと同じ容量の記憶領域を割り当てる必要があるなど、記憶容量の削減効果はあまり大きいものではない。また、バックリンクによる検索処理の遅延の問題や追加削除等の処理が困難であることも改善されていない。
【００１６】
上述の従来の検索手法における問題点を解決するものとして、本出願人は、特願２００６−１８７８２７において、ルートノードと、隣接した記憶領域に配置されるブランチノードとリーフノードまたはブランチノード同士またはリーフノード同士のノード対からなるビット列検索に用いるツリーであって、ルートノードはツリーの始点を表すノードであ
って、該ツリーのノードが１つのときはリーフノード、ツリーのノードが２つ以上のときは前記ブランチノードであり、前記ブランチノードは、ビット列検索を行う検索キーの弁別ビット位置とリンク先のノード対の一方のノードである代表ノードの位置を示す位置情報を含み、前記リーフノードは検索対象のビット列からなるインデックスキーを含むカップルドノードツリーを用いたビット列検索を提案した。
【００１７】
上記出願においては、与えられたインデックスキーの集合からカップルドノードツリーを生成する方法と、カップルドノードツリーから単一のインデックスキーを検索する手法等の、カップルドノードツリーを用いた基本的な検索手法が示されている。また、カップルドノードツリーの構成が、インデックスキーの集合により一意に規定されることも説明されている。
【００１８】
また、ビット列の検索には、最小値、最大値を求める、ある範囲の値のものを求める等の各種の検索要求が存在する。そこで、本出願人は、特願２００６−２９３６１９において、カップルドノードツリーの任意の部分木に含まれるインデックスキーの最大値／最小値を求める手法及びカップルドノードツリーに格納されたインデックスキーを昇順または降順に取り出す手法等を提案した。
【００１９】
インデックスキーの最大値／最小値を求める手法は、代表ノードあるいは代表ノードと対を成すノード（以下、非代表ノードということがある。）のみをリーフノードに至るまでリンクするものであり、カップルドノードツリーに格納されたインデックスキーを昇順または降順に取り出す手法は、後に説明するように、インデックスキーはカップルドノードツリーにおいて、順序性をもって配置されていることを利用したものであり、検索開始ノードを前記順序性に基づいて変更しながら最小値検索または最大値検索を繰り返すものである。
【００２０】
また、上記各出願において、カップルドノードツリーを配列に配置すること、上記提案した各検索処理における検索開始ノードからのツリー上の探索経路のノードの配列番号を探索経路スタックに順次スタックし、探索経路スタックにスタックされた配列番号を用いた処理も開示した。
【特許文献１】特開２００１−３５７０７０号公報
【発明の開示】
【発明が解決しようとする課題】
【００２１】
上記各出願で提案されたカップルドノードツリーの記憶領域上の配置については、先に述べたように、対をなすノード同士は隣接した記憶領域に配置されることが規定されているが、ノード対間についてはどのように配置されるかについては、特に制限はなく、アプリケーションあるいは記憶領域を管理する記憶管理システムに任されるものである。
【００２２】
また、そもそも、ブランチノードの有するリンク先のノード対の一方のノードである代表ノードの位置を示す位置情報は、そのカップルドノードツリーが格納されている記憶領域により規定されるものである。
【００２３】
したがって、カップルドノードツリーを他の記憶領域にコピーして利用しようとすると、仮にノード対間の配置の記憶領域上での相対的関係を保存したままコピーしたとしても、ブランチノードに含まれる上記リンク先に関する位置情報の値は変更する必要がある。
【００２４】
また、コピー先の事情で、ノード対間の配置の記憶領域上での相対的関係を保存したままコピーできない場合もあり得るし、相対的関係を保存したままコピーすることが適切とは限らず、その必要性も一般的には認められない。
【００２５】
以上述べたとおりであるので、カップルドノードツリーを例えば主記憶上から外部記憶装置に格納したり、通信回線を経由して別のコンピュータの記憶装置に転送したりするようなコピー処理を行う場合、何らかの変換処理が必要になる。
【００２６】
そこで、その変換処理を容易にするため、カップルドノードツリーの記憶領域上の配置によらない、カップルドノードツリーのノード情報の交換形式を定義し、その交換形式を利用してコピー処理を行うことが考えられる。
【００２７】
例えばカップルドノードツリーに格納されたインデックスキー自体を転送して転送されたインデックスキーに基づいて受信側でカップルドノードツリーの生成処理を行えばコピー処理が完成することは明らかである。しかし、それではカップルドノードツリーの転送というよりはインデックスキーの転送であり、転送先では再度、インデックスキー同士の比較に基づいてブランチノードに含めるべき弁別ビット位置を決定する処理や、新たなノードを挿入すべき場所を決定する処理を含むカップルドノードツリーの生成処理を行う必要がある。したがって、弁別ビット位置やノードの挿入場所の決定などの処理が不要で、より効率的な変換処理を可能とする手法を創案することが望ましい。
【００２８】
そこで本発明の目的は、カップルドノードツリーの記憶領域上の具体的な配置によらない、カップルドノードツリーのノード情報の交換形式にカップルドノードツリーを変換してある記憶領域に保存する退避方法及び該退避方法に対応する上記交換形式からカップルドノードツリーへの逆変換である復元方法であって、効率的な退避方法及び復元方法を提供することである。
【課題を解決するための手段】
【００２９】
本発明の一つの態様によれば、カップルドノードツリーのツリー構造を、ノード情報の列に変換して退避する。つまり、カップルドノードツリーのノードの内容を退避用の記憶領域に順次書き出す。この記憶領域は配列とすることができる。
【００３０】
その際、先に提案したカップルドノードツリーに格納されたインデックスキーを昇順または降順に取り出す手法を応用し、最小値検索または最大値検索を繰り返すときにたどるノード、すなわち検索開始ノードから最小値または最大値に至るリンク経路のノードと次の最小値検索または最大値検索を開始する検索開始ノード、の内容をそのノードをたどる順序で退避用の記憶領域に書き出す。
【００３１】
上述の本発明によるカップルドノードツリーのノードを順次たどることを、ノードを巡回するあるいは経路を巡回すると表記することとし、検索開始ノードを巡回開始ノードと表記することとすると、本発明の退避方法の具体的アルゴリズムは次のとおりである。
【００３２】
インデックスキーを昇順または降順に取り出す手法が、カップルドノードツリーの任意の部分木に対して適用可能であるのと同様に、退避においても、任意の部分木に対して適用可能であることから、まず、退避しようとする部分木のルートノードを、巡回開始ノードとして指定する。
【００３３】
次に、巡回開始ノードから、ノード対のうち代表ノードのみあるいは非代表ノードのみをリンクしてリーフノードに至るまで巡回しながら、巡回開始ノードからリーフノードに至る前記経路上の各ノードについて、当該ノードの位置を示す位置情報を順次スタックに格納するとともに当該ノードの内容を順次別の記憶領域に退避する。
【００３４】
次に、代表ノードあるいは非代表ノードの位置情報が得られるまで前記スタックのポッ
プ動作を繰り返し行って該スタックから該位置情報を読み出し、該位置情報が読み出された前記代表ノードあるいは前記非代表ノードとノード対をなす非代表ノードあるいは代表ノードを、新たな前記巡回開始ノードとして指定して前記ノードの巡回と退避を繰り返す。
【００３５】
以上の処理により、カップルドノードツリーの各ノードは、ノードの巡回順により退避用記憶領域に格納される。その際、ブランチノードにおける代表ノードの位置情報は、カップルドノードツリーを復元する場合には一般的に退避前の記憶領域とは別の領域に復元されることから復元時には意味を持たなくなるので、ブランチノードについてはノード種別と弁別ビット位置だけを退避するようにしてもよい。
【００３６】
本発明の別の態様によれば、退避用の記憶領域に格納されたノード情報（退避情報）からカップルドノードツリーを復元する復元方法が提供される。
この復元は、カップルドノードツリーの記憶領域上の配置によらない、カップルドノードツリーのノード情報の交換形式に変換されたノード情報の列であるデータ構造を、カップルドノードツリーのデータ構造に逆変換するものである。各ノードは退避された順番で復元される。
【００３７】
この復元方法では、前記退避情報から順次ノードを読み出し、読み出した順番でノードを復元する。
復元しようとするカップルドノードツリーのルートノードが、復元される順番にあるときは、該ルートノード用の記憶領域を取得し、読み出したノードの内容を該記憶領域に格納することにより、該ルートノードを復元する。
【００３８】
また、読み出されたノードがブランチノードである間は順次、前記退避情報において該ブランチノードの次の順番にある子ノードを、該子ノードと対になるノード用の記憶領域も取得しながら、該子ノード用の記憶領域を取得して読み出した該子ノードの内容を前記記憶領域に格納することによって復元し、リーフノードが読み出されたら、復元中の前記カップルドノードツリーのツリー構造をルートノードに向かって遡って、取得済みだがノードの内容が格納されていない記憶領域を探索し、該探索により見つかった該記憶領域を、次に復元すべきノードの内容を格納すべき記憶領域として決定することを、この復元方法では繰り返す。
【００３９】
また、本発明の別の態様によれば、上記退避用記憶領域を構成する記憶媒体に替えて伝送媒体を用い、送信側ではカップルドノードツリーを巡回して順番にノードを取り出し、取り出したノードを、伝送媒体を経由して送信し、受信側では受信したノードを復元ノードとしてカップルドノードツリーを受信側の記憶領域に復元する。
【００４０】
さらに本発明の別の態様によれば、上記カップルドノードツリーの退避方法あるいはカップルドノードツリーの復元方法をコンピュータに実行させるプログラムが提供される。
【発明の効果】
【００４１】
本発明によるカップルドノードツリーの退避方法は、退避の対象であるカップルドノードツリーの部分木を構成するノードを、深さ優先探索順に退避する方法である。そのため、元のカップルドノードツリーが記憶領域上に具体的にどのように配置されているかということに依存しない順序（深さ優先探索順）でノードが退避される。このような退避／復元処理を介すことにより、カップルドノードツリーが再利用しやすくなる。
【００４２】
また、上記の退避方法及び復元方法は、ノードに含まれる弁別ビット位置やインデックスキーの値に基づく判断等の複雑な処理を含まない、簡潔な方法である。すなわち、本発
明によれば、カップルドノードツリーの構造の特徴を利用することにより、簡単な処理で、効率よくカップルドノードツリーの退避／復元処理を実施することができる。
【発明を実施するための最良の形態】
【００４３】
最初に、本出願人により先の上記出願において提案された、本発明の前提となるカップルドノードツリーについて、カップルドノードツリーを配列に格納する例を説明する。ブランチノードが保持するリンク先の位置を示すデータとして、記憶装置のアドレス情報とすることもできるが、ブランチノードあるいはリーフノードのうち占有する領域の記憶容量の大きい方を格納可能な配列要素からなる配列を用いることにより、ノードの位置を配列番号で表すことができ、位置情報の情報量を削減することができる。
【００４４】
図１は、配列に格納されたカップルドノードツリーの構成例を説明する図である。
図１を参照すると、ノード１０１が配列１００の配列番号１０の配列要素に配置されている。ノード１０１はノード種別１０２、弁別ビット位置１０３及び代表ノード番号１０４で構成されている。ノード種別１０２は０であり、ノード１０１がブランチノードであることを示している。弁別ビット位置１０３には１が格納されている。代表ノード番号１０４にはリンク先のノード対の代表ノードの配列番号２０が格納されている。なお、以下では表記の簡略化のため、代表ノード番号に格納された配列番号を代表ノード番号ということもある。また、代表ノード番号に格納された配列番号をそのノードに付した符号あるいはノード対に付した符号で表すこともある。
【００４５】
配列番号２０の配列要素には、ノード対１１１の代表ノードであるノード［０］１１２が格納されている。そして隣接する次の配列要素（配列番号２０＋１）に代表ノードと対になるノード［１］１１３が格納されている。ノード［０］１１２のノード種別１１４には０が、弁別ビット位置１１５には３が、代表ノード番号１１６には３０が格納されている。またノード［１］１１３のノード種別１１７には１が格納されており、ノード［１］１１３がリーフノードであることを示している。インデックスキー１１８には、“０００１”が格納されている。パトリシアツリーについて先に述べたと同様に、リーフノードにインデックスキーと対応するレコードにアクセスする情報が含まれることは当然であるが、表記は省略している。
【００４６】
なお、代表ノードをノード［０］で表し、それと対になるノードをノード［１］で表すことがある。また、ある配列番号の配列要素に格納されたノードを、その配列番号のノードということがあり、ノードの格納された配列要素の配列番号を、ノードの配列番号ということもある。
【００４７】
配列番号３０及び３１の配列要素に格納されたノード１２２とノード１２３からなるノード対１２１の内容は省略されている。
ノード［０］１１２、ノード［１］１１３、ノード１２２、及びノード１２３の格納された配列要素にそれぞれ付された０あるいは１は、検索キーで検索を行う場合にノード対のどちらのノードにリンクするかを示すものである。前段のブランチノードの弁別ビット位置にある検索キーのビット値である０か１を代表ノード番号に加えた配列番号のノードにリンクする。
【００４８】
したがって、前段のブランチノードの代表ノード番号に、検索キーの弁別ビット位置のビット値を加えることにより、リンク先のノードが格納された配列要素の配列番号を求めることができる。
【００４９】
なお、上記の例では代表ノード番号をノード対の配置された配列番号のうち小さい方を採用しているが、大きいほうを採用することも可能であることは明らかである。
図２は、カップルドノードツリーのツリー構造を概念的に示す図である。図示の６ビットのインデックスキーは、図１６に例示されたパトリシアツリーのものと同じである。
【００５０】
符号２１０ａで示すのがルートノードである。図示の例では、ルートノード２１０ａは配列番号２２０に配置されたノード対２０１ａの代表ノードとしている。
ツリー構造としては、ルートノード２１０ａの下にノート対２０１ｂが、その下層にノード対２０１ｃとノード対２０１ｆが配置され、ノード対２０１ｆの下層にはノード対２０１ｈとノード対２０１ｇが配置されている。ノード対２０１ｃの下にはノード対２０１ｄが、さらにその下にはノード対２０１ｅが配置されている。
【００５１】
各ノードの前に付された０あるいは１の符号は、図１において説明した配列要素の前に付された符号と同じである。検索キーの弁別ビット位置のビット値に応じてツリーをたどり、検索対象のリーフノードを見つけることになる。
【００５２】
図示された例では、ルートノード２１０ａのノード種別２６０ａは０でブランチノードであることを示し、弁別ビット位置２３０ａは０を示している。代表ノード番号は２２０ａであり、それはノード対２０１ｂの代表ノード２１０ｂの格納された配列要素の配列番号である。
【００５３】
ノード対２０１ｂはノード２１０ｂと２１１ｂで構成され、それらのノード種別２６０ｂ、２６１ｂはともに０であり、ブランチノードであることを示している。ノード２１０ｂの弁別ビット位置２３０ｂには１が格納され、リンク先の代表ノード番号にはノード対２０１ｃの代表ノード２１０ｃの格納された配列要素の配列番号２２０ｂが格納されている。
【００５４】
ノード２１０ｃのノード種別２６０ｃには１が格納されているので、このノードはリーフノードであり、したがって、インデックスキー２５０ｃを含んでいる。インデックスキー２５０ｃには“０００１１１”が格納されている。一方ノード２１１ｃのノード種別２６１ｃは０、弁別ビット位置２３１ｃは２であり、代表ノード番号にはノード対２０１ｄの代表ノード２１０ｄの格納された配列要素の配列番号２２１ｃが格納されている。
【００５５】
ノード２１０ｄのノード種別２６０ｄは０、弁別ビット位置２３０ｄは５であり、代表ノード番号にはノード対２０１ｅの代表ノード２１０ｅの格納された配列要素の配列番号２２０ｄが格納されている。ノード２１０ｄと対になるノード２１１ｄのノード種別２６１ｄは１であり、インデックスキー２５１ｄには“０１１０１０”が格納されている。
【００５６】
ノード対２０１ｅのノード２１０ｅ、２１１ｅのノード種別２６０ｅ、２６１ｅはともに１であり双方ともリーフノードであることを示し、それぞれのインデックスキー２５０ｅ、２５１ｅにはインデックスキーとして“０１００１０”と“０１００１１”が格納されている。
【００５７】
ノード対２０１ｂのもう一方のノードであるノード２１１ｂの弁別ビット位置２３１ｂには２が格納され、リンク先の代表ノード番号にはノード対２０１ｆの代表ノード２１０ｆの格納された配列要素の配列番号２２１ｂが格納されている。
【００５８】
ノード対２０１ｆのノード２１０ｆ、２１１ｆのノード種別２６０ｆ、２６１ｆはともに０であり双方ともブランチノードである。それぞれの弁別ビット位置２３０ｆ、２３１ｆには５、３が格納されている。ノード２１０ｆの代表ノード番号にはノード対２０１ｇの代表ノード２１０ｇの格納された配列要素の配列番号２２０ｆが格納され、ノード２１１ｆの代表ノード番号にはノード対２０１ｈの代表ノードであるノード［０］２１０ｈの
格納された配列要素の配列番号２２１ｆが格納されている。
【００５９】
ノード対２０１ｇのノード２１０ｇ、２１１ｇのノード種別２６０ｇ、２６１ｇはともに１であり双方ともリーフノードであることを示し、それぞれのインデックスキー２５０ｇ、２５１ｇには“１０００１０”と“１０００１１”が格納されている。
【００６０】
また同じくノード対２０１ｈの代表ノードであるノード［０］２１０ｈとそれと対をなすノード［１］２１１ｈのノード種別２６０ｈ、２６１ｈはともに１であり双方ともリーフノードであることを示し、それぞれのインデックスキー２５０ｈ、２５１ｈには“１０１０１１”と“１０１１００”が格納されている。
【００６１】
以下、上述のツリーからインデックスキー“１０００１０”を検索する処理の流れを簡単に説明する。弁別ビット位置は、左から０、１、２、・・・とする。
まず、ビット列“１０００１０”を検索キーとしてルートノード２１０ａから処理をスタートする。ルートノード２１０ａの弁別ビット位置２３０ａは０であるので、検索キー“１０００１０”の弁別ビット位置が０のビット値をみると１である。そこで代表ノード番号の格納された配列番号２２０ａに１を加えた配列番号の配列要素に格納されたノード２１１ｂにリンクする。ノード２１１ｂの弁別ビット位置２３１ｂには２が格納されているので、検索キー“１０００１０”の弁別ビット位置が２のビット値をみると０であるから、代表ノード番号の格納された配列番号２２１ｂの配列要素に格納されたノード２１０ｆにリンクする。
【００６２】
ノード２１０ｆの弁別ビット位置２３０ｆには５が格納されているので、検索キー“１０００１０”の弁別ビット位置が５のビット値をみると０であるから、代表ノード番号の格納された配列番号２２０ｆの配列要素に格納されたノード２１０ｇにリンクする。
【００６３】
ノード２１０ｇのノード種別２６０ｇは１でありリーフノードであることを示しているので、インデックスキー２５０ｇを読み出して検索キーと比較すると両方とも“１０００１０”であって一致している。このようにしてカップルドノードツリーを用いた検索が行われる。
【００６４】
次に、図２を参照してカップルドノードツリーの構成の意味について説明する。
カップルドノードツリーの構成はインデックスキーの集合により規定される。図２の例で、ルートノード２１０ａの弁別ビット位置が０であるのは、図２に例示されたインデックスキーに０ビット目が０のものと１のものがあるからである。０ビット目が０のインデックスキーのグループはノード２１０ｂの下に分類され、０ビット目が１のインデックスキーのグループはノード２１１ｂの下に分類されている。
【００６５】
ノード２１１ｂの弁別ビット位置が２であるのは、ノード２１１ｈ、２１０ｈ、２１１ｇ、２１０ｇに格納された０ビット目が１のインデックスキーの１ビット目がすべて０で等しく、２ビット目で初めて異なるものがあるという、インデックスキーの集合の性質を反映している。
【００６６】
以下０ビット目の場合と同様に、２ビット目が１であるものはノード２１１ｆ側に分類され、２ビット目が０であるものはノード２１０ｆ側に分類される。
そして２ビット目が１であるインデックスキーは３ビット目の異なるものがあるのでノード２１１ｆの弁別ビット位置には３が格納され、２ビット目が０であるインデックスキーでは３ビット目も４ビット目も等しく５ビット目で異なるのでノード２１０ｆの弁別ビット位置には５が格納される。
【００６７】
ノード２１１ｆのリンク先においては、３ビット目が１のものと０のものがそれぞれ１つしかないことから、ノード２１０ｈ、２１１ｈはリーフノードとなり、それぞれインデックスキー２５０ｈと２５１ｈに“１０１０１１”と“１０１１００”が格納されている。
【００６８】
仮にインデックスキーの集合に“１０１１００”の代わりに“１０１１０１”か“１０１１１０”が含まれていたとしても、３ビット目までは“１０１１００”と等しいので、ノード２１１ｈに格納されるインデックスキーが変わるだけで、ツリー構造自体は変わることはない。しかし、“１０１１００”に加えて“１０１１０１”が含まれていると、ノード２１１ｈはブランチノードとなり、その弁別ビット位置は５になる。追加されるインデックスキーが“１０１１１０”であれば、弁別ビット位置は４となる。
【００６９】
以上説明したように、カップルドノードツリーの構造は、インデックスキーの集合に含まれる各インデックスキーの各ビット位置のビット値により決定される。
そしてさらにいえば、異なるビット値となるビット位置ごとにビット値が“１”のノードとビット値が“０”のノードとに分岐していることから、ノード［１］側とツリーの深さ方向を優先させてリーフノードをたどると、それらに格納されたインデックスキーは、ノード２１１ｈのインデックスキー２５１ｈの“１０１１００”、ノード２１０ｈのインデックスキー２５０ｈの“１０１０１１”、・・・、ノード２１０ｃのインデックスキー２５０ｃの“０００１１１”となり降順にソートされている。
【００７０】
すなわち、カップルドノードツリーにおいては、インデックスキーはソートされてツリー上に配置されている。
検索キーで検索するときはインデックスキーがカップルドノードツリー上に配置されたルートをたどることになり、例えば検索キーが“１０１１００”であればノード２１１ｈに到達することができる。また、上記説明からも想像がつくように、“１０１１０１”か“１０１１１０”を検索キーとした場合でもノード２１１ｈにたどり着き、インデックスキー２５１ｈと比較することにより検索が失敗したことが分かる。
【００７１】
また、例えば“１００１００”で検索した場合でも、ノード２１０ａ、２１１ｂ、２１０ｆのリンク経路では検索キーの３ビット目と４ビット目は使われることがなく、“１００１００”の５ビット目が０なので、“１０００１０”で検索した場合と同様にノード２１０ｇに到達することになる。このように、カップルドノードツリーに格納されたインデックスキーのビット構成に応じた弁別ビット位置を用いて分岐が行われる。
【００７２】
図３は、本発明を実施するためのハードウェア構成例を説明する図である。
本発明の検索装置による検索処理及びデータメンテナンスは中央処理装置３０２及びキャッシュメモリ３０３を少なくとも備えたデータ処理装置３０１によりデータ格納装置３０８を用いて実施される。カップルドノードツリーが配置される配列３０９と検索中にたどるノードが格納された配列要素の配列番号を記憶する探索経路スタック３１０を有するデータ格納装置３０８は、主記憶装置３０５または外部記憶装置３０６で実現することができ、あるいは通信装置３０７を介して接続された遠方に配置された装置を用いることも可能である。図１の配列１００は、配列３０９の一例である。
【００７３】
図３の例示では、主記憶装置３０５、外部記憶装置３０６及び通信装置３０７が一本のバス３０４によりデータ処理装置３０１に接続されているが、接続方法はこれに限るものではない。また、主記憶装置３０５をデータ処理装置３０１内のものとすることもできるし、探索経路スタック３１０を中央処理装置３０２内のハードウェアとして実現することも可能である。あるいは、配列３０９は外部記憶装置３０６に、探索経路スタック３１０を主記憶装置３０５に持つなど、使用可能なハードウェア環境、インデックスキー集合の
大きさ等に応じて適宜ハードウェア構成を選択できることは明らかである。
【００７４】
また、特に図示されてはいないが、処理の途中で得られた各種の値を後の処理で用いるためにそれぞれの処理に応じた一時記憶装置が用いられることは当然である。
次に、上述の出願において、本出願人により提案されたカップルドノードツリーを用いた基本的な検索処理、及びカップルドノードツリーに含まれるインデックスキーの最大値／最小値を求める処理等の応用処理の一部について、本発明を理解するために必要な範囲で紹介する。
【００７５】
図４は、本出願人による出願である上記特願２００６−２９３６１９で提案されたビット列検索の基本動作を示したフローチャートである。
まず、ステップＳ４０１で、検索開始ノードの配列番号を取得する。取得された配列番号に対応する配列要素は、カップルドノードツリーを構成する任意のノードを格納したものである。検索開始ノードの指定は、後に説明する各種応用検索において行われる。
【００７６】
次に、ステップＳ４０２で、探索経路スタック３１０に取得された配列番号を格納し、ステップＳ４０３で、その配列番号に対応する配列要素を参照すべきノードとして読み出す。そして、ステップＳ４０４で、読み出したノードから、ノード種別を取り出し、ステップＳ４０５で、ノード種別がブランチノードであるか否かを判定する。
【００７７】
ステップＳ４０５の判定において、読み出したノードがブランチノードである場合は、ステップＳ４０６に進み、ノードから弁別ビット位置についての情報を取り出し、更に、ステップＳ４０７で、取り出した弁別ビット位置に対応するビット値を検索キーから取り出す。そして、ステップＳ４０８で、ノードから代表ノード番号を取り出して、ステップＳ４０９で、検索キーから取り出したビット値と代表ノード番号とを加算し、新たな配列番号として、ステップＳ４０２に戻る。
【００７８】
以降、ステップＳ４０５の判定においてリーフノードと判定されてステップＳ４１０に進むまで、ステップＳ４０２からステップＳ４０９までの処理を繰り返す。ステップＳ４１０で、リーフノードからインデックスキーを取り出して、処理を終了する。
【００７９】
図５は、本出願人による出願である上記特願２００６−２９３６１９で提案されたカップルドノードツリー（部分木を含む）に格納されたインデックスキーの最小値を求める処理を示したフローチャートである。先に述べたようなインデックスキーのツリー上の配置から、インデックスキーの最小値を求める処理は検索開始ノードからノード［０］をリーフノードに至るまでツリー上でたどることに相当する。
【００８０】
まず、ステップＳ５０１の検索開始ノードの配列番号の取得からステップＳ５０５のノード種別の判定までは、それぞれ上述の図４のステップＳ４０１からステップＳ４０５の処理と同様である。
【００８１】
ステップＳ５０５のノード種別の判定においてノード種別がブランチノードと判定されると、ステップＳ５０６に進み、ノードから配列の代表ノード番号を取り出し、ステップＳ５０７で、取り出した代表ノード番号に値「０」を加算してその結果を新たな配列番号とし、ステップＳ５０２に戻る。以降、ステップＳ５０５においてそのノードがリーフノードと判定されるまでステップＳ５０２からステップＳ５０７までの処理を繰り返し、ステップＳ５０８で、リーフノードからインデックスキーを取り出し、処理を終了する。
【００８２】
上記の図５に示す処理においては、ノード［０］をたどるため、代表ノード番号に一律「０」を加算している。すなわち、図５の処理によれば、リンク先のノードは、ノード対
のうち必ずノード［０］とし、より小さい値のインデックスキーが格納されているノードのほうに分岐している。これにより、ツリー構造が先に述べたように順列構成であるカップルドノードツリーの最小のインデックスキーを取り出すことができる。
【００８３】
図６は、本出願人による出願である上記特願２００６−２９３６１９で提案されたカップルドノードツリー（部分木を含む）に格納されたインデックスキーの最大値を求める処理を示したフローチャートである。
【００８４】
インデックスキーの最大値を求める処理は、ツリー上のノードのうちノード［１］について、リーフノードに至るまで順次たどっていくことに相当する。以下、任意の部分木の最大のインデックスキーを求める処理について、上記最小のインデックスキーを求める処理と比較しながら、異なる点を中心に説明する。
【００８５】
図６に示す一連の処理のうち、ステップＳ６０１からステップＳ６０６及びステップＳ６０８については、図５のステップ５０１からステップＳ５０６及びステップＳ５０８にそれぞれ対応しており、同様の処理が実行される。図５の最小値を求める処理と異なる点は、ステップＳ６０７において、代表ノード番号に、値「１」を加算する点である。これにより、代表ノード番号が表すノード対のうち、ノード［１］に常にリンクすることとなり、リーフノードに至るまで順次ステップＳ６０２からステップＳ６０７の処理を繰り返すことにより、インデックスキーの最大値を得ることができる。
【００８６】
図４から図６に示すように、検索キーと一致するインデックスキーを検索する基本動作やインデックスキーの最小値／最大値の検索処理を実行する際には、探索経路スタック３１０に参照した配列の配列番号が順次格納されていく。
【００８７】
なお、上述の図５及び図６を参照したインデックスキーの最小値／最大値の検索処理では、カップルドノードツリーは配列に記憶されたものとして説明したが、カップルドノードツリーが配列に記憶されることは必須ではなく、ノード対を構成する２つのノードのうちの代表ノードのみあるいは代表ノードと隣接した記憶領域に配置されたノードのみをリンクしてリーフノードに至ることによりインデックスキーの最小値／最大値の検索が可能であることは明らかである。
【００８８】
図７は、本出願人による出願である上記特願２００６−２９３６１９で提案されたカップルドノードツリーに格納されたインデックスキーを昇順に取り出す処理を示したフローチャートである。インデックスキーを昇順に取り出す処理は、ノード対をなすノードのうちノード［０］側及びツリーの深さを優先させてルートノードから順次リーフノードをたどり、各リーフノードからインデックスキーを取り出していくことに相当する。
【００８９】
まず、ステップＳ７０１で、検索開始ノードの配列番号にルートノードの配列番号を設定し、ステップＳ７０２で、上記図５を参照して説明した最小のインデックスキーを求める処理を実行して、カップルドノードツリーに含まれるインデックスキーの中で最小のインデックスキーを取得する。そして、ステップＳ７０３で、取得したインデックスキーを取り出し、ステップＳ７０４に進む。
【００９０】
ステップＳ７０４で、探索経路スタック３１０を参照し、スタックポインタがルートノードの配列番号を指しているか否かを判定する。ポインタが指す配列番号がルートノード以外である場合は、ステップＳ７０５に進む。そして、ステップＳ７０５で、探索経路スタック３１０からポインタの指す配列番号を取り出してから、ポインタを１減らす。上記ステップＳ７０５で探索経路スタック３１０からポインタの指す配列番号を取り出してからポインタを１減らすことは、スタックのポップ動作により実行される。以下の各実施態
様におけるスタックからの配列番号の読み出しにおいても同様である。
【００９１】
ステップＳ７０６で、ステップＳ７０５で取り出した配列番号から、その配列番号のノードがノード対のどちらの配列要素に格納されているかのノード位置を得る。例えばノード［０］については偶数番号の配列の配列要素に格納する等により、配列番号からノード位置を求めることができる。そして、ステップＳ７０７で、ステップＳ７０６で得たノード位置がノード［１］側であるか否かを判定する。ステップＳ７０７においてノード［１］側と判定された場合は、ステップＳ７０４に戻り、ポインタの指す配列番号のノードがノード［０］あるいはルートノードとなるまで、ステップＳ７０４からステップＳ７０７までの処理を繰り返す。
【００９２】
ステップＳ７０７においてノード［０］側と判定されると、ステップＳ７０８に進み、配列番号に１を加算し、そのノードと対をなすノード［１］の配列番号を得る。そして、ステップＳ７０９で、検索開始ノードの配列番号にステップＳ７０８で得たノード［１］の配列番号を設定し、ステップＳ７１０で、検索開始ノードをルートノードとする部分木の最小のインデックスキーを求める処理を実行する。ステップＳ７１０の処理は、ステップＳ７０２と同様であり、図５に示す最小値検索処理が用いられる。
【００９３】
ステップＳ７１０で最小のインデックスキーを求めると、ステップＳ７０３に戻り、求めたインデックスキーを取り出し、以降ステップＳ７０４においてスタックポインタがルートノードの配列番号を指していると判定されるまで、同様の処理を繰り返す。
【００９４】
このように、探索経路スタック３１０のポインタが指す配列番号を参照し、探索経路スタック３１０に格納されている配列番号のノード［０］と対をなすノード［１］について、そのノードを検索開始ノードとしてそのノード配下で最小のインデックスキーを求める。ステップＳ７０２で最小値が求められた段階においては、探索経路スタック３１０のポインタは、カップルドノードツリーの最小のインデックスキーを含むノードの配列番号を指している。続いて探索経路スタック３１０のポップ動作を行い、取り出した配列番号のノードのうちノード［１］を検索開始ノードとして該検索開始ノードをルートノードとする部分木のインデックスキーの最小値を求める処理を行い、探索経路スタック３１０のポップ動作の結果カップルドノードツリーのルートノードの配列番号が取り出されるまでポップ動作と最小値検索処理を繰り返す。
【００９５】
探索経路スタック３１０には、先にステップＳ７０２においてルートノード配下のノードについて最小値を求める処理を行っていることにより、リンク経路についての配列番号が順次格納されている。このため、探索経路スタック３１０のポインタを１減らして新たにポインタが指す配列番号のノードのうち、ノード［０］について、そのノードと対をなすノード［１］を求め、ノード［１］のノード配下について順次最小値検索の処理を行っていくと、インデックスキーは昇順に取り出されることとなる。
【００９６】
図８は、カップルドノードツリーに格納されたインデックスキーを降順に取り出す処理を示したフローチャートである。インデックスキーを降順に取り出す処理は、ノード対をなすノードのうちノード［１］及びツリーの深さを優先させてルートノードから順次リーフノードをたどっていくことに相当する。ここでは、図７のインデックスキーを昇順に取り出す処理と比較して、異なる点を中心に説明する。
【００９７】
上記のインデックスキーを昇順に取り出す処理においては、図７のステップＳ７０２及びステップＳ７１０において検索開始ノード配下の最小値をとるインデックスキーを求めていたのに対し、図８のステップＳ８０２及びステップＳ８１０において求めるのは、検索開始ノード配下の最大値をとるインデックスキーである。
【００９８】
また、図７においてはステップＳ７０３で所望のインデックスキーを取り出した後、探索経路スタック３１０に格納されている配列番号のうち、ノード［０］の配列番号を求め、そのノードと対をなすノード［１］を検索開始ノードとして設定して、最小値検索処理を行っている。これに対して、図８の降順取り出し処理においては、ステップＳ８０３において所望のインデックスキーを取り出した後、探索経路スタック３１０に格納されている配列番号のうち、ノード［１］の配列番号を求め、そのノードと対をなすノード［０］を検索開始ノードとして設定して、最大値検索処理を行っている。
【００９９】
次に、図９Ａ〜図９Ｃ、図９Ｄにより本出願人による出願である上記特願２００６−１８７８２７で提案されたカップルドノードツリーにおけるノード挿入処理を説明する。図９Ａ〜図９Ｃが通常の挿入処理を説明するものであり、図９Ｄはルートノードの挿入処理を説明するものである。ルートノードの挿入処理と通常の挿入処理により、カップルドノードツリーが生成されることから、ノード挿入処理の説明はカップルドノードツリーの生成処理の説明でもある。
【０１００】
図９Ａは挿入処理の前段である検索処理の処理フローを示す図であり、図４に示した検索処理において挿入キーを検索キーとしたものに相当する。ステップＳ９０１は図４のステップＳ４０１で検索開始ノードをルートノードとしたものに相当し、ステップＳ９０２〜ステップＳ９１０の処理は図４のステップＳ４０２〜ステップＳ４１０に完全に対応するので説明は省略する。
【０１０１】
図９ＡのステップＳ９１１において挿入キーとインデックスキーを比較し、等しければ挿入キーは既にカップルドノードツリーに存在するのであるから、挿入は失敗となり、処理を終了する。等しくなければ次の処理、図９ＢのステップＳ９１２以下の処理に進む。
【０１０２】
図９Ｂは、挿入するノード対のための配列要素を準備する処理を説明する処理フロー図である。
ステップＳ９１２において、配列から空きのノード対を求め、そのノード対のうち代表ノードとなるべき配列要素の配列番号を取得する。
【０１０３】
ステップＳ９１３に進み、挿入キーとステップＳ９１０で得たインデックスキーの大小を比較し、挿入キーが大きいときは値１を小さいときは値０のブール値を得る。
ステップＳ９１４に進み、ステップＳ９１２で得た代表ノードの配列番号にステップＳ９１３で得たブール値を加算した配列番号を得る。
【０１０４】
ステップＳ９１５に進み、ステップＳ９１２で得た代表ノードの配列番号にステップＳ９１３で得たブール値の論理否定値を加算した配列番号を得る。
ステップＳ９１４で得た配列番号は、挿入キーをインデックスキーとして持つリーフノードが格納される配列要素の配列番号であり、ステップＳ９１５で得た配列番号は、そのリーフノードと対を成すブランチノードが格納される配列要素のものである。
【０１０５】
つまり、前段の検索処理で得られたリーフノードに格納されたインデックスキーと挿入キーの大小により、挿入されるノード対のうちどちらのノードに挿入キーを保持するリーフノードが格納されるかが決定される。
【０１０６】
例えば図２のカップルドノードツリーに“０１１０１１”を挿入する場合、検索結果のインデックスキーはノード２１１ｄに格納された“０１１０１０”になる。挿入キー“０１１０１１”とノード２１１ｄに格納されたインデックスキー“０１１０１０”の大小比較によりブール値が求められ、今の例では挿入キーが大きいのでブール値１が得られ、挿
入されるノード対の代表ノード番号に１を加えた配列要素に挿入キーを保持するリーフノードが格納される。一方、インデックスキー“０１１０１０”は、大小比較で得られたブール値を論理反転した値を代表ノード番号に加算した配列番号の配列要素に格納される。
【０１０７】
その際、インデックスキー“０１１０１０”と挿入キー“０１１０１１”とは５ビット目で異なることから、ノード２１１ｄは、弁別ビット位置を５とし、代表ノード番号を挿入されたノード対の代表ノードの配列番号とするブランチノードとなる。
【０１０８】
また図２のカップルドノードツリーに“０１１００１”を挿入しようとする場合も、検索結果のインデックスキーはノード２１１ｄに格納された“０１１０１０”になる。この場合には挿入キーが小さいのでブール値０が得られ、挿入されるノード対の代表ノード番号に０を加えた配列要素に挿入キーを保持するリーフノードが格納される。そして、インデックスキー“０１１０１０”と挿入キー“０１１００１”とは４ビット目で異なることから、ノード２１１ｄは、弁別ビット位置を４とし、代表ノード番号を挿入されたノード対の代表ノードの配列番号とするブランチノードとなる。次に図９ＣのステップＳ９１６以下の処理に進む。
【０１０９】
図９Ｃは図９Ｂで準備された配列要素にノードを格納するとともにその挿入位置を求め、既存のノードの内容を変更して挿入処理を完成させる処理フローを示す図である。
ステップＳ９１６〜ステップＳ９２３までの処理は、挿入するノード対のカップルドノードツリー上の位置を求める処理であり、ステップＳ９２４以下の処理は各ノードにデータを設定して挿入処理を完成させる処理である。
【０１１０】
ステップＳ９１６で、挿入キーとステップＳ９１０で得たインデックスキーのビット列比較を例えば排他的論理和で行い、差分ビット列を得る。
ステップＳ９１７に進み、ステップＳ９１６で得た差分ビット列から、上位０ビット目から見た最初の不一致ビットのビット位置を得る。この処理は、例えばプライオリティエンコーダを有するＣＰＵではそこに差分ビット列を入力し、不一致のビット位置を得ることができる。また、ソフト的にプライオリティエンコーダと同等の処理を行い最初の不一致ビットのビット位置を得ることも可能である。
【０１１１】
次にステップＳ９１８に進み、探索経路スタックのスタックポインタがルートノードの配列番号を指しているか判定する。指していればステップＳ９２４に移行し、指していなければステップＳ９１９に進む。
【０１１２】
ステップＳ９１９において、探索経路スタックのスタックポインタを１つ戻してそこにスタックされている配列番号を取り出す。
ステップＳ９２０に進み、ステップＳ９１９で取り出した配列番号の配列要素を配列からノードとして読み出す。
【０１１３】
ステップＳ９２１に進み、ステップＳ９２０で読み出したノードから、弁別ビット位置を取り出す。
次にステップＳ９２２に進み、ステップＳ９２１で取り出した弁別ビット位置がステップＳ９１７で得たビット位置より上位の位置関係か判定する。ここで上位の位置関係とは、ビット列のより左側の位置、すなわちビット位置の値が小さい位置であることとする。
【０１１４】
ステップＳ９２２の判定結果が否定であれば、ステップＳ９１８に戻り、ステップＳ９１８での判定が肯定になるかステップＳ９２２での判定が肯定になるまで繰り返す。ステップＳ９２２での判定が肯定になると、ステップＳ９２３で探索経路スタックのスタックポインタを１つ進め、ステップＳ９２４以下の処理に移行する。
【０１１５】
上記ステップＳ９１６〜ステップＳ９２３で説明した処理は、挿入するノード対の挿入位置を決定するために、挿入するインデックスキーと検索により取得されたインデックスキーの間でビット列比較を行い、ビット列比較で異なるビット値となる先頭の（最上位の）ビット位置と探索経路スタックに格納されているブランチノードの弁別ビット位置との相対的位置関係を調べ、弁別ビット位置が上位となるブランチノードの次のブランチノードのリンク先を挿入するノード対の挿入位置とするものである。
【０１１６】
例えば図２のカップルドノードツリーに“１１１０００”を挿入するとき、検索結果のインデックスキーはノード２１０ｈに格納された“１０１０１１”になる。挿入キー“１１１０００”とノード２１０ｈに格納されたインデックスキー“１０１０１１”のビット列比較により異なるビット値となる最上位のビット位置１が得られる。得られたビット位置１と探索経路スタックに積まれた配列番号の配列要素に格納されたブランチノードの弁別ビット位置との位置関係をチェックしながら、弁別ビット位置が上位になるまで順次探索経路スタックを逆にたどると、ルートノード２１０ａに至る。そこで探索経路スタックのポインタを１つ進め、ノード２１１ｂの配列番号を得る。挿入キー“１１１０００”はノード２１１ｂのリンク先に挿入される。
【０１１７】
また、探索経路スタックを逆にたどりルートノードに至っても、ルートノードの弁別ビット位置が、先に求めたビット列比較で異なるビット値となる最上位のビット位置より上位のビット位置でないということは、そのカップルドノードツリーのインデックスキーの上位ビットで、ルートノードの弁別ビット位置より上位のビットの値は全て等しい場合である。そして、挿入するインデックスキーにおいて、初めてルートノードの弁別ビット位置より上位のビットの値に異なるビット値のものがあるということである。したがって、挿入するノード対はルートノードの直接のリンク先となり、ルートノードの弁別ビット位置は、既存のインデックスキーと異なる値である挿入キーの最上位ビットの位置に変わる。
【０１１８】
次に、ステップＳ９２４以下の各ノードにデータを設定して挿入処理を完成させる処理について説明する。
ステップＳ９２４では探索経路スタックからスタックポインタの指す配列番号を取り出す。
【０１１９】
ステップＳ９２５において、ステップＳ９１４で得た配列番号の指す配列要素のノード種別に１（リーフノード)を、インデックスキーに挿入キーを書き込む。
ステップＳ９２６に進み、配列からステップＳ９２４で得た配列番号の配列要素を読み出す。
【０１２０】
次にステップＳ９２７において、ステップＳ９１５で得た配列番号の配列要素にステップＳ９２６で読み出した内容を書き込む。
最後にステップＳ９２８において、ステップＳ９２４で得た配列番号の指す配列要素のノード種別に０(ブランチノード）を、弁別ビット位置にステップＳ９１７で得たビット位置を、代表ノード番号にステップＳ９１２で得た配列番号を書き込み、処理を終了する。
【０１２１】
上述の図２のカップルドノードツリーに“１１１０００”を挿入する例では、取得された空ノード対のノード［０］にノード２１１ｂの内容を書き込み（ステップＳ９２７）、ノード［１］を挿入キー“１１１０００”を保持するリーフノードとする（ステップＳ９２５）。そして、ノード２１１ｂの弁別ビット位置にビット列比較により異なるビット値となる最上位のビット位置１を格納し、代表ノード番号には取得されたノード対の代表ノ
ードが格納される配列要素の配列番号が格納される（ステップＳ９２８）。
【０１２２】
図９Ｄは、本出願人による出願である上記特願２００６−１８７８２７で提案されたルートノードの挿入処理を含むインデックスキーを追加する場合のノード挿入処理全体を説明する処理フロー図である。
【０１２３】
ステップＳ１０１において、取得することを求められたカップルドノードツリーのルートノードの配列番号が登録済みであるか判定される。登録済みであれば、図９Ａ〜図９Ｃを用いて説明した通常の挿入処理が行われる。
【０１２４】
ステップＳ１０１での判定が登録済みでなければ、まったく新しいカップルドノードツリーの登録、生成が始まることになる。
まず、ステップＳ１０２において、配列から空きのノード対を求め、そのノード対のうち代表ノードとなるべき配列要素の配列番号を取得する。次にステップＳ１０３において、ステップＳ１０２で得た配列番号に０を加えた配列番号を求める。（実際には、ステップＳ１０２で取得した配列番号に等しい。)。さらにステップＳ１０４において、ステップＳ１０３で得た配列番号の配列要素に、挿入するルートノードのノード種別に１（リーフノード)とインデックスキーに挿入キーを書き込み、ステップＳ１０５で、ステップＳ１０２で取得したルートノードの配列番号を登録して処理を終了する。
【０１２５】
先にも述べたように、インデックスキーの集合があるとき、そこから順次インデックスキーを取り出し、図９Ｄ及び図９Ａ〜図９Ｃの処理を繰り返すことにより、インデックスキーの集合に対応した本発明のカップルドノードツリーを構築することができることは明らかである。
【０１２６】
以上、カップルドノードツリーの退避／復元処理の前提となる技術を説明したが、必要とあれば、上述の特許出願の明細書及び図面の記載を参照されたい。
次に、本発明によるカップルドノードツリーの退避／復元処理について説明する。
【０１２７】
図１０Ａと図１０Ｂは、本発明の一実施形態によるカップルドノードツリーを退避する退避処理を示したフローチャートである。本実施形態では、配列３０９に配置されたカップルドノードツリーのノード対をなすノードのうち、ノード［０］側及びツリーの深さを優先させてルートノードからカップルドノードツリーの各ノードをたどり、その深さ優先探索順に、たどったノードをノード退避配列４０１に退避する。ノード退避配列４０１は、本実施形態において退避用の記憶領域として用いられる配列である。深さ優先探索順にノードをたどる点は、図７を参照して説明したインデックスキーを昇順に取り出す処理と共通であるから、図１０Ａは図７と類似したものである。
【０１２８】
まず、ステップＳ１００１で、巡回開始ノードの配列番号としてルートノードの配列番号を設定する。つまり、巡回開始ノードの配列番号を設定すべきワークエリアを用意し、そのワークエリアにルートノードの配列番号を設定する。
【０１２９】
次に、ステップＳ１００２で、後述の図１０Ｂの処理を実行して、ノード［０］のみをたどって巡回開始ノードからリーフノードへ至るまでの経路を巡回し、巡回したノードを順次ノード退避配列４０１に格納する。ステップＳ１００１とＳ１００２は、図７のステップＳ７０１とＳ７０２に類似の処理である。
【０１３０】
ステップＳ１００２の実行後、ステップＳ１００３に進む。ステップＳ１００３からステップＳ１００９は、図７のステップＳ７０４からステップＳ７１０に類似の処理である。
【０１３１】
ステップＳ１００３で、探索経路スタック３１０を参照し、スタックポインタがルートノードの配列３０９上の配列番号を指しているか否かを判定する。ポインタが指す配列３０９上の配列番号がルートノード以外である場合は、ステップＳ１００４に進む。そして、ステップＳ１００４で、探索経路スタック３１０からポインタの指す配列３０９上の配列番号を取り出してから、ポインタを１減らす。すなわち、ステップＳ１００４ではポップ動作が行われる。
【０１３２】
ステップＳ１００５で、ステップＳ１００４で取り出した配列３０９の配列番号から、その配列番号のノードがノード対のどちらの配列要素に格納されているかのノード位置を得る。そして、ステップＳ１００６で、ステップＳ１００５で得たノード位置がノード［１］側であるか否かを判定する。ステップＳ１００６においてノード［１］側と判定された場合は、ステップＳ１００３に戻り、ポインタの指す配列番号のノードがノード［０］あるいはルートノードとなるまで、ステップＳ１００３からステップＳ１００６までの処理を繰り返す。
【０１３３】
ステップＳ１００６においてノード［０］側と判定されると、ステップＳ１００７に進み、配列番号に１を加算し、そのノード［０］と対をなすノード［１］の配列３０９上の配列番号を得る。そして、ステップＳ１００８で、巡回開始ノードの配列番号としてステップＳ１００７で得たノード［１］の配列番号を設定し、ステップＳ１００９で、ステップＳ１００２と同様に図１０Ｂの処理を実行し、ノード［０］のみをたどって巡回開始ノードからリーフノードへ至るまでの経路を巡回し、巡回したノードを順次ノード退避配列４０１に格納する。その後はステップＳ１００３に戻り、以降ステップＳ１００３においてスタックポインタがルートノードの配列３０９上の配列番号を指していると判定されるまで、同様の処理を繰り返す。
【０１３４】
なお、図１０ＡのステップＳ１００２とステップＳ１００９は同じ処理であるから、ステップＳ１００８からステップＳ１００２に戻るように図示することも可能である。しかし、後の説明の都合上、ステップＳ１００３からステップＳ１００９までを連続する番号で参照することが便利なため、図１０Ａのように示した。
【０１３５】
次に、図１０Ｂを参照して、ノードを巡回しながらノードをノード退避配列４０１に格納する処理について説明する。図１０Ｂの処理は、図１０ＡのステップＳ１００２またはＳ１００９から呼び出される。また、図１０Ｂの処理は、図５を参照して説明したインデックスキーの最小値を求める処理の応用例である。
【０１３６】
まず、ステップＳ１０１１で、図１０ＡのステップＳ１００１またはステップＳ１００８で設定された巡回開始ノードの配列番号を取得する。この配列番号は配列３０９の配列番号である。次に、取得された配列番号をステップＳ１０１２で探索経路スタック３１０に格納し、ステップＳ１０１３で、その配列番号に対応する配列要素を参照すべきノードとして配列３０９から読み出す。そして、ステップＳ１０１４で、読み出したノードをノード退避配列４０１に格納する。なお、ノード退避配列４０１は、最初の配列要素から順に、間を空けずに詰めて使われる。
【０１３７】
続いてステップＳ１０１５で、読み出したノードからノード種別を取り出し、ステップＳ１０１６で、ノード種別がブランチノードであるか否かを判定する。
ステップＳ１０１６の判定において、読み出したノードがブランチノードである場合は、ステップＳ１０１７に進んでノードから代表ノード番号を取り出し、ステップＳ１０１８で取り出した代表ノード番号に値「０」を加算してその結果を新たな配列番号とし、ステップＳ１０１２に戻る。以降、ステップＳ１０１６においてそのノードがリーフノード
と判定されるまでステップＳ１０１２からステップＳ１０１８までの処理を繰り返す。ステップＳ１０１６においてノード種別がリーフノードと判定されると、処理を終了する。
【０１３８】
図１０Ｂの処理は、図５のインデックスキーの最小値を求める処理との共通点から明らかなとおり、巡回開始ノードをルートノードとする部分木において、巡回開始ノードから最小のインデックスキーを含むリーフノードまでの経路を巡回する処理である。そして、巡回開始ノードからリーフノードまでの経路上のノードは、経路の両端である巡回開始ノードとリーフノードを含めて、順次、探索経路スタック３１０に配列番号が格納され、ノード退避配列４０１にそのノードの内容が格納される。
【０１３９】
インデックスキーを昇順に取り出す図７の処理が、最小のインデックスキーを検索する図５の処理を含むのと同様に、ノード［０］側及びツリーの深さを優先させた探索順にノードをノード退避配列４０１に退避する図１０Ａの処理が、巡回開始ノードから巡回開始ノードをルートノードとする部分木で最小のインデックスキーを含むリーフノードまでのノードをたどる図１０Ｂの処理を含む。
【０１４０】
図１１と図１２は、図１０Ａと図１０Ｂのフローチャートにより示した本実施形態に係る退避処理を、図２に例示したカップルドノードツリーを退避する例を用いて説明する図である。以下では、図１１と図１２の双方を参照して、図２のカップルドノードツリーが図１０Ａと図１０Ｂの退避処理により退避される流れを説明する。
【０１４１】
図１１には、処理の流れを表す矢印とともに図２と同じカップルドノードツリーを示し、ノード退避配列４０１の最終的な内容も示した。図１２は、図１１の処理の各段階における探索経路スタック３１０の状態とノード退避配列４０１に退避された内容を示す図である。
【０１４２】
ノード退避配列４０１の各配列要素には、その配列要素に退避されるノードの符号と対応する、アポストロフィ付きの符号を付した。例えば、ノード２１０ａの内容を退避した配列要素には「２１０ａ’」なる符号を付した。また、説明の便宜上、ノード退避配列４０１の配列要素を、０から始まる配列番号により参照する。この配列番号は、図１１と図１２のノード退避配列４０１の左側に示してある。なお、図１２の探索経路スタック３１０に格納されている配列３０９の配列番号は、図１１に示すカップルドノードツリーと対応付けられている。
【０１４３】
退避処理は、図１１のステップＳ１１０１の矢印に示すように、ルートノード２１０ａを巡回開始ノードとして、ルートノード２１０ａの配下で最小のインデックスキーを含むリーフノード２１０ｃへの経路を巡回することから始まる。これは図１０ＡのステップＳ１００１とステップＳ１００２に対応する。よって、ステップＳ１００２から呼び出された図１０ＢのステップＳ１０１１からステップＳ１０１８の実行結果として、図１２（ａ）に示すとおり、探索経路スタック３１０にはルートノード２１０ａの配列番号２２０から順に、配列番号２２０ａ、２２０ｂが格納され、ノード退避配列４０１の配列番号０、１、２の配列要素には、ルートノード２１０ａ、ノード２１０ｂ、ノード２１０ｃの内容がそれぞれ退避される。
【０１４４】
続いて、ステップＳ１００３からステップＳ１００８が実行される。それにより、ステップＳ１００４で配列番号２２０ｂが探索経路スタック３１０から得られ、配列番号２２０ｂのノード２１０ｃはノード［０］なので、ステップＳ１００６からステップＳ１００７に進んで配列番号（２２０ｂ＋１）が得られ、これがステップＳ１００８で巡回開始ノードの配列番号に指定される。
【０１４５】
そして、図１１のステップＳ１１０２に示すとおり、配列番号（２２０ｂ＋１）のノード２１１ｃを巡回開始ノードとして、ノード２１１ｃの配下で最小のインデックスキーを含むリーフノード２１０ｅへの経路を巡回する。これは図１０ＡのステップＳ１００９から図１０Ｂの処理を呼び出して実行することに対応する。よって、図１０ＢのステップＳ１０１１からステップＳ１０１８の実行結果として、図１２（ｂ）に示すとおり、探索経路スタック３１０には配列番号（２２０ｂ＋１）、２２１ｃ、２２０ｄが順に格納され、ノード退避配列４０１の配列番号３、４、５の配列要素には、ノード２１１ｃ、ノード２１０ｄ、ノード２１０ｅの内容がそれぞれ退避される。なお、図１２（ｂ）のノード退避配列４０１のうち、ステップＳ１１０１で退避済みのノードに対応する配列番号０から２の部分は細線で囲い、ステップＳ１１０２で退避されたノードに対応する配列番号３から５の部分は太線で囲んである。以下のステップでも同様にノード退避配列４０１を表現する。
【０１４６】
続いて、ステップＳ１００３からステップＳ１００８が実行される。それにより、ステップＳ１００４で配列番号２２０ｄが探索経路スタック３１０から得られ、配列番号２２０ｄのノード２１０ｅはノード［０］なので、ステップＳ１００６からステップＳ１００７に進んで配列番号（２２０ｄ＋１）が得られ、これがステップＳ１００８で巡回開始ノードの配列番号に指定される。
【０１４７】
そして、図１１のステップＳ１１０３に示すとおり、配列番号（２２０ｄ＋１）のノード２１１ｅを巡回開始ノードとして、図１０ＡのステップＳ１００９から図１０Ｂの処理が呼び出されて、ステップＳ１０１１からステップＳ１０１６が実行される。ノード２１１ｅはリーフノードなので、図１２（ｃ）に示すとおり、この処理の結果として、配列番号（２２０ｄ＋１）のみが探索経路スタック３１０に格納され、ノード退避配列４０１には配列番号６の配列要素としてノード２１１ｅの内容のみが退避される。
【０１４８】
続いて、ステップＳ１００３からステップＳ１００８が次のように実行される。すなわち、ステップＳ１００４で配列番号（２２０ｄ＋１）が探索経路スタック３１０から得られ、配列番号（２２０ｄ＋１）のノード２１１ｅはノード［１］なので、ステップＳ１００６からステップＳ１００３に戻る。そして再びステップＳ１００４のポップ動作が行われ、配列番号２２１ｃが探索経路スタック３１０から得られる。配列番号２２１ｃのノード２１０ｄはノード［０］なので、ステップＳ１００６からステップＳ１００７に進んで配列番号（２２１ｃ＋１）が得られ、これがステップＳ１００８で巡回開始ノードの配列番号に指定される。
【０１４９】
そして、図１１のステップＳ１１０４に示すとおり、配列番号（２２１ｃ＋１）のノード２１１ｄを巡回開始ノードとして、図１０ＡのステップＳ１００９から図１０Ｂの処理が呼び出されて、ステップＳ１０１１からステップＳ１０１６が実行される。ノード２１１ｄもリーフノードなので、図１２（ｄ）に示すとおり、この処理の結果として、配列番号（２２１ｃ＋１）のみが探索経路スタック３１０に格納され、ノード退避配列４０１には配列番号７の配列要素としてノード２１１ｄの内容のみが退避される。
【０１５０】
続いて、ステップＳ１００３からステップＳ１００８が次のように実行される。すなわち、ステップＳ１００４で配列番号（２２１ｃ＋１）が探索経路スタック３１０から得られる。配列番号（２２１ｃ＋１）のノード２１１ｄはノード［１］なのでステップＳ１００６からステップＳ１００３に戻り、再びステップＳ１００４のポップ動作が行われ、配列番号（２２０ｂ＋１）が探索経路スタック３１０から得られる。配列番号（２２０ｂ＋１）のノード２１１ｃもノード［１］なので再度ステップＳ１００３に戻り、ステップＳ１００４のポップ動作によって、配列番号２２０ａが探索経路スタック３１０から得られる。配列番号２２０ａのノード２１０ｂはノード［０］なので、ステップＳ１００６から
ステップＳ１００７に進んで配列番号（２２０ａ＋１）が得られ、これがステップＳ１００８で巡回開始ノードの配列番号に指定される。
【０１５１】
そして、図１１のステップＳ１１０５に示すとおり、配列番号（２２０ａ＋１）のノード２１１ｂを巡回開始ノードとして、図１０ＡのステップＳ１００９から図１０Ｂの処理を呼び出してステップＳ１０１１からステップＳ１０１８を実行し、ノード２１１ｂの配下で最小のインデックスキーを含むリーフノード２１０ｇへの経路を巡回する。その結果、図１２（ｅ）に示すとおり、探索経路スタック３１０には配列番号（２２０ａ＋１）、２２１ｂ、２２０ｆが順に格納され、ノード退避配列４０１の配列番号８、９、１０の配列要素には、ノード２１１ｂ、ノード２１０ｆ、ノード２１０ｇの内容がそれぞれ退避される。
【０１５２】
続いて、ステップＳ１００３からステップＳ１００８が実行される。それにより、ステップＳ１００４で配列番号２２０ｆが探索経路スタック３１０から得られ、配列番号２２０ｆのノード２１０ｇはノード［０］なので、ステップＳ１００６からステップＳ１００７に進んで配列番号（２２０ｆ＋１）が得られ、これがステップＳ１００８で巡回開始ノードの配列番号に指定される。
【０１５３】
そして、図１１のステップＳ１１０６に示すとおり、配列番号（２２０ｆ＋１）のノード２１１ｇを巡回開始ノードとして、図１０ＡのステップＳ１００９から図１０Ｂの処理が呼び出されてステップＳ１０１１からステップＳ１０１６が実行される。ノード２１１ｇはリーフノードなので、図１２（ｆ）に示すとおり、この処理の結果として、配列番号（２２０ｆ＋１）のみが探索経路スタック３１０に格納され、ノード退避配列４０１には配列番号１１の配列要素としてノード２１１ｇの内容のみが退避される。
【０１５４】
続いて、ステップＳ１００３からステップＳ１００８が次のように実行される。すなわち、ステップＳ１００４で配列番号（２２０ｆ＋１）が探索経路スタック３１０から得られ、配列番号（２２０ｆ＋１）のノード２１１ｇはノード［１］なので、ステップＳ１００６からステップＳ１００３に戻る。そして、ステップＳ１００４で配列番号２２１ｂが探索経路スタック３１０から得られる。配列番号２２１ｂのノード２１０ｆはノード［０］なので、ステップＳ１００６からステップＳ１００７に進んで配列番号（２２１ｂ＋１）が得られ、これがステップＳ１００８で巡回開始ノードの配列番号に指定される。
【０１５５】
そして、図１１のステップＳ１１０７に示すとおり、配列番号（２２１ｂ＋１）のノード２１１ｆを巡回開始ノードとして、図１０ＡのステップＳ１００９から図１０Ｂの処理を呼び出してステップＳ１０１１からステップＳ１０１８を実行し、ノード２１１ｆの配下で最小のインデックスキーを含むリーフノード２１０ｈへの経路を巡回する。その結果、図１２（ｇ）に示すとおり、探索経路スタック３１０には配列番号（２２１ｂ＋１）、２２１ｆが順に格納され、ノード退避配列４０１の配列番号１２、１３の配列要素には、ノード２１１ｆ、ノード２１０ｈの内容がそれぞれ退避される。
【０１５６】
続いて、ステップＳ１００３からステップＳ１００８が実行される。それにより、ステップＳ１００４で配列番号２２１ｆが探索経路スタック３１０から得られ、配列番号２２１ｆのノード２１０ｈはノード［０］なので、ステップＳ１００６からステップＳ１００７に進んで配列番号（２２１ｆ＋１）が得られ、これがステップＳ１００８で巡回開始ノードの配列番号に指定される。
【０１５７】
そして、図１１のステップＳ１１０８に示すとおり、配列番号（２２１ｆ＋１）のノード２１１ｈを巡回開始ノードとして、図１０ＡのステップＳ１００９から図１０Ｂの処理が呼び出されてステップＳ１０１１からステップＳ１０１６が実行される。ノード２１１
ｈはリーフノードなので、図１２（ｈ）に示すとおり、この処理の結果として、配列番号（２２１ｆ＋１）のみが探索経路スタック３１０に格納され、ノード退避配列４０１には配列番号１４の配列要素としてノード２１１ｈの内容のみが退避される。
【０１５８】
その後、ステップＳ１００３からステップＳ１００８が次のように実行される。すなわち、ステップＳ１００４で配列番号（２２１ｆ＋１）が探索経路スタック３１０から得られ、配列番号（２２１ｆ＋１）のノード２１１ｈはノード［１］なので、ステップＳ１００６からステップＳ１００３に戻る。そして、ステップＳ１００４で配列番号（２２１ｂ＋１）が探索経路スタック３１０から得られ、配列番号（２２１ｂ＋１）のノード２１１ｆもノード［１］なのでステップＳ１００６から再度ステップＳ１００３に戻る。そして、ステップＳ１００４で配列番号（２２０ａ＋１）が得られ、配列番号（２２０ａ＋１）のノード２１１ｂもノード［１］なのでステップＳ１００６から再度ステップＳ１００３に戻り、ここで、スタックポインタはルートノード２１０ａの配列番号２２０を指しているため、退避処理が終了する。
【０１５９】
以上の処理により、図１１に示したカップルドノードツリーを構成するノードはすべてノード退避配列４０１に退避される。また、ノードが退避される順序は、図１１のノード退避配列４０１と処理順を表す矢印とを比較すれば明らかなとおり、カップルドノードツリーのノード［０］側と深さ方向を優先して探索した順である。
【０１６０】
また、周知のように、ツリー構造のノードを深さ優先探索順に並べると、任意の部分木を構成するノードは連続した順序で並ぶ。例えば、ノード２１１ｃをルートノードとする部分木は、配列番号３から７の連続する領域に退避されている。
【０１６１】
図１３は、上記で説明した退避処理により得られたノード退避配列４０１からカップルドノードツリーを復元する復元処理を示したフローチャートであり、復元後のカップルドノードツリーが配列に記憶される場合のフローチャートである。復元後のカップルドノードツリーを記憶する配列は、例えば図３の配列３０９と同様の配列である。以下では、復元後のカップルドノードツリーを記憶する配列を「３０９’」なる符号で参照するが、配列３０９’は図示していない。
【０１６２】
実施形態によって、配列３０９と配列３０９’は同じ配列でもよく、同じ記憶装置上の異なる配列でもよく、異なる記憶装置上の異なる配列でもよい。また、以下の復元処理の説明では、探索経路スタック３１０を使うものとして説明しているが、元のカップルドノードツリーの検索等に使う探索経路スタック３１０とは異なる探索経路スタックを用いて復元処理を行ってもよいことは当然である。
【０１６３】
図１３では、まず、ステップＳ１３０１で、復元対象のカップルドノードツリーのノードを格納するための配列３０９’から、空きのノード対の代表ノード番号を得て、ステップＳ１３０２で、その代表ノード番号に値「０」を加え、ノード対のうちノード［０］の配列番号を得る。そしてステップＳ１３０３で、ルートノードの配列番号としてステップＳ１３０２で得た配列番号を登録する。ステップＳ１３０１からステップＳ１３０３の処理により、復元すべきカップルドノードツリーのルートノードの領域が確保され、ルートノードが登録される。
【０１６４】
続いてステップＳ１３０４で、探索経路スタック３１０に配列番号を格納する。図１３に示すとおり、ステップＳ１３０４は、ステップＳ１３０３、ステップＳ１３１３、またはステップＳ１３１７の直後に実行される。ステップＳ１３０４で探索経路スタック３１０に格納される配列番号は、ステップＳ１３０４の直前のステップがステップＳ１３０３の場合はステップＳ１３０２で得られた配列３０９’の配列番号であり、直前のステップ
がステップＳ１３１３の場合はステップＳ１３１３で得られた配列３０９’の配列番号であり、直前のステップがステップＳ１３１７の場合はステップＳ１３１７で得られた配列３０９’の配列番号である。
【０１６５】
次にステップＳ１３０５で、ノード退避配列４０１の未処理のノードのうちの先頭のノードの内容を取り出し、ステップＳ１３０６で、ステップＳ１３０５で取り出したノードの内容を、ステップＳ１３０４で探索経路スタック３１０に格納した配列番号が指す、配列３０９’の配列要素に書き込む。
【０１６６】
ステップＳ１３０４からステップＳ１３０６の処理により、１つのノードが復元される。正確には、リーフノードはステップＳ１３０４からステップＳ１３０６の処理により完全に復元され、ブランチノードは、後続のステップＳ１３１０からステップＳ１３１２により復元されるリンク先の代表ノード番号以外の情報（ノード種別及び弁別ビット位置）が復元される。
【０１６７】
次にステップＳ１３０７に進んで、ノード退避配列４０１からすべてのノードを取り出したか否かを判断する。すべてのノードを取り出したら復元処理は終了し、未処理のノードがノード退避配列４０１に残っていれば、ステップＳ１３０８に進む。
【０１６８】
ステップＳ１３０８では、ステップＳ１３０５で取り出したノードから、ノード種別を取り出し、ステップＳ１３０９でそのノード種別（ステップＳ１３０６で復元したノードの種別）がブランチノードか否かを判定する。ノード種別がブランチノードならステップＳ１３１０に進み、リーフノードならステップＳ１３１４に進む。
【０１６９】
ステップＳ１３１０ではステップＳ１３０１と同様に、配列３０９’から空きのノード対の代表ノード番号を得る。そしてステップＳ１３１１では探索経路スタック３１０からスタックポインタが指す配列番号を取り出す。なお、ステップＳ１３１１の処理はポップ動作ではなく、スタックポインタは変更されない。
【０１７０】
続いてステップＳ１３１２で、ステップＳ１３１１で取り出した配列番号の、配列３０９’の配列要素の代表ノード番号に、ステップＳ１３１０で得た代表ノード番号を書き込む。これにより、ステップＳ１３０６で一部が復元されたブランチノードが完全に復元された状態となる。
【０１７１】
そして、ステップＳ１３１３では、次に復元すべきノードに対応する、配列３０９’の配列番号を得る。つまり、ステップＳ１３１０で得た代表ノード番号に値０を加えて、ノード［０］の配列３０９’上の配列番号を得る。ステップＳ１３１３の実行後、処理はステップＳ１３０４に戻る。
【０１７２】
一方、ステップＳ１３０９でリーフノードと判定された場合は、ステップＳ１３１４で、探索経路スタック３１０からスタックポインタが指す配列３０９’の配列要素の配列番号を取り出し、スタックポインタを１つ減らす。
【０１７３】
続いて、ステップＳ１３１５で、ステップＳ１３１４で取り出した配列番号から、その配列番号のノードがノード対のどちらの配列要素に格納されているかのノード位置を得る。
【０１７４】
そして、ステップＳ１３１６で、ステップＳ１３１５で得たノード位置がノード［０］側であるか否かを判定する。ステップＳ１３１６でノード［１］側と判定された場合はステップＳ１３１４に戻り、スタックポインタの指す配列番号のノードがノード［０］とな
るまで、ステップＳ１３１４からステップＳ１３１６までの処理を繰り返す。
【０１７５】
ステップＳ１３１６においてノード［０］側と判定されると、ステップＳ１３１７に進み、ステップＳ１３１４で取り出した配列番号に１を加えて、そのノードと対をなすノード［１］の配列番号を得る。そしてステップＳ１３０４に進む。
【０１７６】
ステップＳ１３１４からステップＳ１３１６は、リーフノードを復元した後、次に復元すべきノードを決定するために探索経路スタック３１０を遡るステップである。
以上のようにして、ステップＳ１３０７でノード退避配列４０１から全てのノードを取り出したと判定されるまで、同様の処理が繰り返される。
【０１７７】
つまり、図１３の処理は、ノード退避配列４０１に含まれるノードを先頭から順番に１つずつ復元することの繰り返しである。そして、１つのノードの復元は、そのノードを復元すべき位置である復元先位置としての配列３０９’の配列番号を決定し、その配列番号を探索経路スタック３１０に格納し、ノード退避配列４０１から未処理の先頭にあるノードの内容を読み出し、読み出したノードの内容を配列番号の指す配列要素に書き込むことにより行われる。
【０１７８】
図１４と図１５は、図１１と図１２のノード退避配列４０１から、図２の元のカップルドノードツリーを、不図示の配列３０９’上に復元する例を用いて、図１３のフローチャートにより示した本実施形態に係る復元処理を説明する図である。以下では、図１４と図１５の双方を参照して、図２のカップルドノードツリーが図１３の復元処理により配列３０９’上に復元される流れを説明する。
【０１７９】
図１４には、処理の流れを表す矢印とともに復元後のカップルドノードツリーの構造を示し、ノード退避配列４０１の内容も示した。図１４のノード退避配列４０１は、左側に示したステップの番号を除いて、図１１に示したものと同一である。
【０１８０】
図１４に示した復元後のカップルドノードツリーは、図２と図１１に例示された元のカップルドノードツリーと同じ構造であり、各リーフノードが含むインデックスキーの値も図２及び図１１と同様である。しかし、元のカップルドノードツリーと復元後のカップルドノードツリーでは、ノードの配列番号の値が一般には異なる。
【０１８１】
そこで、図１４では、元のノード及び代表ノード番号を表す符号にアポストロフィをつけた符号を用いる。例えば、元のノード２１０ｂを復元したノードには「２１０ｂ’」なる符号を付した。また、元のノード２１０ｂの配列３０９上の配列番号２２０ａと、復元されたノード２１０ｂ’の配列３０９’上の配列番号２２０ａ’は、値が異なるかもしれないが、互いに対応するので、「２２０ａ」と「２２０ａ’」という対応する符号を用いた。なお、図１５の探索経路スタック３１０に格納されている配列３０９’の配列番号は、図１４に示すカップルドノードツリーと対応付けられている。
【０１８２】
図１５は、図１４の処理の各段階における探索経路スタック３１０の状態を示すとともに、ノード退避配列４０１のうちその段階で処理される部分を強調して示した図である。
復元処理は、図１４のステップＳ１４０１の矢印に示すように、図１３のステップＳ１３０１からステップＳ１３０３によりルートノード２１０ａ’を復元することから始まる。つまり、配列３０９’から空きのノード対の代表ノード番号２２０’が得られ、（２２０’＋０）＝２２０’なる配列番号が得られ、この配列番号が、ルートノード２１０ａ’の配列番号として登録される。ただし、この時点ではルートノード２１０ａ’の代表ノード番号の値は未定であり、ルートノード２１０ａ’の復元は不完全である。
【０１８３】
続いて、ステップＳ１３０４からステップＳ１３０９とステップＳ１３１０を経てステップＳ１３１３に至る一連の処理が、ステップＳ１３０９の判定がブランチノードである間、繰り返される。
【０１８４】
すなわち、ステップＳ１３０４で探索経路スタック３１０に配列番号２２０’がプッシュされ、ステップＳ１３０５でノード退避配列４０１の配列番号０のノードが取り出される。このノードは、図１１と図１２で説明したとおり、ルートノードである。ステップＳ１３０６では、配列３０９’の配列番号２２０’の配列要素に、ステップＳ１３０５で取り出したノードの内容が書き込まれる。これにより、ルートノード２１０ａ’は、ノード種別にはブランチノードを示す０が、弁別ビット位置には０が、代表ノード番号にはノード退避配列４０１から取得した２２０ａなる配列番号が、それぞれ格納された状態となる。
【０１８５】
続いて、ステップＳ１３０７からステップＳ１３０９が実行され、ルートノード２１０ａ’がブランチノードであることからステップＳ１３１０に進み、配列３０９’から空きのノード対の代表ノード番号２２０ａ’が取得される。そしてステップＳ１３１１で探索経路スタック３１０から配列番号２２０’が取得され、ステップＳ１３１２で、配列番号２２０’が指すルートノード２１０ａ’の代表ノード番号に、ステップＳ１３１０で取得した代表ノード番号２２０ａ’が書き込まれる。その結果、ルートノード２１０ａ’の復元が完了し、ルートノード２１０ａ’は図１４に示す状態となる。
【０１８６】
次のステップＳ１３１３では、（２２０ａ’＋０）＝２２０ａ’なる配列番号が取得され、これが次のステップＳ１３０４で探索経路スタック３１０にプッシュされる。そして、ステップＳ１３０５でノード退避配列４０１の配列番号１のノードが取り出され、ステップＳ１３０６で、配列３０９’の配列番号２２０ａ’の配列要素に、ノード種別０、弁別ビット位置１、代表ノード番号２２０ｂなる取得したノードの内容が書き込まれる。
【０１８７】
上記と同様にしてステップＳ１３０７からステップＳ１３１２が実行されてノード２１０ｂ’が復元された後、ステップＳ１３１３からステップＳ１３０４に戻って配列番号２２０ｂ’が探索経路スタック３１０にプッシュされる。そしてステップＳ１３０５でノード退避配列４０１の配列番号２のノードが取り出される。ステップＳ１３０６で、配列３０９’の配列番号２２０ｂ’の配列要素には、ノード種別としてリーフノードを示す１が、インデックスキーとして“０００１１１”が、それぞれ格納され、ノード２１０ｃ’が図１４のとおり復元される。続いて、ステップＳ１３０７からステップＳ１３０９が実行され、ノード２１０ｃ’がリーフノードと判定される。
【０１８８】
図１５（ａ）はこの段階、すなわち図１４のステップＳ１４０１を実行した段階の探索経路スタック３１０の状態を示す。また、この段階までにノード退避配列４０１のうち配列番号０から２に相当する３つのノードが復元されたので、これら３つのノードに対応するノード退避配列４０１の配列要素が、図１５（ａ）では太線で囲われており、配列番号０から２の配列要素が復元済みであるため、後続の図１５（ｂ）〜（ｈ）では省略されている。
【０１８９】
続いて、Ｓ１３１４からステップＳ１３１７が実行される。それにより、ステップＳ１３１４で探索経路スタック３１０から配列番号２２０ｂ’がポップされ、配列番号２２０ｂ’のノード２１０ｃ’がノード［０］なので、ステップＳ１３１６からステップＳ１３１７に進み、配列番号（２２０ｂ’＋１）が得られる。
【０１９０】
そして、図１４のステップＳ１４０２に示すように、ステップＳ１３０４からステップＳ１３０９とステップＳ１３１０を経てステップＳ１３１３に至る一連の処理が、ステッ
プＳ１３０９の判定がブランチノードである間、繰り返される。この過程では、下記のようにしてノード２１１ｃ’とノード２１０ｄ’とノード２１０ｅ’が復元される。
【０１９１】
ステップＳ１４０２を構成する最初のステップであるステップＳ１３０４では、探索経路スタック３１０に配列番号（２２０ｂ’＋１）がプッシュされる。ステップＳ１３０５でノード退避配列４０１の配列番号３のノードが取り出され、上記と同様にしてステップＳ１３０６からステップＳ１３１２によりノード２１１ｃ’が復元される。そしてステップＳ１３１３からステップＳ１３０４に戻って配列番号２２１ｃ’が探索経路スタック３１０にプッシュされる。
【０１９２】
続いて、ステップＳ１３０５でノード退避配列４０１の配列番号４のノードが取り出され、ステップＳ１３０６からステップＳ１３１２により、上記と同様にしてノード２１０ｄ’が復元される。そしてステップＳ１３１３からステップＳ１３０４に戻って配列番号２２０ｄ’が探索経路スタック３１０にプッシュされる。
【０１９３】
そして、ステップＳ１３０５でノード退避配列４０１の配列番号５のノードが取り出され、ステップＳ１３０６でこのノードの内容が配列３０９’の配列番号２２０ｄ’の配列要素に書き込まれて、ノード２１０ｅ’が復元される。続いて、ステップＳ１３０７からステップＳ１３０９が実行され、ノード２１０ｅ’がリーフノードと判定される。
【０１９４】
図１５（ｂ）はこの段階、すなわちステップＳ１４０２を実行した段階の探索経路スタック３１０を表す。また、図１５（ａ）の状態から図１５（ｂ）の状態になる過程でノード退避配列４０１のうち配列番号３から５に相当する３つのノードが復元されたので、これらを太線で囲って示した。
【０１９５】
続いて、ステップＳ１３１４からステップＳ１３１７が実行される。それにより、ステップＳ１３１４で探索経路スタック３１０から配列番号２２０ｄ’がポップされ、配列番号２２０ｄ’のノード２１０ｅ’はノード［０］なので、ステップＳ１３１６からステップＳ１３１７に進み、配列番号（２２０ｄ’＋１）が得られる。
【０１９６】
次に、図１４のステップＳ１４０３に示すように、ステップＳ１３０４からステップＳ１３０９が実行される。つまり、ステップＳ１３０４で探索経路スタック３１０に配列番号（２２０ｄ’＋１）がプッシュされ、ステップＳ１３０５でノード退避配列４０１の配列番号６のノードが取り出され、ステップＳ１３０６でノード２１１ｅ’が復元される。その後、ステップＳ１３０９でノード２１１ｅ’がリーフノードだと判定される。
【０１９７】
図１５（ｃ）はこの段階、つまりステップＳ１４０３が実行された段階の探索経路スタック３１０の状態を示す。また、図１５（ｂ）の状態から図１５（ｃ）の状態になる過程で、ノード退避配列４０１のうち配列番号６に相当するノードが復元された。
【０１９８】
続いて、ステップＳ１３１４からステップＳ１３１７が次のように実行される。まず、ステップＳ１３１４で探索経路スタック３１０から配列番号（２２０ｄ’＋１）がポップされる。配列番号（２２０ｄ’＋１）のノード２１１ｅ’はノード［１］なので、ステップＳ１３１６からステップＳ１３１４に戻り、探索経路スタック３１０から配列番号２２１ｃ’がポップされる。配列番号２２１ｃ’のノード２１０ｄ’はノード［０］なので、ステップＳ１３１６からステップＳ１３１７に進み、配列番号（２２１ｃ’＋１）が得られる。
【０１９９】
次に、図１４のステップＳ１４０４に示すように、ステップＳ１３０４からステップＳ１３０９が実行される。それにより、ステップＳ１３０４で探索経路スタック３１０に配
列番号（２２１ｃ’＋１）がプッシュされ、ステップＳ１３０５でノード退避配列４０１の配列番号７のノードが取り出され、ステップＳ１３０６でノード２１１ｄ’が復元される。その後、ステップＳ１３０９でノード２１１ｄ’がリーフノードだと判定される。
【０２００】
図１５（ｄ）はこの段階、つまりステップＳ１４０４が実行された段階の探索経路スタック３１０の状態を示す。また、図１５（ｃ）の状態から図１５（ｄ）の状態になる過程で、ノード退避配列４０１のうち配列番号７に相当するノードが復元された。
【０２０１】
続いて、ステップＳ１３１４からステップＳ１３１７が実行される。すなわち、ノード［０］であるノード２１０ｂ’の配列番号２２０ａ’が得られるまで、ステップＳ１３１４からステップＳ１３１６が繰り返されてから、ステップＳ１３１７が実行される。この過程で、探索経路スタック３１０から、配列番号（２２１ｃ’＋１）と（２２０ｂ’＋１）と２２０ａ’が順次ポップされる。その後ステップＳ１３１７で配列番号（２２０ａ’＋１）が得られる。
【０２０２】
次に、図１４のステップＳ１４０５に示すように、ステップＳ１３０４からステップＳ１３０９とステップＳ１３１０を経てステップＳ１３１３に至る一連の処理が、ステップＳ１３０９の判定がブランチノードである間、繰り返される。この過程では、下記のようにしてノード２１１ｂ’とノード２１０f’とノード２１０ｇ’が復元される。
【０２０３】
ステップＳ１４０５を構成する最初のステップであるステップＳ１３０４では、探索経路スタック３１０に配列番号（２２０ａ’＋１）がプッシュされる。ステップＳ１３０５でノード退避配列４０１の配列番号８のノードが取り出され、その内容がステップＳ１３０６で配列３０９’の配列番号（２２０ａ’＋１）の配列要素に書き込まれる。
【０２０４】
そしてステップＳ１３０７からステップＳ１３０９が実行され、書き込まれたのがブランチノードの内容であることからステップＳ１３１０に進み、配列３０９’から空きのノード対の代表ノード番号２２１ｂ’が取得される。そしてステップＳ１３１１で探索経路スタック３１０から配列番号（２２０ａ’＋１）が取得され、ステップＳ１３１２で、配列番号（２２０ａ’＋１）のノード２１１ｂ’の代表ノード番号に、ステップＳ１３１０で取得した代表ノード番号２２１ｂ’が書き込まれる。その結果、ノード２１１ｂ’の復元が完了し、ノード２１１ｂ’は図１４に示す状態となる。
【０２０５】
次のステップＳ１３１３では、（２２１ｂ’＋０）＝２２１ｂ’なる配列番号が取得され、これがステップＳ１３０４で探索経路スタック３１０にプッシュされる。そして、ステップＳ１３０５でノード退避配列４０１の配列番号９のノードが取り出され、その内容がステップＳ１３０６で配列３０９’の配列番号２２１ｂ’の配列要素に書き込まれる。
【０２０６】
そしてステップＳ１３０７からステップＳ１３０９が実行され、書き込まれたのがブランチノードの内容であることからステップＳ１３１０に進み、配列３０９’から空きのノード対の代表ノード番号２２０ｆ’が取得される。そしてステップＳ１３１１で探索経路スタック３１０から配列番号２２１ｂ’が取得され、ステップＳ１３１２で、配列番号２２１ｂ’のノード２１０ｆ’の代表ノード番号に、ステップＳ１３１０で取得した代表ノード番号２２０ｆ’が書き込まれる。その結果、ノード２１０ｆ’の復元が完了し、ノード２１０ｆ’は図１４に示す状態となる。
【０２０７】
次のステップＳ１３１３では、（２２０ｆ’＋０）＝２２０ｆ’なる配列番号が取得され、これがステップＳ１３０４で探索経路スタック３１０にプッシュされる。そして、ステップＳ１３０５でノード退避配列４０１の配列番号１０のノードが取り出され、その内容がステップＳ１３０６で配列３０９’の配列番号２２０ｆ’の配列要素に書き込まれて
、ノード２１０ｇ’が復元される。その後、ステップＳ１３０７からステップＳ１３０９が実行され、ノード２１０ｇ’がリーフノードだと判定される。
【０２０８】
図１５（ｅ）はこの段階、すなわちステップＳ１４０５が実行された段階の探索経路スタック３１０を示す。また、図１５（ｄ）の状態から図１５（ｅ）の状態になる過程でノード退避配列４０１のうち配列番号８から１０に相当する３つのノードが復元された。
【０２０９】
続いて、テップＳ１３１４からステップＳ１３１７が実行される。すなわち、ステップＳ１３１４で探索経路スタック３１０から配列番号２２０ｆ’がポップされ、配列番号２２０ｆ’のノード２１０ｇ’がノード［０］なので、ステップＳ１３１６からステップＳ１３１７に進み、配列番号（２２０ｆ’＋１）が得られる。
【０２１０】
次に、図１４のステップＳ１４０６に示すように、ステップＳ１３０４からステップＳ１３０９が実行される。それにより、ステップＳ１３０４で探索経路スタック３１０に配列番号（２２０ｆ’＋１）がプッシュされ、ステップＳ１３０５でノード退避配列４０１の配列番号１１のノードが取り出され、ステップＳ１３０６でノード２１１ｇ’が復元される。その後、ステップＳ１３０９でノード２１１ｇ’がリーフノードだと判定される。
【０２１１】
図１５（ｆ）はこの段階、つまりステップＳ１４０６が実行された段階の探索経路スタック３１０の状態を示す。また、図１５（ｅ）の状態から図１５（ｆ）の状態になる過程で、ノード退避配列４０１のうち配列番号１１に相当するノードが復元された。
【０２１２】
続いて、ステップＳ１３１４からステップＳ１３１７が次のように実行される。まず、ステップＳ１３１４で探索経路スタック３１０から配列番号（２２０ｆ’＋１）がポップされる。配列番号（２２０ｆ’＋１）のノード２１１ｇ’はノード［１］なので、ステップＳ１３１６からステップＳ１３１４に戻り、探索経路スタック３１０から配列番号２２１ｂ’がポップされる。配列番号２２１ｂ’のノード２１０ｆ’はノード［０］なので、ステップＳ１３１６からステップＳ１３１７に進み、配列番号（２２１ｂ’＋１）が得られる。
【０２１３】
次に、図１４のステップＳ１４０７に示すように、ステップＳ１３０４からステップＳ１３０９とステップＳ１３１０を経てステップＳ１３１３に至る一連の処理が、ステップＳ１３０９の判定がブランチノードである間、繰り返される。この過程では、下記のようにしてノード２１１ｆ’とノード２１０h’が復元される。
【０２１４】
ステップＳ１４０７を構成する最初のステップであるステップＳ１３０４では、探索経路スタック３１０に配列番号（２２１ｂ’＋１）がプッシュされる。ステップＳ１３０５でノード退避配列４０１の配列番号１２のノードが取り出され、その内容がステップＳ１３０６で配列３０９’の配列番号（２２１ｂ’＋１）の配列要素に書き込まれる。
【０２１５】
そしてステップＳ１３０７からステップＳ１３０９が実行され、書き込まれたのがブランチノードの内容であることからステップＳ１３１０に進み、配列３０９’から空きのノード対の代表ノード番号２２１ｆ’が取得される。そしてステップＳ１３１１で探索経路スタック３１０から配列番号（２２１ｂ’＋１）が取得され、ステップＳ１３１２で、配列番号（２２１ｂ’＋１）のノード２１１ｆ’の代表ノード番号に、ステップＳ１３１０で取得した代表ノード番号２２１ｆ’が書き込まれる。その結果ノード２１１ｆ’の復元が完了し、ノード２１１ｆ’は図１４に示す状態となる。
【０２１６】
次のステップＳ１３１３では、（２２１ｆ’＋０）＝２２１ｆ’なる配列番号が取得され、これがステップＳ１３０４で探索経路スタック３１０にプッシュされる。ステップＳ
１３０５でノード退避配列４０１の配列番号１３のノードが取り出され、ステップＳ１３０６によりノード２１０ｈ’が復元される。その後、ステップＳ１３０９でノード２１０ｈ’がリーフノードだと判定される。
【０２１７】
図１５（ｇ）はこの段階、すなわちステップＳ１４０７が実行された段階の探索経路スタック３１０を示す。また、図１５（ｆ）の状態から図１５（ｇ）の状態になる過程でノード退避配列４０１のうち配列番号１２と１３に相当する２つのノードが復元された。
【０２１８】
続いて、ステップＳ１３１４からステップＳ１３１７が実行される。すなわち、ステップＳ１３１４で探索経路スタック３１０から配列番号２２１ｆ’がポップされ、配列番号２２１ｆ’のノード２１０ｈ’はノード［０］なので、ステップＳ１３１６からステップＳ１３１７に進み、配列番号（２２１ｆ’＋１）が得られる。
【０２１９】
次に、図１４のステップＳ１４０８に示すように、ステップＳ１３０４からステップＳ１３０７が実行されて復元処理が完了する。すなわち、ステップＳ１３０４で探索経路スタック３１０に配列番号（２２１ｆ’＋１）がプッシュされ、ステップＳ１３０５でノード退避配列４０１の配列番号１４のノードが取り出され、ステップＳ１３０６によりノード２１１ｈ’が復元される。そして、ステップＳ１３０７でノード退避配列４０１からすべてのノードを取り出したと判定され、復元処理が終了する。
【０２２０】
図１５（ｈ）はこの段階、すなわちステップＳ１４０８が実行された段階の探索経路スタック３１０を示す。また、図１５（ｇ）の状態から図１５（ｈ）の状態になる過程でノード退避配列４０１のうち配列番号１４に相当するノードが復元された。
【０２２１】
図１５には（ａ）〜（ｈ）の８つの段階が示されているが、上記のとおり、これら８つの段階はいずれも、０個以上のブランチノードを復元してから１個のリーフノードを復元する一連のステップに対応している。復元処理がこのような一連のステップの繰り返しであることは、ノードが深さ優先探索順で退避されたことの帰結である。
【０２２２】
深さ優先探索順にノードが退避されたノード退避配列４０１からは、退避された順序のとおりにノードを復元するだけでよい。つまり、ノード退避配列４０１から配列要素を順次読み出し、ブランチノードが続く間は順次、子ノードを、復元すべき子ノードと対になるノードの記憶領域も確保しながら復元し、リーフノードが読み出されたら、ツリー構造をルートノードに向かって遡って、復元後のノードを格納するための記憶領域が確保済みだがまだ復元されていないノードを見つけ、その見つけたノードを次に復元すべきノードとして決定する、という処理を繰り返すだけで、容易にカップルドノードツリーを復元することができる。上記のとおり、復元処理では探索経路スタック３１０を利用するが、ノードに含まれるインデックスキーや弁別ビット位置に基づく判断などは必要ない。
【０２２３】
このように単純かつ効率的にカップルドノードツリーを復元することができる点は、本発明による復元方法の利点である。上記のとおり、カップルドノードツリーは、インデックスキーの集合により一意に構造が規定される。よって、インデックスキーの集合さえ退避されていればカップルドノードツリーを復元すること自体は可能である。しかしながら、インデックスキーの集合のみからカップルドノードツリーを復元する方法は、弁別ビット位置を調べるなどの処理が必要である。一方、本発明による復元方法は、インデックスキーや弁別ビット位置に基づく判断などは必要なく、その分処理時間が短くて済む。
【０２２４】
また、本発明による復元方法は、退避情報に退避された順にノードを復元するだけでよいので、退避情報がネットワークを介して送信され、送信先のコンピュータがカップルドノードツリーを受信して復元する場合に時間短縮の効果がある。なぜなら、受信が完了す
る前に、受信した部分から順次ノードを復元することによって、受信と復元を同時に行うことができるためである。
【０２２５】
以上、本発明を実施するための最良の形態について詳細に説明したが、本発明の実施の形態はそれに限ることなく種々の変形が可能である。
上記で説明したフローチャートは、処理の一例であり、処理順を入れ替えたり並行に処理したりすることが可能なステップが存在することは自明である。例えば、図１３のステップＳ１３０４は、ステップＳ１３０５の直後あるいはステップＳ１３０６の直後に移動させてもよく、ステップＳ１３０５及びステップＳ１３０６からなる処理と並行して実行してもよい。
【０２２６】
上記の例では、ビット値０に対応してリンクされるノード［０］を代表ノードとし、ビット値１に対応してリンクされるノード［１］を代表ノードと対になる非代表ノードとしていた。しかし、ノード［１］を代表ノードとし、ノード［０］を非代表ノードとしてもよい。
【０２２７】
また、例えば、元のカップルドノードツリーにおいてノード［０］が代表ノードでありノード［１］が非代表ノードである場合に、復元したカップルドノードツリーにおいては、ノード［０］が代表ノードでありノード［１］が非代表ノードであってもよく、ノード［０］が非代表ノードでありノード［１］が代表ノードであってもよい。
【０２２８】
なお、ルートノードを代表ノードの位置に配置するか非代表ノードの位置に配置するかが任意であることは、図２などに関する説明から明らかであろう。
また、上記の例では、ビット値０を優先させた深さ優先探索順にノードを退避し、復元しているが、ビット値１を優先させた深さ優先探索順にノードを退避し、復元することも当然可能である。
【０２２９】
ビット値０を優先させた深さ優先探索順は、カップルドノードツリーに格納されたインデックスキーを昇順に取り出す図７の処理順と同じである。よって、上記実施形態における退避処理は、図７と類似した図１０Ａのフローチャートにより示され、図１０Ａから呼び出される図１０Ｂの処理は、図７から呼び出される図５の最小値を求める処理と類似している。
【０２３０】
同様に、ビット値１を優先させた深さ優先探索順は、カップルドノードツリーに格納されたインデックスキーを降順に取り出す図８の処理順と同じである。よって、この場合は、図８と図６に示したのと同様の処理順でノードを巡回するように、図１０Ａと図１０Ｂの処理をそれぞれ変更すればよい。また、それにあわせて図１３の処理を変更すればよい。
【０２３１】
上記の実施形態と同様に、ノード［０］を代表ノードとするという仮定のもとで説明すると、具体的には次のような変更が必要である。まず、図１０ＡのステップＳ１００６を、ノード［１］のときにステップＳ１００７に進むようにする。ステップＳ１００７は、配列番号から１を減じてノード［０］の配列番号を得るように変更し、ステップＳ１００８は、巡回開始ノードの配列番号にノード［０］の配列番号を設定するように変更する。そして、図１０ＢのステップＳ１０１８は、値０のかわりに値１を加えるように変更する。
【０２３２】
そのようにビット値１を優先させた深さ優先探索順で退避されたカップルドノードツリーを復元するには、図１３を次のように変更すればよい。まず、ステップＳ１３１３を、代表ノード番号に値１を加えてノード［１］の配列番号を得るように変更し、ステップＳ
１３１６を、ノード［１］のときにステップＳ１３１７に進むように変更し、ステップＳ１３１７を、配列番号から１を減じてノード［０］の配列番号を得るように変更する。
【０２３３】
換言すれば、上記の変形例は次のようにまとめられる。退避処理において代表ノード側を優先してたどると、ノード［０］が代表ノードのときは図１０Ａと同様にインデックスキーの昇順に、ノード［１］が代表ノードのときはインデックスキーの降順に、カップルドノードツリーを退避することになる。一方、退避処理において非代表ノード側を優先してたどると、ノード［０］が代表ノードのときはインデックスキーの降順に、ノード［１］が代表ノードのときはインデックスキーの昇順に、カップルドノードツリーを退避することになる。復元処理は、ノード［０］とノード［１］のいずれが代表ノードであるか、退避はインデックスキーの昇順と降順のいずれの順序でなされたか、ということに基づいて、実施形態に応じて適宜変形される。
【０２３４】
図１０Ａから図１５の例では、退避されたノードの内容の退避情報における並び順を表すのに便利なので、説明の便宜上、退避情報がノード退避配列４０１に格納される例を用いて説明した。しかし退避情報は、ノードが退避された順序にノードの情報が並んだ情報であればよく、ノード退避配列４０１のような配列でなくともよい。
【０２３５】
退避情報は、実施形態によって、外部記憶装置３０６上にファイルとして格納されてもよく、主記憶装置３０５上にノード退避配列４０１のような配列あるいはその他の形式で格納されてもよく、通信装置３０７とネットワークを介して他のコンピュータに送信されてもよい。上記の実施形態では説明の便宜上、ノード退避配列４０１にノードを格納する、あるいはノード退避配列４０１にノードを退避する、などと表現したが、ネットワークを介してノードの内容を送信することによってノードの内容を退避するといった形態を除外する意図ではない。
【０２３６】
また、ブランチノードに含まれる代表ノード番号は、上記の退避処理では退避されているが、退避しなくてもよい。その理由は、復元処理で、元のカップルドノードツリーで使われていた配列３０９の配列番号とは無関係に、復元後のカップルドノードツリーを格納すべき配列３０９’上の空きのノード対の代表ノードの配列番号が取得されるためである。つまり、退避される前の元のブランチノードに含まれる代表ノード番号は、復元後にまったく使われないので、退避する必要がない。
【０２３７】
ブランチノードの代表ノード番号を退避しない場合は、その分、退避情報のデータ量が少なくなる。つまり、退避情報をファイルとして格納する場合はファイルの大きさが小さくて済み、ネットワークを介して退避情報を送信する場合はネットワークのトラフィックが少なくて済む。また、図１３の復元処理には、元の配列３０９の配列番号と無関係な配列３０９’の配列番号を使うので、ある環境で退避したカップルドノードツリーを別の環境で復元することが容易だという利点もある。
【０２３８】
なお、図１０Ａには既存のカップルドノードツリーの全体を退避する処理を示したが、部分木のみを退避することも可能である。そのためには、図１０ＡのステップＳ１００１とステップＳ１００３におけるルートノードを、カップルドノードツリー全体のルートノードではなく、退避すべき部分木のルートノードとすればよい。それにより得られたノード退避配列に対して図１３の復元処理を実行すれば、退避した部分木が復元される。
【０２３９】
また、図１３には、ノード退避配列４０１に退避された全ノードからなるカップルドノードツリーを復元する処理を示したが、そのうちの部分木のみを復元することも、図１３の処理の一部を変更することにより可能である。
【０２４０】
上記のとおり、ノード退避配列４０１では、任意の部分木について、その部分木を構成する全ノードが連続する配列番号の配列要素に退避されている。したがって、復元したい部分木のルートノードがノード退避配列４０１のどの位置にあるかが予め指定されれば、その位置を読み取り開始位置としてノード退避配列４０１の内容を読み取ることで、退避されたカップルドノードツリーの部分木のみを復元することも可能である。
【０２４１】
ただし、そのためには図１３のステップＳ１３０３とステップＳ１３０４の間にステップＳ１３１８を追加し、ステップＳ１３１５とステップＳ１３１６の間にステップＳ１３１９を追加する。追加されたステップＳ１３１８では、復元したい部分木のルートノードがノード退避配列４０１のどの位置にあるかを指定して、その位置より前のノード退避配列４０１の内容をスキップする。また、追加されたステップＳ１３１９では、スタックポインタがルートノードの配列番号を指しているか否かを判定する。そして、スタックポインタがルートノードの配列番号を指していれば復元処理を終了し、そうでなければステップＳ１３１６に進む。なお、ステップＳ１３０３及び追加されるステップＳ１３１９におけるルートノードは、退避された元のカップルドノードツリー全体のルートノードではなく、復元対象の部分木のルートノードを意味する。
【０２４２】
このように処理の一部を変更することにより、例えば、図１４のノード退避配列４０１の配列番号３のノードを復元すべき部分木のルートノードとして指定し、ノード退避配列４０１のうち配列番号３から７の部分のみを利用して、ノード２１１ｃ’をルートノードとする部分木をノード退避配列４０１から復元することが可能である。
【０２４３】
以上のように、本発明によれば、部分木のみを退避したり、ノード退避配列から必要な部分木のみを復元したりすることも、簡単に効率よく行うことが可能である。よって、本発明によれば、カップルドノードツリーの大きさが大きくなったとしても、必要な部分木のみを処理することができ、カップルドノードツリーの取り扱いを容易なものとすることができる。
【０２４４】
なお、本発明の退避方法または復元方法を実行する装置が、カップルドノードツリーを格納する記憶手段と、図１０Ａ〜図１０Ｂまたは図１３に示した処理をコンピュータに実行させるプログラムによりコンピュータ上に構築可能なことは明らかである。したがって、上記プログラム、及びプログラムを記憶したコンピュータ読み取り可能な記憶媒体は、本発明の実施の形態に含まれる。
【０２４５】
以上詳細に説明したとおり、本発明によるカップルドノードツリーの退避方法は、退避の対象であるカップルドノードツリーの部分木を構成するノードを、インデックスキーの昇順または降順に対応する深さ優先探索順に退避する方法である。昇順あるいは降順のいずれかが選択されれば、深さ優先探索順は、カップルドノードツリーのツリー構造と一対一に対応する順序である。また、カップルドノードツリーは、各ノードが記憶領域上に具体的にどのように配置されているかは任意である一方、ツリー構造はインデックスキーの集合によって一意に規定されるという特徴がある。
【０２４６】
したがって、本発明によれば、記憶領域上のノードの配置のされ方に依存しない標準的な順序、すなわち、インデックスキーの集合から一意に規定されたツリー構造と一対一に対応する順序で、ノード情報（退避情報）が退避される。つまり、ノード情報（退避情報）は、退避されたリーフノードによってインデックスキーの集合を表すとともに、この順序性でカップルドノードツリーのツリー構造を表している。この順序性があるため、復元処理においては、復元すべきカップルドノードツリーのツリー構造を決定するための余計な処理が不要であり、効率的な復元が可能となっている。以上のことから、本発明による退避の順序は、ノード情報の交換形式として好適な順序であると言える。
【図面の簡単な説明】
【０２４７】
【図１】配列に格納されたカップルドノードツリーの構成例を説明する図である。
【図２】カップルドノードツリーのツリー構造を概念的に示す図である。
【図３】本発明を実施するためのハードウェア構成例を説明する図である。
【図４】本発明の一実施形態における検索処理を示すフローチャートである。
【図５】カップルドノードツリーに格納されたインデックスキーの最小値を求める処理を示したフローチャートである。
【図６】カップルドノードツリーに格納されたインデックスキーの最大値を求める処理を示したフローチャートである。
【図７】カップルドノードツリーに格納されたインデックスキーを昇順に取り出す処理を示したフローチャートである。
【図８】カップルドノードツリーに格納されたインデックスキーを降順に取り出す処理を示したフローチャートである。
【図９Ａ】挿入処理の前段である検索処理の処理フローを示す図である。
【図９Ｂ】挿入するノード対のための配列要素を準備する処理を説明する処理フロー図である。
【図９Ｃ】ノード対を挿入する位置を求め、ノード対の各ノードの内容を書き込んで挿入処理を完成させる処理フローを示す図である。
【図９Ｄ】ルートノードの挿入処理を含むインデックスキーを追加する場合のノード挿入処理全体を説明する処理フロー図である。
【図１０Ａ】本発明の一実施形態における退避処理を示すフローチャートである。
【図１０Ｂ】本発明の一実施形態におけるノードを退避する処理を示すフローチャートである。
【図１１】退避処理をカップルドノードツリーにより説明する図である。
【図１２】退避処理によって変化する探索経路スタックとノード退避配列の状態を説明する図である。
【図１３】本発明の一実施形態における復元処理を示すフローチャートである。
【図１４】復元処理をカップルドノードツリーにより説明する図である。
【図１５】復元処理によって変化する探索経路スタックとノード退避配列の状態を説明する図である。
【図１６】従来の検索で用いられるパトリシアツリーの一例を示す図である。
【符号の説明】
【０２４８】
１０、２０、３０  配列番号
１００  配列
１０１  ノード
１０２、１１４、１１７、１２４、１２６、２６０ａ〜２６０ｈ、２６１ｂ〜２６１ｈ
ノード種別
１０３、１１５、２３０ａ〜２３０ｆ、２３１ｂ〜２３１ｆ  弁別ビット位置
１０４、１１６、２２０、２２０ａ〜２２０ｆ、２２１ｂ〜２２１ｆ  代表ノード番号
１１１、１２１、２０１ａ〜２０１ｈ  ノード対
１１２、１２２、２１０ａ〜２１０ｈ  ノード［０］、代表ノード
１１３、１２３、２１１ｂ〜２１１ｈ  ノード［１］、代表ノードと対をなす非代表ノード
１１８、２５０ｃ〜２５０ｈ、２５１ｄ〜２５１ｈ  インデックスキー
３０１  データ処理装置
３０２  中央処理装置
３０３  キャッシュメモリ
３０４  バス
３０５  主記憶装置
３０６  外部記憶装置
３０７  通信装置
３０８  データ格納装置
３０９  配列
３１０  探索経路スタック
４０１  ノード退避配列
１７３０ａ〜１７３０ｈ  検査ビット位置
１７４０ａ〜１７４０ｆ  左リンク、左ポインタ
１７４１ａ〜１７４１ｆ  右リンク、右ポインタ
１７５０ａ〜１７５０ｈ  ノード
【図１】
2008269197.tif 000003
【図２】
2008269197.tif 000004
【図３】
2008269197.tif 000005
【図４】
2008269197.tif 000006
【図５】
2008269197.tif 000007
【図６】
2008269197.tif 000008
【図７】
2008269197.tif 000009
【図８】
2008269197.tif 000010
【図９Ａ】
2008269197.tif 000011
【図９Ｂ】
2008269197.tif 000012
【図９Ｃ】
2008269197.tif 000013
【図９Ｄ】
2008269197.tif 000014
【図１０Ａ】
2008269197.tif 000015
【図１０Ｂ】
2008269197.tif 000016
【図１１】
2008269197.tif 000017
【図１２】
2008269197.tif 000018
【図１３】
2008269197.tif 000019
【図１４】
2008269197.tif 000020
【図１５】
2008269197.tif 000021
【図１６】
2008269197.tif 000022