最初に、本出願人により先の上記出願において提案された、本発明の前提となるカップルドノードツリーについて、カップルドノードツリーを配列に格納する例を説明する。ブランチノードが保持するリンク先の位置を示すデータとして、記憶装置のアドレス情報とすることもできるが、ブランチノードあるいはリーフノードのうち占有する領域の記憶容量の大きい方を格納可能な配列要素からなる配列を用いることにより、ノードの位置を配列番号で表すことができ、位置情報の情報量を削減することができる。
図2Aは、配列に格納されたカップルドノードツリーの構成例を説明する図である。
図2Aを参照すると、ノード101が配列100の配列番号10の配列要素に配置されている。ノード101はノード種別102、弁別ビット位置103及び代表ノード番号104で構成されている。ノード種別102は0であり、ノード101がブランチノードであることを示している。弁別ビット位置103には1が格納されている。代表ノード番号104にはリンク先のノード対の代表ノードの配列番号20が格納されている。なお、以下では表記の簡略化のため、代表ノード番号に格納された配列番号を代表ノード番号ということもある。また、代表ノード番号に格納された配列番号をそのノードに付した符号あるいはノード対に付した符号で表すこともある。
配列番号20の配列要素には、ノード対111の代表ノードであるノード[0]112が格納されている。そして隣接する次の配列要素(配列番号20+1)に代表ノードと対になるノード[1]113が格納されている。ノード[0]112のノード種別114には0が、弁別ビット位置115には3が、代表ノード番号116には30が格納されている。またノード[1]113のノード種別117には1が格納されており、ノード[1]113がリーフノードであることを示している。インデックスキー118には、“0001”が格納されている。パトリシアツリーについて先に述べたと同様に、リーフノードにインデックスキーと対応するレコードにアクセスする情報が含まれることは当然であるが、表記は省略している。
なお、代表ノードをノード[0]で表し、それと対になるノードをノード[1]で表すことがある。また、ある配列番号の配列要素に格納されたノードを、その配列番号のノードということがあり、ノードの格納された配列要素の配列番号を、ノードの配列番号ということもある。
ノード[0]112及びノード[1]113の前に付された符号0,1は、そのノードがノード対のどちらの配列要素に格納されているかを示すノード位置である。例えばノード[0]については偶数番号の配列の配列要素に格納する等により、配列番号からノード位置を求めることができる。すなわち、その場合は、配列番号が偶数であればその配列番号のノードのノード位置は0であり、配列番号が奇数であればその配列番号のノードのノード位置は1である。
配列番号30及び31の配列要素に格納されたノード122とノード123からなるノード対121の内容は省略されている。
ノード[0]112、ノード[1]113、ノード122、及びノード123の格納された配列要素にそれぞれ付されたノード位置0あるいは1は、検索キーで検索を行う場合にノード対のどちらのノードにリンクするかを示すものと考えることができる。前段のブランチノードの弁別ビット位置にある検索キーのビット値である0か1をノード位置として、代表ノード番号で指定されるノード対のうちの該ノード位置のノードにリンクする。
したがって、前段のブランチノードの代表ノード番号に、検索キーの弁別ビット位置のビット値を加えることにより、リンク先のノードが格納された配列要素の配列番号を求めることができる。
なお、上記の例では代表ノード番号をノード対の配置された配列番号のうち小さい方を採用しているが、大きいほうを採用することも可能であることは明らかである。
図2Bは、カップルドノードツリーのツリー構造を概念的に示す図である。図示の6ビットのインデックスキーは、図1に例示されたパトリシアツリーのものと同じである。
符号210aで示すのがルートノードである。図示の例では、ルートノード210aは配列番号220に配置されたノード対201aの代表ノードとしている。
ツリー構造としては、ルートノード210aの下にノード対201bが、その下層にノード対201cとノード対201fが配置され、ノード対201fの下層にはノード対201hとノード対201gが配置されている。ノード対201cの下にはノード対201dが、さらにその下にはノード対201eが配置されている。
各ノードの前に付された0あるいは1の符号は、図2Aにおいて説明した配列要素の前に付された符号と同じであり、ノード位置を示す。検索キーの弁別ビット位置のビット値に応じてツリーをたどり、検索対象のリーフノードを見つけることになる。
図示された例では、ルートノード210aのノード種別260aは0でブランチノードであることを示し、弁別ビット位置230aは0を示している。代表ノード番号は220aであり、それはノード対201bの代表ノード210bの格納された配列要素の配列番号である。
ノード対201bはノード210bと211bで構成され、それらのノード種別260b、261bはともに0であり、ブランチノードであることを示している。ノード210bの弁別ビット位置230bには1が格納され、リンク先の代表ノード番号にはノード対201cの代表ノード210cの格納された配列要素の配列番号220bが格納されている。
ノード210cのノード種別260cには1が格納されているので、このノードはリーフノードであり、したがって、インデックスキーを含んでいる。インデックスキー250cには“000111”が格納されている。一方ノード211cのノード種別261cは0、弁別ビット位置231cは2であり、代表ノード番号にはノード対201dの代表ノード210dの格納された配列要素の配列番号221cが格納されている。
ノード210dのノード種別260dは0、弁別ビット位置230dは5であり、代表ノード番号にはノード対201eの代表ノード210eの格納された配列要素の配列番号220dが格納されている。ノード210dと対になるノード211dのノード種別261dは1であり、インデックスキー251dには“011010”が格納されている。
ノード対201eのノード210e、211eのノード種別260e、261eはともに1であり双方ともリーフノードであることを示し、それぞれのインデックスキー250e、251eにはインデックスキーとして“010010”と“010011”が格納されている。
ノード対201bのもう一方のノードであるノード211bの弁別ビット位置231bには2が格納され、リンク先の代表ノード番号にはノード対201fの代表ノード210fの格納された配列要素の配列番号221bが格納されている。
ノード対201fのノード210f、211fのノード種別260f、261fはともに0であり双方ともブランチノードである。それぞれの弁別ビット位置230f、231fには5、3が格納されている。ノード210fの代表ノード番号にはノード対201gの代表ノード210gの格納された配列要素の配列番号220fが格納され、ノード211fの代表ノード番号にはノード対201hの代表ノードであるノード[0]210hの格納された配列要素の配列番号221fが格納されている。
ノード対201gのノード210g、211gのノード種別260g、261gはともに1であり双方ともリーフノードであることを示し、それぞれのインデックスキー250g、251gには“100010”と“100011”が格納されている。
また同じくノード対201hの代表ノードであるノード[0]210hとそれと対をなすノード[1]211hのノード種別260h、261hはともに1であり双方ともリーフノードであることを示し、それぞれのインデックスキー250h、251hには“101011”と“101100“が格納されている。
以下、上述のツリーからインデックスキー“100010”を検索する処理の流れを簡単に説明する。弁別ビット位置は、左から0、1、2、・・・とする。
まず、ビット列“100010”を検索キーとしてルートノード210aから処理をスタートする。ルートノード210aの弁別ビット位置230aは0であるので、検索キー“100010”の弁別ビット位置が0のビット値をみると1である。そこで代表ノード番号の格納された配列番号220aに1を加えた配列番号の配列要素に格納されたノード211bにリンクする。ノード211bの弁別ビット位置231bには2が格納されているので、検索キー“100010”の弁別ビット位置が2のビット値をみると0であるから、代表ノード番号の格納された配列番号221bの配列要素に格納されたノード210fにリンクする。
ノード210fの弁別ビット位置230fには5が格納されているので、検索キー“100010”の弁別ビット位置が5のビット値をみると0であるから、代表ノード番号の格納された配列番号220fの配列要素に格納されたノード210gにリンクする。
ノード210gのノード種別260gは1でありリーフノードであることを示しているので、インデックスキー250gを読み出して検索キーと比較すると両方とも“100010”であって一致している。このようにしてカップルドノードツリーを用いた検索が行われる。
次に、図2Bを参照してカップルドノードツリーの構成の意味について説明する。
カップルドノードツリーの構成はインデックスキーの集合により規定される。図2Bの例で、ルートノード210aの弁別ビット位置が0であるのは、図2Bに例示されたインデックスキーに0ビット目が0のものと1のものがあるからである。0ビット目が0のインデックスキーのグループはノード210bの下に分類され、0ビット目が1のインデックスキーのグループはノード211bの下に分類されている。
ノード211bの弁別ビット位置が2であるのは、ノード211h、210h、211g、210gに格納された0ビット目が1のインデックスキーの1ビット目がすべて0で等しく、2ビット目で初めて異なるものがあるという、インデックスキーの集合の性質を反映している。
以下0ビット目の場合と同様に、2ビット目が1であるものはノード211f側に分類され、2ビット目が0であるものはノード210f側に分類される。
そして2ビット目が1であるインデックスキーは3ビット目の異なるものがあるのでノード211fの弁別ビット位置には3が格納され、2ビット目が0であるインデックスキーでは3ビット目も4ビット目も等しく5ビット目で異なるのでノード210fの弁別ビット位置には5が格納される。
ノード211fのリンク先においては、3ビット目が1のものと0のものがそれぞれ1つしかないことから、ノード210h、211hはリーフノードとなり、それぞれインデックスキー250hと251hに“101011”と“101100”が格納されている。
仮にインデックスキーの集合に“101100”の代わりに“101101”か“101110”が含まれていたとしても、3ビット目までは“101100”と等しいので、ノード211hに格納されるインデックスキーが変わるだけで、ツリー構造自体は変わることはない。しかし、“101100”に加えて“101101”が含まれていると、ノード211hはブランチノードとなり、その弁別ビット位置は5になる。追加されるインデックスキーが“101110”であれば、弁別ビット位置は4となる。
以上説明したように、カップルドノードツリーの構造は、インデックスキーの集合に含まれる各インデックスキーの各ビット位置のビット値により決定される。
そしてさらにいえば、異なるビット値となるビット位置ごとにビット値が“1”のノードとビット値が“0”のノードとに分岐していることから、ノード[1]側とツリーの深さ方向を優先させてリーフノードをたどると、それらに格納されたインデックスキーは、ノード211hのインデックスキー251hの“101100”、ノード210hのインデックスキー250hの“101011”、・・・、ノード210cのインデックスキー250cの“000111”となり降順にソートされている。
すなわち、カップルドノードツリーにおいては、インデックスキーはソートされてツリー上に配置されている。
検索キーで検索するときはインデックスキーがカップルドノードツリー上に配置されたルートをたどることになり、例えば検索キーが“101100”であればノード211hに到達することができる。また、上記説明からも想像がつくように、“101101”か“101110”を検索キーとした場合でもノード211hにたどり着き、インデックスキー251hと比較することにより同一のビット列からなるインデックスキーの検索が失敗したことが分かる。
また、例えば“100100”で検索した場合でも、ノード210a、211b、210fのリンク経路では検索キーの3ビット目と4ビット目は使われることがなく、“100100”の5ビット目が0なので、“100010”で検索した場合と同様にノード210gに到達することになる。このように、カップルドノードツリーに格納されたインデックスキーのビット構成に応じた弁別ビット位置を用いて分岐が行われる。
図3は、本発明を実施するためのハードウェア構成例を説明する図である。
本発明の検索装置による検索処理及びデータメンテナンスは中央処理装置302及びキャッシュメモリ303を少なくとも備えたデータ処理装置301によりデータ格納装置308を用いて実施される。カップルドノードツリーが配置される配列309と検索中にたどるノードが格納された配列要素の配列番号を記憶する探索経路スタック310を有するデータ格納装置308は、主記憶装置305または外部記憶装置306で実現することができ、あるいは通信装置307を介して接続された遠方に配置された装置を用いることも可能である。
図3の例示では、主記憶装置305、外部記憶装置306及び通信装置307が一本のバス304によりデータ処理装置301に接続されているが、接続方法はこれに限るものではない。また、主記憶装置305をデータ処理装置301内のものとすることもできるし、探索経路スタック310を中央処理装置302内のハードウェアとして実現することも可能である。あるいは、配列309は外部記憶装置306に、探索経路スタック310を主記憶装置305に持つなど、使用可能なハードウェア環境、インデックスキー集合の大きさ等に応じて適宜ハードウェア構成を選択できることは明らかである。
また、特に図示されてはいないが、処理の途中で得られた各種の値を後の処理で用いるためにそれぞれの処理に応じた一時記憶装置が用いられることは当然である。
以下、本実施形態に係る上記のカップルドノードツリーに格納されたインデックスキーの各種検索、カップルドノードツリーの生成、及び分割・結合について説明する。
先ず、図4A、図4B及び図4Cを参照して、基本的な検索処理について説明する。
図4Aは、本実施形態に係る基本検索の処理の概略を説明する図である。図4Bは、基本検索の処理フローを説明する図である。図4Cは、カップルドノードツリーによる基本検索例を説明する図であり、図2Bに例示したカップルドノードツリーのうち検索例に関係する部分及び探索経路スタックと各種ワークエリアが示されている。
図4Aに示すように、ステップS401において、検索開始ノードを設定する。検索開始ノードの設定は、検索開始ノードの配列番号の指定あるいは取得によりその配列番号、あるいは該配列番号のノードを図示しない検索開始ノード設定エリアに設定することにより行う。なお、上述の検索開始ノード設定エリアは、先に述べた「処理の途中で得られた各種の値を後の処理で用いるためにそれぞれの処理に応じた一時記憶装置」の一つである。以下の説明では、「図示しない検索開始ノード設定エリアに設定する」のような表現に変えて、「検索開始ノードとして設定する」あるいは単に「検索開始ノードに設定する」のように記述することもある。
上述のステップS401において、カップルドノードツリー全体からインデックスキーを検索する場合はルートノードが検索開始ノードとして設定されるが、後に説明する各種応用検索においては、カップルドノードツリーのあるノードが検索開始ノードとして指定され、その指定された検索開始ノードをルートノードとする部分木からインデックスキーを検索する場合がある。
次にステップS402において、探索経路スタックに終端ノードを格納する。終端ノードは探索経路スタックのボトムを示すための仮想的なブランチノードであり、ノード種別は他のブランチノードと区別するために“1”としている。弁別ビット位置は0より小さい値である“−1”としている。弁別ビット位置の桁数は、インデックスキーの桁数に対して充分あるものとする。なお、弁別ビット位置が“−1”であることで終端ノードであると識別できるので、ノード種別を“1”とすることは必須ではない。
終端ノードの代表ノード番号は、オール0の終端ノード[0]とオール1の終端ノード[1]がある。代表ノード番号がドントケアの場合は単に終端ノードと表記する。そして、代表ノードが偶数の配列番号の配列要素に格納されるとすると、終端ノード[0]のノード位置は0、終端ノード[1]のノード位置は1である。なお、終端ノード[0]と終端ノード[1]の代表ノード番号は、ノード位置0とノード位置1が識別できれば、必ずしもオール0、あるいはオール1である必要はない。
次にステップS403において検索キーを設定し、ステップS404に進み、ステップS403で設定された検索キーにより、ステップS401で設定された検索開始ノードから配列を検索し、インデックスキーを得る。このインデックスキーを得る検索処理の詳細を、次に図4Bを参照して説明する。
図4Bに示すように、ステップS405において、検索開始ノードの属するノード対の代表ノードの配列番号を代表ノード番号設定エリアに設定する。
図4Cの例示では、検索開始ノードがルートノードであるノード210aであり、ノード対201aの代表ノードすなわちノード210aの配列番号220が代表ノード番号設定エリア280に設定される。もし、検索開始ノードがノード211cであれば、ノード対201cの代表ノード210cの配列番号220bが代表ノード番号設定エリア280に設定される。
次にステップS406において、ノード位置設定エリアに、検索開始ノードがノード対においてどちらに位置するかを示すノード位置を設定する。図4Cの例示では、ノード位置として、ノード位置設定エリア290にノード210aのノード位置“0”が設定される。
図4Cの探索経路スタック310に示すように、終端ノードのノード種別は“1”であり、弁別ビット位置は全てのビットが“1”であることから、“−1”となる。
以上のステップS405及びステップS406からなる初期設定に続いて、ステップS407以降のループ処理に移行する。
ステップS407では、配列から代表ノード番号設定エリアに設定された代表ノード番号の指す配列要素の対をノード対として読み出す。ステップS407の最初の処理では、ステップS405で初期設定された代表ノード番号の指すノード対が読み出される。図4Cの例示では、代表ノード番号として配列番号220が設定されていることから、ノード対201aが読み出される。
次にステップS408において、読み出されたノード対からノード位置設定エリアに設定されたノード位置の指すノードを取り出す。ステップS408の最初の処理では、ステップS406で初期設定されたノード位置の指すノードが取り出される。図4Cの例示では、ノード位置“0”が設定されていることから、ノード対201aの2つのノードのうち、ノード210aが読み出される。
次にステップS409において、ステップS408で取り出されたノードから、ノード種別を取り出し、ステップS410に進む。
ステップS410では、ステップS409で取り出したノード種別がブランチノードのものか判定する。
ノード種別がブランチノードのものでなければ、ステップS408で取り出されたノードはリーフノードであり、ステップS416に進み、ノードからインデックスキーを検索結果として取り出し、処理を終了する。
ステップS410での判定結果が肯定的で、ステップS409で取り出したノード種別がブランチノードのものであれば、ステップS411〜ステップS415の代表ノード番号設定エリア及びノード位置設定エリアの更新処理と探索経路スタックへのノードの格納処理を経てステップS407に戻り、このループ処理をステップS410での判定処理によりリーフノードが取り出されたことを確認するまで繰り返す。
ステップS411では、ステップS408で取り出されたノードから弁別ビット位置を取り出す。
次にステップS412において、検索キーからステップS411で取り出した弁別ビット位置の指すビット値を、ノード位置として設定する。図4Cの例示では、検索キー設定エリア270に設定された値が“011010”であることから、最初のループ処理として弁別ビット位置“0”が取り出され、検索キー“011010”の0ビット目の“0”がノード位置設定エリア290に設定される。
次にステップS413において、ノードから代表ノード番号を取り出して代表ノード番号設定エリアに設定する。
次にステップS414に進み、代表ノード番号設定エリアに設定されている代表ノード番号にノード位置を加えた値をステップS408で取り出されたノードの代表ノード番号に格納し、ステップS415で該ノードを探索経路スタックに格納してステップS407に戻る。図4Cの例示では、代表ノード番号220aが取り出されて代表ノード番号設定エリア280に設定され、220a+0=220aがノード210aの代表ノード番号に格納され、そのノードが探索経路スタック310にスタックされる。
処理がステップS407に戻ると、図4Cの例示では、代表ノード番号220aの指すノード対201bを読み出し、ノード位置設定エリア290に設定された“0”の指すノード210bを取り出してそこから弁別ビット位置“1”を取り出し、検索キー“011010”の1ビット目のビット値“1”をノード位置設定エリア290に設定する。さらに代表ノード番号220bを取り出して代表ノード番号設定エリア280に設定し、代表ノード番号220b+ノード位置“1”をその代表ノード番号に格納したノード210bを探索経路スタック310にスタックする。
引き続きステップS407に戻り、代表ノード番号設定エリア280に設定された220bの指すノード対201cを読み出し、ノード位置設定エリア290に設定された“1”の指すノード211cを取り出してそこから弁別ビット位置“2”を取り出し、検索キー“011010”の2ビット目のビット値“1”をノード位置設定エリア290に設定する。さらに代表ノード番号221cを取り出して代表ノード番号設定エリア280に設定し、代表ノード番号221c+ノード位置“1”をその代表ノード番号に格納したノード211cを探索経路スタック310にスタックする。
再びステップS407に戻り、代表ノード番号設定エリア280に設定された221cの指すノード対201dを読み出し、ノード位置設定エリア290に設定された“1”の指すノード211dを取り出してそこからノード種別261dを取り出す。すると、ノード種別261dは“1”であることからこのノードはリーフノードであることが判定され、インデックスキー“011010”が得られる。
以上、本実施形態に係る基本検索処理について説明したが、基本検索だけのためであれば探索経路スタックにノードをスタックする必要はない。しかし、後に説明する各種処理動作においては、基本検索における検索開始ノードからリーフノードに至るリンク経路の履歴情報を活用するため、リンク経路のノードを探索経路スタックに格納するものとして説明した。
また、図4Cの例示では、検索の結果、検索キーと同一のインデックスキーが得られたが、検索キーと同一のインデックスキーがカップルドノードツリーに存在しなくても、ブランチノードの弁別ビット位置と該弁別ビット位置が指す検索キーのビット値により次にリンク先のノード位置が求められ、最終的にはリーフノードに至ることから、検索結果としてのインデックスキーを求めることができる。
そして、検索キーと検索結果としてのインデックスキーとは、リンク経路の全てのブランチノードの弁別ビット位置のビット値が互いに等しいものであることは、上記説明から明らかである。
次に、図5A〜図5C、図6A、図6Bにより本実施形態に係るカップルドノードツリーにおけるノード挿入処理を説明する。図5A〜図5Cが通常の挿入処理を説明するものであり、図6A、図6Bはルートノードの挿入処理を含んだ挿入処理を説明するものである。ルートノードの挿入処理と通常の挿入処理により、カップルドノードツリーが生成されることから、ルートノードの挿入処理を含んだノード挿入処理の説明はカップルドノードツリーの生成処理の説明でもある。
図5Aは挿入処理の前段である検索処理の処理フローを示す図であり、図4Aに示した検索処理において、検索開始ノードをルートノードとし、挿入しようとするノードのインデックスキーである挿入キーを検索キーとしたものに相当する。すなわち、ステップS501は図4AのステップS401で検索開始ノードをルートノードとしたものに相当し、ステップS503は図4AのS403ステップで挿入キーを検索キーとしたものに相当する。さらにS502、ステップS504の処理は図4AのステップS402、ステップS404の処理に完全に対応するので説明は省略する。
図5AのステップS511において挿入キーと検索結果として得られたインデックスキーを比較し、等しければ挿入キーは既にカップルドノードツリーに存在するのであるから、挿入は失敗となり、処理を終了する。等しくなければ次の処理、図5BのステップS512以下の処理に進む。
図5Bは、挿入するノード対のための配列要素とその挿入位置を準備する処理を説明するフロー図である。
ステップS512において、配列から空きのノード対を求め、そのノード対のうち代表ノードとなるべき配列要素の配列番号を取得して、代表ノード番号として設定する。
ステップS513に進み、挿入キーとステップS504で得たインデックスキーの大小を比較し、挿入キーが大きいときは値1を小さいときは値0のブール値を得てノード位置に設定する。
ステップS514に進み、ステップS512で設定した代表ノード番号にステップS513で得たブール値を加算した配列番号を挿入ノードの配列番号として設定する。
ステップS515に進み、ステップS512で設定した代表ノード番号にステップS513で得たブール値の論理否定値を加算した配列番号を対ノードの配列番号として設定する。
ステップS514で設定した配列番号は、挿入キーをインデックスキーとして持つリーフノードが格納される配列要素の配列番号であり、ステップS515で得た配列番号は、そのリーフノードと対をなすノードが格納される配列要素のものである。
つまり、前段の検索処理で得られたリーフノードに格納されたインデックスキーと挿入キーの大小により、挿入されるノード対のうちどちらのノードに挿入キーを保持するリーフノードが格納されるかが決定される。
ステップS516で、挿入キーとステップS504で得たインデックスキーのビット列比較を例えば排他的論理和で行い、差分ビット列を得る。
ステップS517に進み、ステップS516で得た差分ビット列から、上位0ビット目から見た最初の不一致ビットのビット位置である差分ビット位置を得る。この処理は、例えばプライオリティエンコーダを有するCPUではそこに差分ビット列を入力し、不一致のビット位置を得ることができる。また、ソフト的にプライオリティエンコーダと同等の処理を行い差分ビット位置を得ることも可能である。
例えば図2Bのカップルドノードツリーに“011011”を挿入する場合、検索結果のインデックスキーはノード211dに格納された“011010”になる。挿入キー“011011”とノード211dに格納されたインデックスキー“011010”の大小比較によりブール値が求められ、今の例では挿入キーが大きいのでブール値1が得られ、挿入されるノード対の代表ノード番号に1を加えた配列要素に挿入キーを保持するリーフノードが格納される。一方、インデックスキー“011010”は、大小比較で得られたブール値を論理反転した値を代表ノード番号に加算した配列番号の配列要素に格納される。
その際、インデックスキー“011010”と挿入キー“011011”とは5ビット目が差分ビット位置となることから、ノード211dは、弁別ビット位置を5とし、代表ノード番号を挿入されたノード対の代表ノードの配列番号とするブランチノードとなる。
また図2Bのカップルドノードツリーに“011001”を挿入しようとする場合も、検索結果のインデックスキーはノード211dに格納された“011010”になる。この場合には挿入キーが小さいのでブール値0が得られ、挿入されるノード対の代表ノード番号に0を加えた配列要素に挿入キーを保持するリーフノードが格納される。そして、インデックスキー“011010”と挿入キー“011001”とは4ビット目が差分ビット位置であることから、ノード211dは、弁別ビット位置を4とし、代表ノード番号を挿入されたノード対の代表ノードの配列番号とするブランチノードとなる。
次に図5CのステップS518以下の処理に進む。
図5Cは図5Bで準備された配列にノードを格納するとともにその挿入位置を求め、既存のノードの内容を変更して挿入処理を完成させる処理を説明するフロー図である。
ステップS518〜ステップS524までの処理は、挿入するノード対のカップルドノードツリー上の位置を求める処理であり、ステップS525以下の処理は各ノードにデータを設定して挿入処理を完成させる処理である。
ステップS518において、現在取り出されているノードを退避する。最初に退避されるノードはステップS504で取り出されたリーフノードである。
次にステップS519に進み、探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタを1つ戻す。
ステップS520に進み、ステップS519で取り出したノードから、弁別ビット位置を取り出す。
次にステップS521に進み、ステップS520で取り出した弁別ビット位置がステップS517で得たビット位置より上位の位置関係か判定する。ここで上位の位置関係とは、ビット列のより左側の位置、すなわちビット位置の値が小さい位置であることとする。
ステップS521の判定結果が否定であれば、ステップS518に戻り、ステップS518において、ステップS519で取り出したノードを退避して、以下ステップS521での判定が肯定になるまで繰り返す。ステップS521での判定が肯定になると、ステップS522に進む。
ステップS522では、ステップS519で取り出したノードは終端ノードであるか判定する。終端ノードでなければ、ステップS523に移行し、ステップS519で取り出したノードから代表ノード番号を取り出し、親ノードの配列番号として設定してステップ525に進む。終端ノードであれば、ステップS524に移行し、ルートノードの配列番号を親ノードの配列番号として設定してステップ525に進む。ここで親ノードとは、そのリンク先が、ステップS512で取得され挿入されるノード対となるノードであって、挿入されるノード対の直近上位のノードである。
上記ステップS518〜ステップS524で説明した処理は、挿入するノード対の挿入位置を決定するために、挿入するインデックスキーと検索により取得されたインデックスキーの差分ビット位置と探索経路スタックに格納されているブランチノードの弁別ビット位置との相対的位置関係を調べ、弁別ビット位置が上位となるブランチノードの次のブランチノードを親ノードとしてそのリンク先を挿入するノード対の挿入位置とするものである。
例えば図2Bのカップルドノードツリーに“111000”を挿入するとき、その3ビット目が0であることから、検索結果のインデックスキーはノード210hに格納された“101011”になる。挿入キー“111000”とノード210hに格納されたインデックスキー“101011”のビット列比較により差分ビット位置1が得られる。得られたビット位置1と探索経路スタックに積まれたブランチノードの弁別ビット位置との位置関係を弁別ビット位置が上位になるまで順次探索経路スタック310を逆にたどると、ルートノード210aに至る。探索経路スタック310に格納されたルートノード210aの代表ノード番号は、図4Bに示すステップS414においてノード位置を加えた値が設定されている。したがって、ルートノード210aから代表ノード番号220a+1を取り出し、親ノードの配列番号に設定する(ステップS523)。すなわち、親ノードの配列番号として、ノード211bの配列番号を得る。ノード211bの内容はステップS527で書き換えられ、挿入キー“111000”は書き換えられたノード211bのリンク先に挿入される。
また、探索経路スタックを逆にたどり終端ノードに至るということは、ルートノードに至っても、ルートノードの弁別ビット位置が、先に求めたビット列比較で異なるビット値となる最上位のビット位置より上位のビット位置でないということであり、そのカップルドノードツリーのインデックスキーの上位ビットで、ルートノードの弁別ビット位置より上位のビットの値は全て等しい場合である。そして、挿入するインデックスキーにおいて、初めてルートノードの弁別ビット位置より上位のビットの値に異なるビット値のものがあるということである。したがって、挿入するノード対はルートノードの直接のリンク先となる。すなわち、ルートノードが親ノードとなる。そして、ルートノードの弁別ビット位置は、既存のインデックスキーと異なる値である挿入キーの最上位ビットの位置に変わる。
なお、終端ノードが探索経路スタックから取り出されたときは、その弁別ビット位置は先に述べたように“−1”であるから、ステップS521の判定は「はい」になり、ステップS522の判定処理に移行する。
次に、ステップS525以下の各ノードにデータを設定して挿入処理を完成させる処理について説明する。
ステップS525において、ステップS514で設定した挿入ノードの配列番号の指す配列要素のノード種別に1(リーフノード)を、インデックスキーに挿入キーを書き込む。
ステップS526に進み、ステップS518で退避したノードを読み出し、ステップS515で設定した対ノードの配列番号の配列要素に読み出した内容を書き込む。
最後にステップS527において、親ノードの配列番号の指す配列要素のノード種別に0(ブランチノード)を、弁別ビット位置にステップS517で設定した差分ビット位置を、代表ノード番号にステップS512で設定した代表ノード番号を書き込み、処理を終了する。
上述の図2Bのカップルドノードツリーに“111000”を挿入する例では、取得された空ノード対のノード[0]に退避したノード211bの内容を書き込み(ステップS526)、ノード[1]を挿入キー“111000”を保持するリーフノードとする(ステップS525)。そして、ノード211bの弁別ビット位置にビット列比較により異なるビット値となる最上位のビット位置である差分ビット位置1を格納し、代表ノード番号には取得されたノード対の代表ノードが格納される配列要素の配列番号が格納される(ステップS527)。
以上の処理により、カップルドノードツリーへの新しいインデックスキーを格納したリーフノードの挿入が完了する。
図6Aは、本実施形態に係るルートノードの挿入処理を含むインデックスキーを追加する場合のノード挿入処理全体を説明する処理フロー図である。
ステップS601において、取得することを求められたカップルドノードツリーのルートノードの配列番号が登録済みであるか判定される。登録済みであれば、ステップS602に移行して図5A〜図5Cを用いて説明した通常の挿入処理が行われる。
ステップS601での判定が登録済みでなければ、ステップS603、ステップS604の処理に移行し、まったく新しいカップルドノードツリーの登録、生成が始まることになる。
ステップS603では、ルートノードに挿入キーを含むリーフノードを設定する。ステップS603の処理の詳細は、図6Bを参照して後に説明する。
次にステップS604に進み、ルートノードの配列番号として挿入ノードの配列番号を登録して処理を終了する。
図6Bは、ルートノードに挿入キーを含むリーフノードを設定する処理フローを説明する図である。
まず、ステップS605において、配列から空きのノード対を求め、そのノード対のうち代表ノードとなるべき配列要素の配列番号を取得する。次にステップS606において、ステップS605で得た配列番号に0を加えた配列番号を求め、挿入ノードの配列番号として設定する。(実際には、ステップS605で取得した配列番号に等しい。)。さらにステップS607において、ステップS606で設定した挿入ノードの配列番号のさす配列要素のノード種別に1(リーフノード)とインデックスキーに挿入キーを格納して処理を終了する。
先にも述べたように、インデックスキーの集合があるとき、そこから順次インデックスキーを取り出し、図6A、図6B及び図5A〜図5Cの処理を繰り返すことにより、インデックスキーの集合に対応した本発明のカップルドノードツリーを構築することができることは明らかである。
次に図7A、図7Bを参照して、本実施形態に係る、カップルドノードツリーから特定のインデックスキーを削除する処理フローを説明する。
図7Aは、削除処理の前段である検索処理の処理フローを示す図であり、図4A、図4Bに示した検索処理において削除キーを検索キーとし、検索開始ノードをルートノードとしたものに類似したものである。しかし、本実施形態の削除処理では、探索経路スタックは用いず、1つ分のノードを退避する退避ノードを用いる点で先に説明した検索処理と異なる。
後の説明で分かるように、削除処理では、探索経路は1つさかのぼるだけでよいのでスタックを用いる必要はないので、そのかわりにノードを退避するノード退避エリアとそのノードの配列番号を退避する親ノード配列番号退避エリアを用いる。
以下、ノード退避エリアに設定したノードを退避ノードといい、ノード退避エリアにノードを退避することを退避ノードにノードを設定すると表記することがある。また、親ノード配列番号退避エリアに退避した配列番号を親ノードの配列番号といい、親ノード配列番号退避エリアに配列番号を退避することを、親ノードに配列番号を設定すると表記することがある。
図7Aに示すように、まずステップS701において、代表ノード番号としてルートノードの配列番号を設定する。
次にステップS702において、ノード位置としてルートノードのノード位置を設定する。
さらにステップS703において、退避ノードに終端ノードを設定する。
以上で初期設定を終了し、ステップS704〜ステップS712のループ処理と、ステップS707での判定結果によりループから抜け出した後の処理であるステップS713とステップS714を実行する。
上記ループ処理のうち、ステップS704からステップS707のノード種別の判定処理は、図4Bに示すステップS407からステップ410と全く同じであるので、説明を省略する。
ステップS707の判定結果が、ノード種別がブランチノードのものであった場合は、ステップS708〜ステップS712を経てステップS704に戻る、ループ処理が実行される。
ステップS708及びステップS709の処理は探索経路スタックを用いることの代わりの処理であり、ステップS708において、ステップS705で取り出したノードを退避ノードに設定する。
ステップS709においては、代表ノード番号設定エリアに設定されている代表ノード番号にノード位置設定エリアに設定されているノード位置を加えた値の配列番号を親ノードに設定する。ここで親ノードに設定した配列番号が、ステップS708で退避したノードが格納された配列要素の配列番号であることは、明らかである。
次のステップS710〜ステップS712の処理は、図4BのステップS411〜ステップS413の処理と完全に対応するので説明は省略する。なお、図4Bに示すステップS414、ステップS415に対応するステップは、探索経路スタックを用いないことから、本実施形態の削除処理には存在しない。
上述のループ処理によるリンクの結果、リーフノードに至りステップS707での判定が否定的なものとなると、ステップS713に分岐し、リーフノードからインデックスキーを取り出す。
次にステップS714において削除キーとインデックスキーを比較し、等しくなければければ削除するインデックスキーはカップルドノードツリーに存在しないのであるから、削除は失敗となり、処理を終了する。等しければ次の処理、図7BのステップS715以下の処理に進む。
図7Bは、削除処理の後段の処理フローを説明する図である。
まず、ステップS715でノード退避エリアに退避したノードが終端ノードであるか判定する。退避したノードが終端ノードであるということは、ルートノードがリーフノードであるということである。その場合はステップS719に移行し、ステップS701で設定した代表ノード番号の指すノード対、すなわちルートノードの配列番号の指すノード対を削除する。次にステップS720に進み、登録されていたルートノードの配列番号を削除して処理を終了する。
ステップS715において退避したノードは終端ノードではないと判定されたときはステップS716に進み、ステップS704で読み出したノード対から、ステップS711で設定したノード位置のビット値を反転して得たノード位置の指すノードを取り出す。この処理は、削除対象のインデックスキーが格納されたリーフノードと対をなすノードを取り出すものである。
次にステップS717において、ステップS716で取り出したノードの内容を読み出し、ステップS709で設定した親ノードの配列番号の配列要素に上書きする。この処理は、削除対象のインデックスキーが格納されたリーフノードへのリンク元であるブランチノード(親ノード)を上記リーフノードと対をなすノードに置き換えるものである。
最後にステップS718においてステップS712で設定した代表ノード番号の指すノード対を削除して処理を終了する。
次に図8A、図8B及び図8Cを参照して、本実施形態に係る、カップルドノードツリー(部分木を含む)に格納されたインデックスキーの最小値を求める最小値検索処理を説明する。
図8Aは、カップルドノードツリー(部分木を含む)に格納されたインデックスキーの最小値を求める処理フローの概要を説明する図である。先に述べたようなインデックスキーのツリー上の配置から、インデックスキーの最小値を求める処理は検索開始ノードからノード[0]をリーフノードに至るまでツリー上でたどることに相当する。つまり、図4A、図4Bに示す基本検索において、ノード位置が常に“0”である検索を行うことに相当する。すなわちビット値が全て“0”である検索キーで検索することに相当する。
図8Aに示すステップS801とステップS802は図4Aに示すステップS401とステップS402に相当するものであり、上述のとおり、ノード位置は“0”に固定されているとすることができるので、検索キーを設定してそのビット値による分岐を行う必要がない。したがって、ステップS403に相当するステップは省略することができる。
次のステップS804において、ステップS801で設定された検索開始ノードから配列を検索し、インデックスキーの最小値を得る。このインデックスキーの最小値を得る検索処理の詳細を、次に図8Bを参照して説明する。
図8Bに示すように、ステップS805において、検索開始ノードの属するノード対の代表ノードの配列番号を代表ノード番号設定エリアに設定する。
次にステップS806において、ノード位置設定エリアに、検索開始ノードがノード対においてどちらに位置するかを示すノード位置を設定する。
次にステップS807に進み、配列から代表ノード番号設定エリアに設定された代表ノード番号の指す配列要素の対をノード対として読み出す。
次にステップS808において、読み出されたノード対からステップS806においてノード位置設定エリアに設定されたノード位置の指すノードを取り出す。
次にステップS809において、ステップS808あるいは後述のステップS817で取り出されたードから、ノード種別を取り出し、ステップS810に進む。
ステップS810では、ステップS809で取り出したノード種別がブランチノードのものか判定する。
ノード種別がブランチノードのものでなければ、ステップS808あるいはステップS817で取り出されたノードはリーフノードであり、ステップS818に進み、ノードからインデックスキーを検索結果、すなわち最小値として取り出し、処理を終了する。
ステップS810での判定結果が肯定的で、ステップS809で取り出したノード種別がブランチノードのものであれば、ステップS813、ステップS815〜ステップS817の処理を経てステップS809に戻り、このループ処理をステップS810での判定処理によりリーフノードが取り出されたことを確認するまで繰り返す。
ステップS813では、ノードから代表ノード番号を取り出して代表ノード番号設定エリアに設定する。
次にステップS815でノードを探索経路スタックに格納する。
次にステップS816に進み、配列から代表ノード番号設定エリアに設定された代表ノード番号の指す配列要素の対をノード対として読み出す。
次にステップS817において、ステップS816で読み出されたノード対から、ノード[0]であるノードを取り出し、ステップS809に戻る。そして上述のとおり、ステップS810での判定処理によりリーフノードが取り出されたことを確認するまでステップS809〜ステップS817の処理を繰り返す。
図8Cは、カップルドノードツリーによる最小値検索例を説明する図であり、図2Bに例示したカップルドノードツリーのうち最小値検索に関係するルートノード210aとノード210b以下の階層の部分木が示されている。
初期設定において、検索開始ノードとしてルートノード210a、代表ノード番号として配列番号220が設定され、探索経路スタック310には終端ノードが格納される。さらにルートノード210aのノード位置0が設定される。
次に代表ノード番号として設定された配列番号220の指すノード対201aから初期設定されたノード位置の指すノード210aを取り出してノード種別260aの判定を行い、ブランチノードであるので代表ノード番号220aを取り出して代表ノード番号設定エリアに設定するとともに、ノード210aを探索経路スタック310に格納する。
次に代表ノード番号220aの指すノード対201bからノード[0]であるノード210bを取り出してノード種別260bの判定を行い、ブランチノードであるので代表ノード番号220bを取り出して代表ノード番号設定エリアに設定するとともに、ノード210bを探索経路スタック310に格納する。
さらに代表ノード番号220bの指すノード対201cからノード[0]であるノード210cを取り出してノード種別260cの判定を行い、リーフノードであるのでインデックスキー“000111”を最小値として取り出すものである。
上述の例では、検索開始ノードはノード位置が0であるルートノードであったが、検索開始ノードを211cとすると、代表ノード番号として220b、ノード位置として1が初期設定され、ノード対201cが読み出されてそこからノード211cが取り出される。
次に図9A、図9B及び図9Cを参照して、本実施形態に係る、カップルドノードツリー(部分木を含む)に格納されたインデックスキーの最大値を求める最大値検索処理を説明する。
この最大値検索処理は、先に説明した最小値検索処理といわば双対の関係にある処理であり、以下の説明から明らかなとおり、最小値検索における値“0”を“1”に置き換えたものに相当する。
図9Aは、カップルドノードツリー(部分木を含む)に格納されたインデックスキーの最大値を求める処理フローの概要を説明する図である。先に述べたようなインデックスキーのツリー上の配置から、インデックスキーの最大値を求める処理は検索開始ノードからノード[1]をリーフノードに至るまでツリー上でたどることに相当する。つまり、図4A、図4Bに示す基本検索において、ノード位置が常に“1”である検索を行うことに相当する。すなわちビット値が全て“1”である検索キーで検索することに相当する。
図9Aに示すステップS901とステップS902は図4Aに示すステップS401とステップS402に相当するものであり、上述のとおり、ノード位置は“1”に固定されているとすることができるので、検索キーを設定してそのビット値による分岐を行う必要がない。したがって、ステップS403に相当するステップは省略することができる。
次のステップS904において、ステップS901で設定された検索開始ノードから配列を検索し、インデックスキーの最大値を得る。このインデックスキーの最大値を得る検索処理の詳細を、次に図9Bを参照して説明する。
図9Bに示すように、ステップS905において、検索開始ノードの属するノード対の代表ノードの配列番号を代表ノード番号設定エリアに設定する。
次にステップS906において、ノード位置設定エリアに、検索開始ノードがノード対においてどちらに位置するかを示すノード位置を設定する。
次にステップS907に進み、配列から代表ノード番号設定エリアに設定された代表ノード番号の指す配列要素の対をノード対として読み出す。
次にステップS908において、読み出されたノード対からステップS906においてノード位置設定エリアに設定されたノード位置の指すノードを取り出す。
次にステップS909において、ステップS908あるいは後述のステップS917で取り出されたードから、ノード種別を取り出し、ステップS910に進む。
ステップS910では、ステップS909で取り出したノード種別がブランチノードのものか判定する。
ノード種別がブランチノードのものでなければ、ステップS908あるいはステップS917で取り出されたノードはリーフノードであり、ステップS918に進み、ノードからインデックスキーを検索結果、すなわち最大値として取り出し、処理を終了する。
ステップS910での判定結果が肯定的で、ステップS909で取り出したノード種別がブランチノードのものであれば、ステップS913〜ステップS917の処理を経てステップS909に戻り、このループ処理をステップS910での判定処理によりリーフノードが取り出されたことを確認するまで繰り返す。
ステップS913では、ノードから代表ノード番号を取り出して代表ノード番号設定エリアに設定する。
次にステップS914に進み、代表ノード番号設定エリアに設定されている代表ノード番号に1を加えた値をノードの代表ノード番号に格納し、ステップS915で該ノードを探索経路スタックに格納する。
次にステップS916に進み、配列から代表ノード番号設定エリアに設定された代表ノード番号の指す配列要素の対をノード対として読み出す。
次にステップS917において、ステップS916で読み出されたノード対から、ノード[1]であるノードを取り出し、ステップS909に戻る。そして上述のとおり、ステップS910での判定処理によりリーフノードが取り出されたことを確認するまでステップS909〜ステップS917の処理を繰り返す。
図9Cは、カップルドノードツリーによる最大値検索例を説明する図であり、図2Bに例示したカップルドノードツリーのうち最大値検索に関係するルートノード210aとノード211b以下の階層の部分木が示されている。
初期設定において、検索開始ノードとしてルートノード210a、代表ノード番号として配列番号220が設定され、探索経路スタック310には終端ノードが格納される。さらにルートノード210aのノード位置0が設定される。
次に代表ノード番号として設定された配列番号220の指すノード対201aから初期設定されたノード位置の指すノード210aを取り出してノード種別260aの判定を行い、ブランチノードであるので代表ノード番号220aを取り出して代表ノード番号設定エリアに設定するとともに、その代表ノード番号を210a+1に設定したノード210aを探索経路スタック310に格納する。
次に代表ノード番号220aの指すノード対201bからノード[1]であるノード211bを取り出してノード種別261bの判定を行い、ブランチノードであるので代表ノード番号221bを取り出して代表ノード番号設定エリアに設定するとともに、代表ノード番号に221b+1を格納したノード211bを探索経路スタック310に格納する。
さらに代表ノード番号221bの指すノード対201fからノード[1]であるノード211fを取り出してノード種別261fの判定を行い、ブランチノードであるので代表ノード番号221fを取り出して代表ノード番号設定エリアに設定するとともに、代表ノード番号に221f+1を格納したノード211fを探索経路スタック310に格納する。
さらに代表ノード番号221fの指すノード対201hからノード[1]であるノード211hを取り出してノード種別261hの判定を行い、リーフノードであるのでインデックスキー“101100”を最大値として取り出すものである。
以上、本実施形態に係る最小値・最大値検索処理について説明したが、最小値・最大値検索だけのためであれば、基本検索の場合と同様に探索経路スタックにノードをスタックする必要はない。しかし、後に説明する各種処理動作においては、最小値・最大値検索における検索開始ノードからリーフノードに至るリンク経路の履歴情報を活用するため、リンク経路のノードを探索経路スタックに格納するものとして説明した。
次に図10A、図10B及び図10Cを参照して、本実施形態に係る、カップルドノードツリー(部分木を含む)に格納されたインデックスキーの下限値を求める下限値検索処理を説明する。ここで下限値とは、指定された下限キー以上のインデックスキーの最小値である。
図10A及び図10Bは、カップルドノードツリーに格納されたインデックスキーの下限値を求める処理を示したフローチャートである。図10A及び図10Bに示す下限値を求める処理は、ユーザ等が指定する検索範囲について検索を行う際に、実際にはインデックスキーが取り得ない範囲については対象外とし、実際にインデックスキーが含まれる範囲について検索を行う処理に応用される。なお、図10A及び図10Bでは、指定された下限キーの取得処理は省略されている。以降の各種応用検索においても同様である。
まず、ステップS1001で、検索開始ノードを設定する。先に図4Aに示す基本検索の説明で述べたように、検索開始ノードの設定は、検索開始ノードの配列番号の指定あるいは取得によりその配列番号、あるいは該配列番号のノードを図示しない検索開始ノード設定エリアに設定することにより行う。上述の点は、後に説明する他の応用検索においても同様である。
次にステップS1002において、探索経路スタックに、終端ノードを格納する。
ステップS1003では、図8Bに示す最小値検索処理を行いインデックスキーの最小値を求める。そして、ステップS1004で、下限キーと、ステップS1003で求めた最小値との比較をし、最小値が下限キー以上であるかを判定する。最小値が下限キー以上の値をとる場合、ステップS1005に進み、ステップS1003で求めた最小値を下限値として設定し、処理を終了する。
ステップS1004において、ステップS1002で求めた最小値が下限キーよりも小さいと判定された場合は、ステップS1006で探索経路スタックに終端ノード[0]を格納し、ステップS1007に進む。
ステップS1007で下限キーを検索キーとして設定する。次にステップS1008で、該検索キーによりステップS1001で設定した検索開始ノードを検索開始ノードとして、図4Bを参照して説明したビット列検索方法により配列を検索し、インデックスキーを得る。
そして、ステップS1009で、検索キーとステップS1008の検索の結果得られたインデックスキーとを比較して値が一致するか否かを判定する。検索キーとインデックスキーが等しいと判定された場合は、ステップS1010に進み、検索により得られたインデックスキーを上記下限値として設定し、処理を終了する。
検索キーとインデックスキーが等しくないと判定された場合は、図10Bに示すステップS1011に進む。
ステップS1011では、検索キーとインデックスキーの大小関係を判定する。インデックスキーが、検索キーすなわち下限キーよりも小さい場合は、そのインデックスキーは、ユーザ等により指定された検索範囲に含まれないことを意味する。
一方、インデックスキーが検索キーよりも大きい場合は、そのインデックスキーは指定された検索範囲に含まれることを意味する。そこで、インデックスキーが検索キーよりも大きいと判定されると、ステップS1019に進み、そのインデックスキーを下限値に設定して、処理を終了する。
一方、ステップS1011において、インデックスキーが検索キーよりも小さいと判定されると、ステップS1012に進む。ステップS1012からステップS1018までの処理は、カップルドノードツリーの順序性に基づいて昇順にインデックスキーを取り出す処理である。先に述べたとおり、カップルドノードツリーにおいて、ノード[1]側とツリーの深さ方向を優先させてリーフノードをたどると、そこに格納されているインデックスキーは降順にソートされている。
したがって、昇順にインデックスキーを取り出すには、ノード対をなすノードのうちノード[0]側及びツリーの深さを優先させてノードから順次リーフノードをたどり、各リーフノードからインデックスキーを取り出していけばよい。
ステップS1012からステップS1018の処理により、カップルドノードツリーに格納されているインデックスキーが順に取り出されていき、検索キーすなわち下限キーよりも大きい値をとるインデックスキーが得られると、そのインデックスキーが下限値として設定される。
まず、ステップS1012で、探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタの値を1つ減らす。最初のステップS1012での探索経路スタックの状態は、ステップS1008の検索処理を実行したときの状態である。
次にステップS1013において、取り出したノードの代表番号から取り出したノードのノード位置を得る。
次にステップS1014に進み、ステップS1013で得たノード位置がノード[1]側であるか判定する。ノード[1]側であればステップS1012に戻り、ノード[0]側であればステップS1015に進む。
ステップS1015では、ステップS1012で取り出したノードが終端ノードであるか判定する。該ノードが終端ノードであれば、下限値は存在しないことになり、検索失敗として処理を終了する。この場合は例外的処理であり、下限値を求める対象であるカップルドノードツリーが下限キーより小さいインデックスキーを格納したリーフノードだけから構成されている場合である。
ステップS1015での判定が「終端ノードではない」であれば、ステップS1016に進み、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS1012で取り出したノードの代表ノード番号を設定する。
さらにステップS1017で、検索開始ノードのノード位置として、値1を設定してステップS1018に進み、図8Bに示す最小値検索を実行し、インデックスキーの最小値を取得し、ステップS1011の下限キーとインデックスキーの大小の判定処理に戻る。
上述のステップS1016とステップS1017の処理は、図8Bに示すステップS805とステップS806に対応した処理である。ステップS1016で、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS1012で取り出したノードの代表ノード番号を設定し、ステップS805において、該設定されたステップS1012で取り出したノードの代表ノード番号が、代表ノード番号設定エリアに設定される。同様に、ステップS1017で、検索開始ノードのノード位置として、値1を設定し、ステップS806において、該設定された値1をノード位置設定エリアに設定する。
以上説明したステップS1011〜ステップS1018のループ処理によりインデックスキーを昇順に取り出し、検索キー(下限キー)より大きいものが得られたとき、ステップS1019に分岐し、それが下限値として設定される。
図10Cは、カップルドノードツリーによる下限値検索例を説明する図であり、図10C(a)には、図2Bに例示したカップルドノードツリーのうち下限値検索例に関係するルートノード210aとノード210b以下の階層の部分木と検索キー設定エリア270が示されており、検索キー設定エリア270には下限キー“010100”が設定されている。図10C(b)には、下限キーによる検索後の下限値検索による探索経路スタック310の状態遷移(1)、(2)、(3)が示されている。
上述のステップS1008における下限キー“010100”によるルートノード210aを検索開始ノードとする検索を実行すると、図10C(a)に太枠で示すように、ノード210a、ノード210b、ノード211c、ノード210dをたどり、リーフノードであるノード210eに至り、インデックスキー“010010”が得られる。
上記検索を実行すると、図10C(b)の(1)に示すように探索経路スタック310には、終端ノード[0]とノード210aからノード210dまでの探索経路のブランチノードが順次格納され、図示しないスタックポインタはノード210dを指している。そして、分岐先ノードのノード位置が“1”であるノード210bの代表ノード番号は1加算され、220b+1となっている。
図10C(a)に示すように、ノード210eが下限値の探索開始ノードとなり、ノード210eに格納されたインデックスキー“010010”と下限キー“010100”の大小比較が図10Bに示すステップS1011で実行される。インデックスキー“010010”が下限キー“010100”より小さいので、探索経路スタック310からノード210dが取り出され、スタックポインタの指すノードは、図10C(b)の(2)に示すようにノード210dからノード211cに変わる。
ノード210dの代表ノード番号220dからはノード位置“0”が検出される。したがって、代表ノード番号220dを、図8Bに示す最小値検索における代表ノード番号と、ノード位置に値“1”を設定して最小値検索を実行する。すると、図10C(b)の(2)に示すように、配列番号が220d+1であるリーフノード211eのインデックスキー“010011”が取り出される。このインデックスキーも下限キーより小さいこと、ノード211cの代表ノード番号221cからはノード位置“0”が検出されるから、代表ノード番号221cを、図8Bに示す最小値検索における代表ノード番号と、ノード位置に値“1”を設定して再び最小値検索を実行する。すると、図10C(b)の(3)に示すように、配列番号が221c+1であるリーフノード211dのインデックスキー“011010”が取り出される。そして、下限キーとの大小比較から、このインデックスキーが下限値として求められる。
次に図11A、図11B及び図11Cを参照して、本実施形態に係る、カップルドノードツリー(部分木を含む)に格納されたインデックスキーの上限値を求める上限値検索処理を説明する。ここで上限値とは、指定された上限キー以下のインデックスキーの最大値である。
図11A及び図11Bは、カップルドノードツリーに格納されたインデックスキーの上限値を求める処理を示したフローチャートである。図11A及び図11Bに示す上限値を求める処理は、先に説明した下限値検索と同様に、ユーザ等が指定する検索範囲について検索を行う際に、実際にはインデックスキーが取り得ない範囲については対象外とし、実際にインデックスキーが含まれる範囲について検索を行う処理に応用される。
この上限値検索処理は、先に説明した下限値検索処理といわば双対の関係にある処理であり、以下の説明から明らかなとおり、下限値検索におけるノード位置0と1を逆にし、最小値を最大値に置き換え、大小関係を逆にしたものに相当する。
まず、ステップS1101で、検索開始ノードを設定する。次にステップS1102において、探索経路スタックに、終端ノードを格納する。
ステップS1103では、図9Bに示す最大値検索処理を行いインデックスキーの最大値を求める。そして、ステップS1104で、上限キーと、ステップS1103で求めた最大値との比較をし、最大値が上限キー以下であるかを判定する。最大値が上限キー以下の値をとる場合、ステップS1105に進み、ステップS1103で求めた最大値を上限値として設定し、処理を終了する。
ステップS1104において、ステップS1102で求めた最大値が上限キーよりも大きいと判定された場合は、ステップS1106で探索経路スタックに終端ノード[1]を格納し、ステップS1107に進む。
ステップS1107で上限キーを検索キーとして設定する。次にステップS1108で、該検索キーによりステップS1101で設定した検索開始ノードを検索開始ノードとして、図4Bを参照して説明したビット列検索方法により配列を検索し、インデックスキーを得る。
そして、ステップS1109で、検索キーとステップS1108の検索の結果得られたインデックスキーとを比較して値が一致するか否かを判定する。検索キーとインデックスキーが等しいと判定された場合は、ステップS1110に進み、検索により得られたインデックスキーを上記上限値として設定し、処理を終了する。
検索キーとインデックスキーが等しくないと判定された場合は、図11Bに示すステップS1111に進む。
ステップS1111では、検索キーとインデックスキーの大小関係を判定する。インデックスキーが、検索キーすなわち上限キーよりも大きい場合は、そのインデックスキーは、ユーザ等により指定された検索範囲に含まれないことを意味する。
一方、インデックスキーが検索キーよりも小さい場合は、そのインデックスキーは指定された検索範囲に含まれることを意味する。そこで、インデックスキーが検索キーよりも小さいと判定されると、ステップS1119に進み、そのインデックスキーを上限値に設定して、処理を終了する。
一方、ステップS1111において、インデックスキーが検索キーよりも大きいと判定されると、ステップS1112に進む。ステップS1112からステップS1118までの処理は、カップルドノードツリーの順序性に基づいて降順にインデックスキーを取り出す処理である。先に述べたとおり、カップルドノードツリーにおいて、ノード[1]側とツリーの深さ方向を優先させてリーフノードをたどると、そこに格納されているインデックスキーは降順にソートされている。
したがって、降順にインデックスキーを取り出すには、ノード対をなすノードのうちノード[1]側及びツリーの深さを優先させてノードから順次リーフノードをたどり、各リーフノードからインデックスキーを取り出していけばよい。
ステップS1112からステップS1118の処理により、カップルドノードツリーに格納されているインデックスキーが順に取り出されていき、検索キーすなわち上限キーよりも小さい値をとるインデックスキーが得られると、そのインデックスキーが上限値として設定される。
まず、ステップS1112で、探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタの値を1つ減らす。最初のステップS1112での探索経路スタックの状態は、ステップS1108の検索処理を実行したときの状態である。
次にステップS1113において、取り出したノードの代表番号から取り出したノードのノード位置を得る。
次にステップS1114に進み、ステップS1113で得たノード位置がノード[0]側であるか判定する。ノード[0]側であればステップS1112に戻り、ノード[1]側であればステップS1115に進む。
ステップS1115では、ステップS1112で取り出したノードが終端ノードであるか判定する。該ノードが終端ノードであれば、上限値は存在しないことになり、検索失敗として処理を終了する。この場合は例外的処理であり、上限値を求める対象であるカップルドノードツリーが上限キーより大きいインデックスキーを格納したリーフノードだけから構成されている場合である。
ステップS1115での判定が「終端ノードではない」であれば、ステップS1116に進み、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS1112で取り出したノードの代表ノード番号を設定する。
さらにステップS1117で、検索開始ノードのノード位置として、値0を設定してステップS1118に進み、図9Bに示す最大値検索を実行し、インデックスキーの最大値を取得し、ステップS1111の上限キーとインデックスキーの大小の判定処理に戻る。
上述のステップS1116とステップS1117の処理は、図9Bに示すステップS905とステップS906に対応した処理である。ステップS1116で、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS1112で取り出したノードの代表ノード番号を設定し、ステップS905において、該設定されたステップS1112で取り出したノードの代表ノード番号が、代表ノード番号設定エリアに設定される。同様に、ステップS1117で、検索開始ノードのノード位置として、値0を設定し、ステップS906において、該設定された値0をノード位置設定エリアに設定する。
以上説明したステップS1111〜ステップS1118のループ処理によりインデックスキーを降順に取り出し、検索キー(上限キー)より小さいものが得られたとき、ステップS1119に分岐し、それが上限値として設定される。
図11Cは、カップルドノードツリーによる上限値検索例を説明する図であり、図11C(a)には、図2Bに例示したカップルドノードツリーのうち上限値検索例に関係するルートノード210aとノード211b以下の階層の部分木と検索キー設定エリア270が示されており、検索キー設定エリア270には上限キー“101001”が設定されている。図11C(b)には、上限キーによる検索後の上限値検索による探索経路スタック310の状態遷移(1)、(2)が示されている。
上述のステップS1108における上限キー“101001”によるルートノード210aを検索開始ノードとする検索を実行すると、図11C(a)に太枠で示すように、ノード210a、ノード211b、ノード211fをたどり、リーフノードであるノード210hに至り、インデックスキー“101011”が得られる。
上記検索を実行すると、図11C(b)の(1)に示すように探索経路スタック310には、終端ノード[1]とノード210aからノード211fまでの探索経路のブランチノードが順次格納され、図示しないスタックポインタはノード211fを指している。そして、分岐先ノードのノード位置が“1”であるノード210a、ノード210bの代表ノード番号は1加算され、それぞれ220a+1、220b+1となっている。
図11C(a)に示すように、ノード210hが上限値の探索開始ノードとなり、ノード210hに格納されたインデックスキー“101011”と上限キー“101001”の大小比較が図11Bに示すステップS1111で実行される。インデックスキー“101011”が上限キー“101001”より大きいので、探索経路スタック310からノード211fが取り出され、スタックポインタの指すノードは、図11C(b)の(1)に矢印で示すようにノード211fからノード211bに変わる。
ノード211fの代表ノード番号221fからはノード位置“0”が検出されるので、図11Bに示すステップS1114からステップS1112へのループ処理が実行される。そして、ステップS1112でノード211bが取り出され、スタックポインタは、図11C(b)の(1)から(2)への点線による矢印に示すように、ノード210aを指す。ノード211bの代表ノード番号221b+1からはノード位置“1”が検出される。
したがって、探索経路スタック310に格納されたノード211bの代表ノード番号221b+1から1を減算した221bを、図9Bに示す最大値検索における代表ノード番号と、ノード位置に値“0”を設定して最大値検索を実行する。すると、図11C(b)の(2)に示すように、配列番号が220f+1であるリーフノード211gのインデックスキー“100011”が取り出される。そして、上限キーとの大小比較から、このインデックスキーが上限値として求められる。
次に、本実施形態に係る、カップルドノードツリーの分割/結合処理について説明をする。
ここでカップルドノードツリーの分割とは、あるビット列からなる分割キーを指定したとき、カップルドノードツリーに含まれるインデックスキーをその分割キーとの大小関係により2グループに分け、それぞれのグループに属するインデックスキーからなる2つのカップルドノードツリーを生成することである。
大小関係による分割について、以下の説明では、分割キーより大きいグループと分割キー以下のグループに分割するとするが、分割キー以上のグループと分割キーより小さいグループに分割する場合でも、同様に分割/結合が可能であることは、以下の説明から容易に理解されるであろう。
要するに、分割キーはカップルドノードツリーをどこで分割するかを決定するために用いられるキーである。
また、カップルドノードツリーの結合とは、2つのインデックスキーの集合に対応する2つカップルドノードツリーから2つのインデックスキーの集合の和集合に対応するカップルドノードツリーを生成することである。本発明では、2つのインデックスキーの集合の積集合は空であることを前提にしている。
以下、カップルドノードツリーの分割/結合処理として3つの実施例を説明するが、その説明において、カップルドノードツリーを単にツリーということがある。
第1の実施例は、分割対象である処理元のツリー(以下、単に処理元ということがある。)のインデックスキーの最小値を取り出し、取り出したインデックスキーの最小値を、処理元の分割により生成される処理先のツリー(以下、単に処理先ということがある。)に挿入し、処理元のツリーからインデックスキーの最小値を削除する処理を、最小値が分割キー以下である間繰り返すことにより、分割対象である処理元のツリーから処理先のツリーを分割するものである。
図12A及び図12Bを参照して、第1の実施例におけるカップルドノードツリーの分割処理フローを説明する。
図12Aは、第1の実施例における分割処理の前段の処理である処理先の初期設定等に関する処理を説明する図である。
最初のステップS1201で指定された分割キーを処理元の分割キーとして設定する。分割キーの指定は、操作者による外部入力の場合もあり得るし、あるコンピュータプログラムの処理結果による場合、遠方からコマンドによる場合等があり得る。指定された分割キーは、処理元の分割キーを保持するメモリ上のエリアに設定される。
次にステップS1202で、処理元のルートノードを、処理元の検索開始ノードに設定し、ステップS1202aで処理元の探索経路スタックに終端ノードを格納してステップS1203に進む。
ステップS1203では、処理元の検索開始ノード、すなわちステップS1202で検索開始ノードに設定したルートノードから図8Bに示す最小値検索を行い、最小値を求める。
次にステップS1204において、該最小値が分割キーより大であるか判定する。処理元の最小値が最初から分割キーより大であれば分割キー以下のインデックスキーは処理元に含まれないことからここで処理は終了となる。以上の初期処理は第2、第3の分割処理においても同様である。
ステップS1203の最小値検索で得られた最小値が分割キーより小さければ、ステップS1205に進み、該最小値を処理先の挿入処理における挿入キーに設定する。
次にステップS1206において、図6Bに示す、ルートノードに挿入キーを含むリーフノード(挿入ノード)を設定する処理を実行する。そして、ステップS1207に進み、処理先のルートノードの配列番号として、挿入ノードの配列番号を登録し、ステップS1208で処理先の検索開始ノードとして、処理先のルートノードを設定することにより、処理先の初期設定を完了させ、引き続いて、図12Bに示すステップS1209に移行する。
図12Bは、第1の実施例における分割処理の後段の処理を説明する図である。
図12Bに示すように、ステップS1209において、ステップS1205あるいは後述のステップS1214における挿入キーを処理元の削除処理における削除キーに設定し、ステップS1210において、図7A、図7Bに示す削除処理により、処理元のツリーから削除キーを含むリーフノードを削除する。
次のステップS1211では、処理元のツリーが登録済みか判定する。この判定結果が登録済みではないというのは処理元のツリーが全て削除済みであることを意味するから、分割キーが処理元のツリーのインデックスキーの最大値以上である例外的なものであり、その場合には処理を終了する。
処理元のツリーが登録済みであればステップS1212に移行し、ステップS1202で検索開始ノードとして設定したルートノードを最小値検索の検索開始ノードとして、図8Aに示す最小値検索処理を実行してインデックスキーの最小値を得る。
次にステップS1213に進み、ステップS1212で得た最小値が分割キーより大であるか判定する。最小値が分割キーより大であれば、ツリーの分割が完成しているのであるから処理を終了し、以下であれば、ステップS1214に移行する。
ステップS1214では、ステップS1212で得られた最小値を処理先の挿入処理における挿入キーに設定する。
次にステップS1215で、図5A、図5Bに示すツリーの挿入処理により、挿入キーによる処理先へのノードの挿入を実行し、処理元のツリーからのノードの削除処理であるステップS1209、ステップS1210へ戻る。
以上のステップS1209〜ステップS1215のループ処理を、ステップS1213において、ステップS1212で得た最小値が分割キーより大であると判定されるまで繰り返すことにより、ツリーの分割が実現される。
上記分割処理の説明では、処理元のインデックスキーの最小値から順に削除を行うようにしたが、同様にインデックスキーの最大値から順に削除を行うことができることは、当業者に明らかである。その場合、ステップS1203とステップS1212はインデックスキーの最大値を求める処理になり、ステップS1204とステップS1213は最大値と分割キーの大小関係の判定処理となり、ステップS1214では最大値を処理先の挿入キーに設定することになる。
以上、分割処理について説明したが、結合処理も図12A及び図12Bに示す処理フローに基づいて実行できる。
結合処理は、結合しようとする2つのツリーのうちどちらかを処理元のツリーとし、分割キーを処理元のツリーのインデックスキーの最大値以上とすれば、先に述べた例外的な処理に該当し、処理元のツリーは削除され、処理先のツリーに結合される。なお、処理元のツリーのインデックスキーの最大値が未知の場合には、前もって図9Aに示す最大値検索処理により分割キーを求めることになる。
そして、処理先は既に登録済みであることから、ステップS1205〜ステップS1207は省略することができ、処理元の分割キーを処理元のツリーのインデックスキーの最大値以上とするのであるから、ステップS1204及びステップS1213の大小比較では、分割キーが最小値より常に大きくステップS1205あるいはステップS1214へ分岐するのでステップS1204及びステップS1213を省略することができる。そうであれば、分割キーを設定する意味もないことから、結局ステップS1201も不要になり、ただ単に最小値検索と挿入処理と削除処理の繰り返しにより結合処理を行うことができる。
また、分割処理について述べたように、最大値検索と挿入処理と削除処理の繰り返しにより結合処理を行うことができることも明らかである。
本実施例は処理のロジックは簡易なものであるが、処理元のルートノードを検索開始ノードとする最小値検索を繰り返し、インデックスキー単位で挿入削除を行うため、実行時の処理ステップ数は大きくなる。
次に本実施形態に係る分割/結合処理の第2の実施例について説明する。
本実施例は、インデックスキー単位で挿入削除を行う点では第1の実施例と同様であるが、挿入削除すべきインデックスキーの探索に探索経路スタックを活用し、挿入処理及び削除処理の実行時の処理ステップ数を小さくしたものである。
図13A及び図13Bを参照して、第2の実施例におけるカップルドノードツリーの分割処理フローを説明する。
図13Aは、第2の実施例における分割処理の前段の処理である初期設定に関する処理を説明する図である。
最初のステップS1301で指定された分割キーを処理元の分割キーとして設定する。第1の実施例について述べたように、分割キーの指定は、操作者による外部入力の場合もあり得るし、あるコンピュータプログラムの処理結果による場合、遠方からコマンドによる場合等があり得る。指定された分割キーは、処理元の分割キーを保持するメモリ上のエリアに設定される。
次にステップS1302で、処理元のルートノードを、処理元の検索開始ノードに設定し、ステップS1302aに進み、処理元の探索経路スタックに、終端ノードを格納する。
次にステップS1303で、処理元の検索開始ノード、すなわちステップS1302で検索開始ノードに設定したルートノードから図8Bに示す最小値検索を行い、最小値を求める。
次にステップS1304において、該最小値が分割キーより大であるか判定する。処理元の最小値が最初から分割キーより大であれば分割キー以下のインデックスキーは処理元に含まれないことからここで処理は終了となる。
ステップS1303の最小値検索で得られた最小値が分割キー以下であれば、ステップS1306〜ステップS1310の処理先の初期設定処理に進む。
ステップS1306において、ステップS1303で得た最小値を挿入キーとして設定する。次にステップS1307において、図6Bに示す、ルートノードに挿入キーを含むリーフノード(挿入ノード)を設定する処理を実行する。そして、ステップS1308に進み、処理先のルートノードの配列番号として、挿入ノードの配列番号を登録し、ステップS1309で処理先の検索開始ノードとして、処理先のルートノードを設定する。さらにステップS1310において、処理先の探索経路スタックに終端ノードを格納して処理先の初期設定処理を完了し、図13Bに示すステップS1311以降の後段の処理に移行する。
図13Bは、第2の実施例におけるカップルドノードツリーの分割処理の後段を説明する図である。
ステップS1311において、処理元から削除ノードを削除し、後に削除ノードと対をなすノードの内容が複写される該ノードの親ノード(処理元の親ノード)を得る。ステップS1311の処理及び削除ノードと処理元の親ノードについては、後に図15を参照して詳細に説明する。
次にステップS1312において、処理元が登録済みか判定する。実施例1の場合と同様に、処理元が登録済みでなければ処理元のツリーが全て削除済みであることを意味するから、分割キーが処理元のツリーのインデックスキーの最大値以上である例外的なものであり、その場合には処理を終了する。
処理元が登録済みであれば、ステップS1313に進み、処理元の検索開始ノードにステップS1311で得た処理元の親ノードを設定し、ステップS1314に進んで、図8Bに示す最小値検索を実行して最小値を得る。
後に説明するように、処理元の親ノードは削除ノードの直近上位のブランチノードである。削除ノードは処理元のインデックスキーの最小値を含むものであり、先に述べたインデックスキーの順序性から、次に検索する最小値は処理元の親ノードの下位にある。したがって、ステップS1314での最小値検索の検索開始ノードはルートノードとしないで処理元の親ノードとすることにより、処理ステップ数を低減することができる。
次にステップS1315において、ステップS1314で得られた最小値が分割キーより大か判定する。最小値が分割キーより大であれば、ツリーの分割が完成しているのであるから処理を終了し、以下であればステップS1316に進む。
ステップS1316において、処理先の検索開始ノードより、図9Bに示す最大値検索を実行し、最大値を得る。処理先の検索開始ノードは、最初の処理ではステップS1309で設定された処理先のルートノードであり、それ以降は後述のステップS1318で設定される。
次にステップS1317に進み、ステップ1303あるいは後述のステップS1314で得た最小値とステップS1316で得た最大値により、挿入するノード対の処理先の親ノードを求め、処理先の該親ノードに該最小値を含むノード対を挿入する。この処理は、図12Bに示すステップS1215の挿入処理とは異なる本実施例特有のものであり、ステップS1317の処理及び処理先の親ノードについて、後に図14を参照して詳細に説明する。
次にステップS1318において、処理先の検索開始ノードに処理先の親ノードを設定し、ステップS1311に戻る。
以上のステップS1311〜ステップS1318のループ処理を、ステップS1315において、ステップS1314で得た最小値が分割キーより大であると判定されるまで繰り返すことにより、ツリーの分割が実現される。
図14は、図13Bに示すステップS1317に対応する処理先のノード対の挿入処理フローを説明する図である。
図14に示すように、ステップS1401で配列からノード対が空の代表ノードの配列番号を取得し、代表ノード番号として設定する。
次にステップS1402において、ステップS1401で設定した代表ノード番号に値“1”を加えて得た配列番号を挿入ノードの配列番号として設定し、ステップS1403において、代表ノード番号に値“0”を加えて得た配列番号を挿入ノードと対をなす対ノードの配列番号として設定する。
次にステップS1404において、図13Bに示すステップS1314で得た最小値である挿入キーとステップS1316で得た最大値をビット列として比較して上位0ビット目から見た最初の不一致ビットの位置を求め、それを差分ビット位置格納エリアに設定する。
次にステップS1405に進み、図5Cに示すステップS518以降の、ノード対を挿入する位置を求め、ノード対の各ノードの内容を書き込んで挿入処理を完成させる処理を実行して処理を終了する。
上述のステップS1401〜ステップS1404の処理は、図5Bに示すステップS512〜ステップS517からなる、挿入するノード対のための配列要素を準備する処理に相当するものである。また、図13Bに示すステップS1316の処理先の最大値検索は、図5Aに示す挿入処理の前段である、処理先の検索処理に相当する。本実施例の場合、処理元の最小値は常に処理先の最大値より大きいから、ステップS513で設定されるとすればブール値は1であるから、ステップS1402での挿入ノードの配列番号設定は、ステップS1401で設定した代表ノード番号に値1を加えたものになる。
以上の挿入するノード対のための配列要素を準備する処理の後、ステップS1405の処理により挿入処理が完了する。
図15は、図13Bに示すステップS1311に対応する処理元の削除処理を説明する図である。
最初のステップS1501において、処理元の探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタを1つ戻す。ここで処理元の探索経路スタックには、図13Aに示すステップS1303あるいは図13Bに示すステップS1314で実行した最小値検索によりノードが格納されており、スタックポインタは、最小値が格納されたリーフノードの直近上位のブランチノードあるいは終端ノード(ルートノードがリーフノードの場合)を指している。
次のステップS1502では、ステップS1501で取り出したノードが終端ノードであるか判定する。該ノードが終端ノードであれば、ステップS1511に移行し、ルートノードの配列番号の指すノード対を削除し、ステップS1512において、ルートノードの配列番号の登録を抹消して「処理元の登録なし」を返す。
ステップS1501で取り出したノードが終端ノードでなければ、ステップS1503に進み、ステップS1501で取り出したノードの代表ノード番号を削除ノードの配列番号として設定する。つまり、削除ノードは最小値が格納されたリーフノードである。
次にステップS1504に進み、処理元の探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタを1つ戻す。ここで処理元の探索経路スタックのスタックポインタは、最小値が格納されたリーフノードの直近上位のブランチノードのさらに直近上位のブランチノードあるいは終端ノード(ブランチノードがルートノードのみのとき)を指している。
次にステップS1505において、該取り出したノードが終端ノードか判定する。
ステップS1504で取り出したノードが終端ノードでなければ、ステップS1506に分岐し、該ノードから代表ノード番号を取り出し、処理元の親ノードの配列番号を格納するエリアに設定するとともに、該親ノードの代表ノード番号を退避してステップS1508に進む。
ステップS1504で取り出したノードが終端ノードであれば、ステップS1507に分岐し、ルートノードの配列番号を、処理元の親ノードの配列番号を格納するエリアに設定するとともに、該親ノードの代表ノード番号を退避してステップS1507aに進む。ステップS1507aでは、スタックポインタのアンダーフローを解消するため、処理元の探索経路スタックのスタックポインタを1つ進め、ステップS1508に進む。
なお、上述のように、ステップS1504で取り出すノードは、削除ノードの2つ上位に位置するブランチノードである。したがって、このブランチノードから取り出した代表ノード番号は削除ノードの直近上位のブランチノードの格納された配列要素を指す配列番号である。すなわち、処理元の親ノードは削除ノードの直近上位のブランチノードである。また、退避した親ノードの代表ノード番号は、削除ノードの配置された配列要素の配列番号である。
ステップS1508においては、削除ノードと対をなすノードの配列番号を対ノードの配列番号を格納するエリアに設定する。
次にステップS1509において、ステップS1508で設定した対ノードの配列番号の指す配列要素の内容を読出し、ステップS1506あるいはステップS1507で設定した処理元の親ノードの配列番号の指す配列要素に格納する。
次にステップS1510において、退避した親ノードの代表ノード番号の指すノード対を削除して「処理元の登録あり」を返す。
上述の処理により、削除ノードと対ノードからなるノード対が削除され、削除ノードの直近上位のブランチノードである親ノードには削除ノードの対ノードの内容が格納されるとともに、該親ノードの配列番号は処理元の親ノードの配列番号を格納するエリアに設定され、図13Bに示すステップS1313で次の最小値検索の検索開始ノードの設定に用いられる。
以上、第2の実施例のツリー分割処理について説明したが、本実施例においても、第1の実施例の場合と同様にインデックスキーの最大値から順に削除を行うことができる。
また、第1の実施例の場合と同様に分割処理の処理フローをツリーの結合処理に用いることが可能である。結合しようとする2つのツリーのうちどちらかを処理元のツリーとし、分割キーを処理元のツリーのインデックスキーの最大値以上あるいは最小値以下として処理元のツリーの削除処理を行い、削除されたノードを処理先のツリーに挿入する処理を行えばよい。
次に本実施形態に係る分割/結合処理の第3の実施例について説明する。
以上説明した第1の実施例と第2の実施例の分割/結合処理は、インデックスキー単位で挿入削除を行うものであった。第3の実施例は、カップルドノードツリーの順序性に着目した、カップルドノードツリーのより大きい、所定の条件を満たす、部分木を単位として挿入削除を行うものである。
図16A及び図16Bは、第3の実施例におけるカップルドノードツリーの分割処理フローを説明する図である。また、図22A〜図22Cは、上記分割処理を実例により説明する図であり、図2Bに例示したカップルドノードツリーと類似したツリーを例示している。図22Aは分割前のツリー構造例を示し、図22Bは最初の分割後のツリー構造例を示し、図22Cは次の分割後のツリー構造例を示している。なお、図22A〜図22Cには、処理元の探索経路スタックとそのスタックポインタが指すノードについても記載されている。
まず図16Aを参照して、本実施例における分割処理の前段である初期処理を説明する。
最初のステップS1601で指定された分割キーを処理元の分割キーとして設定する。第1及び第2の実施例について述べたように、分割キーの指定は、操作者による外部入力の場合もあり得るし、あるコンピュータプログラムの処理結果による場合、遠方からコマンドによる場合等があり得る。指定された分割キーは、処理元の分割キーを保持するメモリ上のエリアに設定される。
図22Aの例示では、分割キーはノード211gのインデックスキー251gの“100011”と等しい。なお、先に述べたように、取得する分割キーは処理元に含まれる必要はないが、後に説明するように、本実施例においては取得された分割キーにより処理元の上限値あるいは下限値を求めて処理元に含まれるインデックスキーを新たな分割キーとする必要がある。したがって、以下の説明では分割キーは処理元に含まれるものとして説明する。
次にステップS1602で、処理元のルートノードを、処理元の検索開始ノードに設定し、ステップS1602aに進み、処理元の探索経路スタックに、終端ノードを格納する。
次にステップS1603で、処理元の検索開始ノード、すなわちステップS1602で検索開始ノードに設定したルートノードから図8Bに示す最小値検索を行い、最小値を求める。
次にステップS1604において、該最小値が分割キーより大であるか判定する。処理元の最小値が最初から分割キーより大であれば分割キー以下のインデックスキーは処理元に含まれないことからここで処理は終了となる。
ステップS1603の最小値検索で得られた最小値が分割キー以下であれば、ステップS1605〜ステップS1606の処理元の初期設定処理とステップS1608〜ステップS1608bの処理先の初期設定処理に進む。
ステップS1605においては、分割キーにより処理元の分割ノードを求める。分割ノードは、分割キーを最大値として含む部分木のうち最大のもの(以下、分割ノードツリーという。)のルートノードである。図22Aの例示では、図22A(a)の(1)に示すように、ノード210fが分割ノードであり、点線で囲まれた部分木が分割ノードツリー291である。ステップS1605の分割ノードを求める処理の詳細は後に図17A及び図17Bを参照して説明する。
次にステップS1606に進み、処理元の探索経路スタックに積まれた終端ノードを終端ノード[1]とする。ステップS1606に進んだ段階では、処理元の探索経路スタックに積まれた終端ノードは後に説明するとおり終端ノード[0]であるが、後に図19を参照して説明する処理元の次の分割ノードを求める処理のため、終端ノード[1]に置き換えておく。
次にステップS1608に進み、ステップS1605で求めた分割ノードを処理先のルートノードに設定して処理先のルートノードとして登録する。次にステップS1608aに進み、処理先の検索開始ノードに処理先のルートノードを設定する。さらにステップS1608bに進み、処理先の探索経路スタックに、終端ノードを格納し、処理先に関する初期処理を完了させて前段の処理を完了し、図16Bに示すステップS1609以降の処理に進む。なおステップS1608の処理の詳細な説明は後に図18Aを参照して行う。
図22Aの例示では、分割処理が開始されたばかりであり、図22Aの(b)に示すように処理先は存在せず登録されていないから、分割ノード210fの内容を処理先として新たに取得されたノード対201iの代表ノード210iに格納して処理先のルートノードに設定し、処理先のルートノードとして登録する。その結果として、図22B(b)に示すように、挿入された分割ノードツリー291からなる処理先のツリーが生成される。
一方、図22B(a)の(1)には、処理元からノード210fを分割ノードとする分割ノードツリー291が削除されたツリー構造が示されており、分割ノード210bをルートノードとする次の分割ノードツリー292が点線で囲まれて示されている。
次に図16Bを参照して、本実施例における分割処理の後段である分割ノードツリーの処理元からの削除と処理先への挿入を説明する。
ステップS1609では、処理元から分割ノードツリーを削除し、該ノードの親ノードを得る。
図22C(b)の例示では、ルートノード210iを挿入位置とし、新たに取得されたノード対201jを介して次の分割ノードツリー292が処理先に挿入されたツリー構造が示されている。また、図22C(a)の(1)には、図22B(a)の(1)に示されたツリー構造から次の分割ノードツリー292が削除された構造が示されている。なおステップS1609における削除処理の詳細は、後に図21を参照して説明する。
次にステップS1610に進み、処理元が登録済みか判定し、登録済みでなければ、処理を終了する。この判定結果が登録済みではないというのは処理元のツリーが全て削除済みであることを意味するから、分割キーが処理元のツリーのインデックスキーの最大値以上である例外的なものである。
ステップS1610の判定結果が登録済みであれば、ステップS1611に進み、処理元を検索して次の分割ノードを求める。ステップS1611における次の分割ノードを求める処理の詳細は、後に図19を参照して説明する。
ステップS1611に続いてステップS1612において、ステップS1611で分割ノードが求まったか判定する。分割ノードが求まらなければ分割処理は終了となる。
分割ノードが求まれば、ステップS1613において、その分割ノードをルートノードとする部分木である分割ノードツリーの最大値を求めて次の分割キーとする。なお、ステップS1613における分割ノードツリーの最大値を求めて次の分割キーとする処理の詳細は、後に図20を参照して説明する。
次にステップS1614において、処理先の検索開始ノードに、処理先の挿入位置のノードを設定する。直前に処理先に挿入された分割ノードツリーに処理先の最小値が含まれていることは明らかであるから、直前に挿入された分割ノード、例えば図22C(b)に例示した処理先においては、ノード210jの配列番号220j(挿入位置)を検索開始ノードの配列番号として設定することにより、ルートノードを検索開始ノードとする場合と比べて最小値検索の処理を軽減することができる。
ステップS1614の後、ステップS1615に進む。
ステップS1615では、処理先の検索開始ノードより図8Bに示す最小値検索によりインデックスキーの最小値を配列から得る。
次にステップS1616において、ステップS1613で設定された次の分割ノードツリーの最大値である分割キーとステップS1615で得た処理先の最小値をビット列比較して上位0ビット目から見た最初の不一致ビット位置を求め、差分ビット位置として設定する。図22Bの例示では、次の分割ノードツリー292の最大値はインデックスキー251c“011010”であり、処理先の最小値はインデックスキー250g“100010”であるから、差分ビット位置は“0”である。
次にステップS1617に進み、処理先のルートノードを挿入位置として処理先に分割ノードツリーを挿入し、ステップS1609に戻る。なおステップS1617における分割ノードツリーの挿入処理の詳細は、後に図18Bを参照して説明する。
以上のステップS1609〜ステップS1617のループ処理において、次の分割ノードツリーの挿入、削除処理及び更なる次の分割ノードを求める処理を、分割ノードが求められなくなるまで繰り返す。
本実施例では上述のように分割ノードツリー単位で削除挿入処理が行われるため、処理ステップ数が削減される。
次に、図17A及び図17Bを参照して図16Aに示すステップS1605における分割ノード(最初の分割ノード)を求める処理を詳細に説明する。
図17Aは、最初の分割ノードを求める処理の前段の処理を説明するフロー図である。
図17Aに示すように、ステップS1701で分割キーを検索キーとして設定し、ステップS1702で処理元のルートノードを検索開始ノードとして設定する。次にステップS1703に進み、処理元の探索経路スタックに終端ノード[0]を格納する。
次にステップS1704に進み、図4Bに示す検索処理を実行し、検索結果として分割キーと等しいインデックスキーを得て前段の処理を終了し、図17Bに示す後段の処理に進む。
後段の処理は図17Bを参照して説明するが、その前に、図22Aを再び参照して、本実施例においては分割キーを処理元に含まれるインデックスキーとしておく必要性について説明する。
いま、図22A(a)の(1)に示す処理元を分割キー“100001”で分割するとする。この分割キーで図17Aに示すステップS1704の検索処理を実行すると、検索結果として得られるインデックスキーはインデックスキー251gの“100011”である。ところが、分割点とすべきインデックスキーは、リーフノード211cに格納された、“100001”を上限とする上限値“011010”あるいはリーフノード210gに格納された、“100001”を下限とする下限値“100010”であり、いずれの場合も分割キー“100001”で検索した結果と一致しないからである。
したがって、分割ノードを求める前に、図10A、図10Bに示す、あるいは図11A、図11Bに示す処理により下限値あるいは上限値を求め、分割キーをその定義に応じて処理元に含まれるインデックスキーとして求めておく必要がある。
次に、最初の分割ノードを求める処理フローの後段の処理を説明する。
図17Bは、最初の分割ノードを求める処理の後段の処理を説明するフロー図である。後段の処理は、処理元の探索経路スタックを遡り、取り出されたノードのノード位置が初めてノード[0]側となるノードを求めて、その代表ノード番号を分割ノードの配列番号として設定するものである。別の言い方をすれば、処理元の探索経路スタックを遡り、最初のノード[0]を分割ノードとするものである。
図17Bに示すように、ステップS1705で探索経路スタックからノードを取り出し、スタックポインタを1つ減らす。ここで最初に取り出されるノードは、処理元がルートノードだけから構成されるような例外的な場合を除いて、分割キーで検索した検索結果のインデックスキーを含むリーフノードの直近上位のブランチノードである。
次にステップS1706へ進み、ノードの代表ノード番号から、この代表ノード番号の指す配列要素に配置されたノードのノード位置を得る。
次にステップS1707において、ステップS1706で得たノード位置がノード[1]側か判定する。判定の結果がノード[1]側であればステップS1705の処理に戻り、ノード[0]側であればステップS1708に進む。
ステップS1708においては、ステップS1705で取り出したノードが終端ノードであるか判定する。判定の結果、終端ノードであれば、ステップS1710に進み、ルートノードの代表ノード番号を分割ノードの配列番号として設定して処理を終了する。
ステップS1708の判定の結果、終端ノードでなければ、ステップS1709に進み、ステップS1705で得たノードの代表ノード番号を分割ノードの配列番号として設定して処理を終了する。
図22Aに示す例では、ルートノード210aを検索開始ノードに設定して分割キー“100011”により検索処理を実行すると検索結果としてのインデックスキー251gが得られ、図22A(a)の(2)に示す探索経路スタック310には終端ノード[0]、ノード210a、211b、210fが順次スタックされる。(ノード210a、210fの代表ノード番号は、それぞれ1加算されている。)
したがって、図17Bに示すステップS1705の最初の処理時には探索経路スタックのスタックポインタはノード210fを指しており、ステップS1706では代表ノード番号220f+1からノード位置1が得られる。したがって、ステップS1707の判定処理の結果、ステップS1705に戻り、次のステップS1707では1つ遡ったノード211bの代表ノード番号221bからノード位置0が判定され、ステップS1708の判定を介してステップS1709に移行し、ステップS1705で取り出されたノード211bの代表ノード番号221b、すなわちノード210fの配列番号221bが分割ノードの配列番号として設定される。そして、処理元の探索経路スタック310のスタックポインタは、図22A(a)の(2)において矢印で示すように、ノード210aを指している。
なお、ステップS1708での判定が終端ノードとなるのは、例えば図22Aに示すノード210fをルートノードとするツリーが処理元で、分割キーが“100011”の場合である。この場合、2回目のステップS1707ではルートノード210fから1つ遡った終端ノード[0]の代表ノード番号からノード位置0が判定され、ステップS1708で終端ノードであると判定されてステップS1710に移行し、ルートノード210fの代表ノード番号220f、すなわちノード210gの配列番号220fが分割ノードの配列番号として設定される。
ここで、さらに分割処理について説明する前に、分割キーは分割ノードツリーの最大値であり、分割ノードツリーは分割キーを最大値とする処理元の部分木のうち最大の部分木、別の表現をすればそのルートノードの弁別ビット位置が最上位である部分木であることを説明する。
今までの説明から明らかなとおり、分割ノードは、分割キーで検索を行ったときの分割キーに至るまでの経路を遡って初めてのノード[0]である。
分割キーをインデックスキーとして含むリーフノードがノード[0]であれば、そのリーフノードが分割ノード自体であり、分割ノードツリーは1つのリーフノードだけから構成される。このリーフノードと対をなすノード[1]側に存在するリーフノードのインデックスキーは、カップルドノードツリーの順序性によって全て分割キーより大きい。したがって、今のケースの場合、分割キーより上位のブランチノードをルートノードとする部分木においては、分割キーは最大値とはなりえないから、分割キーは分割ノードツリーの最大値であり、分割ノードツリーは分割キーを最大値とする処理元の部分木のうち最大のものである。
分割キーをインデックスキーとして含むリーフノードがノード[1]であれば、ツリーをノード[1]側をたどって遡っている限りは、カップルドノードツリーの順序性により、どのノード[1]をルートノードとする部分木においても上記分割キーはこれらの部分木の最大値である。そして、ノード[0]にまで遡ったとき、それ以上上位のノードの下位には当該ノード[0]と対をなすノード[1]以下のノードが存在し、これらのノードには上記分割キーより大きいインデックスキーを含むリーフノードが存在する。
したがって、上記ノード[0]すなわち分割ノードをルートノードとする部分木が、上記分割キーを最大値として含む最大の部分木である。
以下引き続き、分割処理の説明を、図18A以下を参照して行う。
図18Aは、図16Bに示すステップS1608における処理先のルートノードの挿入処理を説明するフロー図である。
ステップS1801において、図16Aに示す処理フローのステップS1605、すなわち図17Bに示すステップS1709あるいはステップS1710で求められた分割ノードの格納された配列要素の配列番号を挿入ノードの配列番号として設定する。
次にステップS1802で、配列から、空のノード対の代表ノードの配列番号を取得する。
次にステップS1803で、ステップS1802で取得した配列番号をノード[0]の配列番号として設定する。
次にステップS1804において、ステップS1801で設定された挿入ノードの配列番号の指す配列要素の内容を読み出して、ステップS1803で設定されたノード[0]の配列番号の指す配列要素に格納する。
最後にステップS1805で、ノード[0]の配列番号を処理先のルートノードの配列番号として登録して、ルートノードの挿入処理を終了する。
図22A及び図22B(b)の例示では、分割ノード210fの格納された配列要素の配列番号221bが挿入ノードの配列番号に設定され、取得された空のノード対201iの代表ノードの配列番号220’ がノード[0]の配列番号として設定される。
そして、配列番号221bが指す配列要素の内容、すなわち分割ノード210fの内容が配列番号220’の指す配列要素すなわちノード210iに格納され、配列番号220’が処理先のルートノードの配列番号として登録される。
図18Bは、図16Bに示すステップS1617におけるルートノード以外の挿入処理を説明するフロー図である。
最初にステップS1811で、図16Bに示す処理フローのステップS1611で求められた分割ノードの格納された配列要素の配列番号を、挿入ノードの配列番号として設定する。このステップS1811は図18Aに示すステップS1801とは、分割ノードが求められた処理ステップがステップS1605ではなくステップS1611である点で異なるだけである。
次にステップS1812において、処理先の挿入位置として、処理先のルートノードの配列番号を設定する。
次のステップS1813〜ステップS1815は、図18Aに示すルートノードの挿入処理のステップS1802〜ステップS1804と同様である。
ステップS1813で、配列から、空のノード対の代表ノードの配列番号を取得し、次にステップS1814で、ステップS1813で取得した配列番号をノード[0]の配列番号として設定し、次にステップS1815において、ステップS1811で設定された挿入ノードの配列番号の指す配列要素の内容を読み出して、ステップS1814で設定されたノード[0]の配列番号の指す配列要素に格納する。
次にステップS1816に進み、ステップS1813で取得した配列番号に値1を加えた値を、ノード[1]の配列番号として設定する。
次にステップS1817において、ステップS1812で設定した処理先の挿入位置の配列番号の指す配列要素の内容を読み出し、ステップS1816で設定したノード[1]の配列番号の指す配列要素に格納する。
最後にステップS1818において、ノード種別にブランチを、弁別ビット位置に図16Bに示すステップS1616で求めた差分ビット位置を、代表ノード番号にステップS1814で設定したノード[0]の配列番号を設定してブランチノードを形成し、ステップS1812で設定した処理先の挿入位置の配列番号の指す配列要素に格納して処理を終了する。
図22B及び図22C(b)の例示では、分割ノード210bの格納された配列要素の配列番号220aが挿入ノードの配列番号に設定され、処理先の挿入位置としてルートノード210iの配列番号220’が設定される。また、取得された空のノード対201jの代表ノードの配列番号220jがノード[0]の配列番号として設定される。
そして、挿入ノードの配列番号220aが指す配列要素の内容、すなわち分割ノード210bの内容をノード[0]の配列番号220jの指す配列要素にノード210jとして格納される。
一方、配列番号220jに1を加えて得た値である配列番号220j+1の指す配列要素すなわちノード211jに、処理先の挿入位置の配列番号220’の指す配列要素すなわち図22B(b)に示すルートノード210iの内容を格納している。
そして図22C(b)に示すルートノード210iの弁別ビット位置230iには、先に図16BのステップS1616に関する例示で説明した分割ノードツリー292の最大値であるインデックスキー251c“011010”と処理先の最小値であるインデックスキー250g“100010”の差分ビット位置
“0”が格納されている。また、代表ノード番号には、ノード[0]の配列番号220jが格納されている。
上記説明から理解されるように、挿入先が生成された後の挿入処理は、挿入先のルートノードの直下にブランチノード同士からなるノード対を挿入し、そのノード対のノード[1]以下に既存の処理先のルートノード以下の部分木を接続し、ノード[0]に分割ノードツリーを接続するものである。この処理により、分割ノードツリーを挿入後の挿入先の順序性が保たれることは明らかである。
図19は、図16Bに示すステップS1611における次の分割ノードを求める処理の処理フローを説明する図である。
ステップS1901において、探索経路スタックからノードを取り出し、探索経路スタックのスタックポインタを1つ減らす。スタックポインタの初期値は、図16Bに示すステップS1609の削除処理終了時のものであり、後に図21を参照した削除処理の説明で明らかになるとおり、分割ノード(削除処理においては削除ノード)の2つ上位のノードを指している。
次にステップS1902に進み、ステップS1901で取り出されたノードの代表ノード番号から、その代表ノード番号が指す配列要素に格納されたノードのノード位置を得る。
次にステップS1903において、ステップS1902で得たノード位置がノード[0]側であるか判定する。ノード[0]側であればステップS1901に戻り、ノード[1]側であればステップS1904に移行する。
ステップS1904では、ノードが終端ノードか判定する。ノードが終端ノードであれば「分割ノードなし」を返す。
ノードが終端ノードでなければ、ステップS1905に進み、S1901で取り出したノードの代表ノード番号から値1を減じて得たノード[0]の配列番号を、分割ノードの配列番号として設定して「分割ノードあり」を返す。
図22A及び図22Bの例示では、次の分割ノードを求める段階では処理元の探索経路スタック310のスタックポインタは、先に述べたように、図22A(a)の(3)に示すとおり、分割ノード210fの2つ上位のルートノード210aを指しており、探索経路スタック310に格納されたルートノード210aの代表ノード番号には220a+1が設定されていることから、ノード位置がノード[1]側となり、それと対を成すノード[0]側に位置するノード210bが次の分割ノードとなり、それの格納されている配列要素の配列番号である220aが分割ノードの配列番号として設定される。
なお、図22A(a)の(3)に示すように、探索経路スタック310に格納された終端ノードは、図16Aに示すステップS1606において、終端ノード[0]から終端ノード[1]に変更されている。
また、図22B及び図22Cの例示では、さらに次の分割ノードを求める段階では処理元の探索経路スタック310のスタックポインタは図22B(a)の(3)に示すように、終端ノード[1]を指しているから、ステップS1903からステップS1904に進み、ステップS1904の判定により分割ノードなしを返す。すなわち、分割ノードの親ノードがルートノードになると次の分割ノードは存在しない。これは、カップルドノードツリーの順序性から見て当然である。
図20は、図16Bに示すステップS1611で求めた分割ノードをルートノードとする分割ノードツリーの最大値を求め次の分割キーとするステップS1613の処理フローを説明する図である。
始めにステップS2001において、処理元の探索経路スタックのスタックポインタの値を退避する。その理由は、図19に示すステップS1901の処理によって分割ノードの2つ上位のノードを指している処理元のスタックポインタの値が、後述のステップS2003の最大値検索によって変動し、後述の図21に示すステップS2104で用いることができなくなるからである。
次にステップS2002において、図19に示すステップS1905で設定された分割ノードの配列番号を検索開始ノードの配列番号として設定する。
そしてステップS2003において、図9Bに示す最大値検索を実行し、インデックスキーの最大値を求める。
次にステップS2004に進み、ステップS2003で得た最大値を分割キーとして設定する。
最後にステップS2005において、ステップS2001で退避した値を処理元の探索経路スタックのスタックポインタの値として復元して処理を終了する。
図22B(a)の例示では(1)に示すように、分割ノード210bを検索開始ノードとして最大値検索を行い、最大値としてインデックスキー251c“011010”が求められている。その際、探索経路スタック310のスタックポインタは退避復元され、図22B(a)の(3)に示す探索経路スタックのスタックポインタは、図22B(a)の(2)に示すノードと同一のノードを指している。
以上、図19及び図20を参照して詳細に説明したところから理解されるように、図16Bに示すステップS1611で求めた次の分割ノードとステップS1613で求めた次の分割キーの関係は、先に説明した図16Aに示すステップS1601で設定された分割キーとステップS1605で求めた分割ノード、あるいは分割ノードツリーの関係と同様である。
上記ステップS1613で求めた次の分割キーは、ステップS1611で求めた次の分割ノードをルートノードとする分割ノードツリーの最大値である。また、ステップS1611で求めた次の分割ノードはノード[0]であるから、それより上位のノードをルートノードとする部分木は、ステップS1613で求めた次の分割キーより大きいインデックスキーを格納したリーフノードを含むことも、カップルドノードツリーの順序性により明らかである。
図21は、図16Bに示すステップS1609における分割ノードツリーの削除処理の処理フローを説明する図である。同じ削除処理で類似している点もあるが、図15に示す削除処理は削除キーの格納されたリーフノードである削除ノードの削除であるのに対して、図21に示すものは基本的にはブランチノードである分割ノードの削除であり、処理元からは該分割ノードをルートノードとする分割ブランチノードツリーが削除される。
まずステップS2101において、図16Aに示すステップS1605もしくは図16Bに示すステップS1611で求めた分割ノードの配列番号を処理元の削除ノードの配列番号として設定する。
次にステップS2102において、ステップS2101で設定された削除ノードの配列番号が、処理元のルートノードの配列番号と一致するか判定する。削除ノードの配列番号が、処理元のルートノードの配列番号と一致するときは、ステップS2111に進み、処理元のルートノードの配列番号の指すノード対を削除し、次にステップS2112で処理元のルートノードの配列番号の登録を抹消し、「処理元の登録なし」を返して処理を終了する。
ステップS2102の判定処理の結果、削除ノードの配列番号が処理元のルートノードの配列番号と一致しないときは、ステップS2104に進み、処理元の探索経路スタックからスタックポインタの指すノードを取り出す。なお、該スタックポインタは、図17Bに示すステップS1705あるいは図19に示すステップS1901の処理により、分割ノードの2つ上位であるノードが格納されている。
次にステップS2105において、該取り出したノードが終端ノードか判定する。該取り出したノードが終端ノードでないと判定されると、ステップS2106に進み、親ノードの配列番号として該取り出したノードの代表番号を設定するとともに、親ノードの代表ノード番号を退避してステップS2108に進む。
ステップS2105で、ステップS2104で取り出したノードが終端ノードであると判定されると、ステップS2107に進み、親ノードの配列番号としてルートノードの配列番号を設定するとともに、親ノードの代表ノード番号を退避してステップS2108に進む。
ステップS2108では、ステップS2101で配列番号の設定された削除ノードと対をなすノードの配列番号を求め、対ノードの配列番号として設定する。
次にステップS2109において、ステップS2108で設定した対ノードの配列番号の指す配列要素の内容を読み出し、ステップS2106あるいはステップS2107で設定した親ノードの配列番号の指す配列要素に格納する。
最後にステップS2110において、ステップS2106あるいはステップS2107で退避した親ノードの代表ノード番号の指すノード対を削除し、「処理元の登録あり」を返して処理を終了する。
図22Aの(1)の例示では、分割ノード210fの配列番号221bが、図示しない削除ノード設定エリアに削除ノード210fの配列番号として設定され、また図22Aの(3)に示すように、探索経路スタックからノード210aを取り出す。この際、図に示すように、スタックポインタの更新は行わない。そして、図21に示すステップS2106において、親ノードの配列番号に代表ノード番号220a+1を設定するとともに、親ノード211bの代表ノード番号221bを退避する。
次に対ノードの配列番号に削除ノード210fと対をなすノード211fの配列番号221b+1を設定し、処理元の親ノードの配列番号220a+1が指す配列要素に、対ノード211fの配列番号221b+1の指す配列要素の内容、すなわちノード211fの内容を格納する。その結果が、図22Bの(1)のノード211bに示されている。
同様に、図22Bの(1)の例示では、分割ノード210bの配列番号220aが、図示しない削除ノード設定エリアに削除ノード210bの配列番号として設定され、また図22Bの(3)に示すように、探索経路スタックから終端ノード[1]を取り出す。
したがって、図21に示すステップS2105の判定結果は「はい」になり、親ノードの配列番号にルートノード210aの配列番号220を設定するとともに、親ノード210aの代表ノード番号220aを退避する。
次に対ノードの配列番号に削除ノード210bと対をなすノード211bの配列番号220a+1を設定し、処理元の親ノードの配列番号220が指す配列要素に、対ノード211bの配列番号220a+1の指す配列要素の内容、すなわちノード211bの内容を格納する。その結果が、図22cの(1)のノード210aに示されている。
以上により、第3の実施例によるカップルドノードツリーの分割処理について詳細に説明したが、第3の実施例によれば、分割ノードツリー単位で分割処理が行われる。すなわち、分割ノードを処理元から分離し、分割ノードの対ノードを親ノードに複写することにより分割ノードツリーが処理元から削除され、分割ノードを処理先に挿入することにより分割ノードツリーの挿入が完成する。
したがって、同じ配列を用いている限りは、分割ノード以外のノードについての処理は不要であり、実施例2の場合よりも処理の実行ステップ数がさらに少なくてすむ。
次に分割処理と同様に部分木単位で処理を行う第3の実施例によるカップルドノードツリーの結合処理を説明する。本実施例の結合処理は、第1の実施例及び第2の実施例の結合処理と大きく異なり、第1の実施例及び第2の実施例の結合処理がインデックスキー単位、言い換えればノード単位で結合処理を行うものであるのに対して、所定の条件を満たす部分木単位で処理元から分割して処理先に結合するものである。第1の実施例及び第2の実施例の結合処理では分割キーを選択することにより分割処理をそのまま適用できたのに対して、本実施例のように部分木単位で結合処理を行おうとすると、単純に分割処理を適用することができない。
それは、処理元及び処理先はそれぞれの内部に格納されたインデックスキーの差分ビット位置に応じた構造を有しており、処理元自体を分割ノードツリーとしてそのまま処理先に挿入することができるとは限らないからである。
図23A及び図23Bは、第3の実施例におけるカップルドノードツリーの結合処理フローを説明する図である。以下の説明では、処理先のインデックスキーは処理元のインデックスキーより大きいとするが、その逆でも同様に処理が可能であることは、下記の説明から容易に理解されるものである。
図26A〜図26Cは、上記結合処理を実例により説明する図であり、図2Bに例示したカップルドノードツリーの部分木と類似したツリーが例示されている。
図26Aは結合処理開始前の処理元と処理先のツリーの構造例を示す図である。図26Aの(a)には処理元が例示され、その配列番号の符号220a+1が付された分割結合ノードとそれをルートノードとする部分木であり、結合処理の単位となる部分木である分割結合ノードツリー293が示されている。以後、ノードを示す符号を、探索経路スタックにスタックされている直近上位のノードの代表ノード番号で表すことがある。
図26Aの(b)には処理先が例示され、結合位置となるノードがその配列番号の符号221fを付して示されている。また、図26Aには、処理元の最大値がインデックスキー251gの“101001”であること、処理先の最小値がインデックスキー250hの“101011”であることも示されている。
図26Bは、図26Aに示す分割結合ノードツリー293を処理先に挿入し、処理元から削除したツリー構造を示す図である。図26Bの(a)には処理元の次の分割結合ノードツリー294が点線で囲われて示され、最大値がインデックスキー251dの“011010”であることが示されている。図26Bの(b)には、処理先の結合された分割結合ノードツリー293、結合処理により追加されたノード対201kとノード221fのリンク関係がそれぞれ点線で囲われて示され、次の結合位置がノード220’であることが示されている。
図26Cは、図26Bに示す分割結合ノードツリー294を処理先に挿入し、処理元から削除したツリー構造を示す図である。図26Bの(a)に示す処理元の次ぎの分割結合ノード220がルートノードであるため、処理元のルートノードは削除され、図26Cの(a)には何も表示されていない。図26Cの(b)には、処理先の結合された分割結合ノードツリー294、結合処理により追加されたノード対201mとノード220’のリンク関係がそれぞれ点線で囲われて示されている。
以下、図23A及び図23B及び図26A〜図26Cを参照して本実施例の結合処理の概要を説明する。
図23Aは、本実施例の結合処理における初期処理の処理フローを説明する図である。図に示すように、ステップS2301において、処理元の探索経路スタックに終端ノードを格納する。次に、ステップS2302において、処理先の探索経路スタックに終端ノードを格納する。
次にステップS2303に進み、処理元のルートノードを処理元の検索開始ノードに設定する。そして、次のステップS2304で、処理先のルートノードを処理先の検索開始ノードに設定して初期処理を終了し、図23Bに示すステップS2307に進む。
図23Bは、処理元をすべて処理先に結合するまでのループ処理を説明する図である。
図23Bに示すように、ステップS2307において、処理元の検索開始ノードから図9Bに示す検索処理により、処理元のインデックスキーの最大値を求め、次にステップS2309において、処理先の検索開始ノードから図8Bに示す検索処理により、処理先のインデックスキーの最小値を求める。
次にステップS2310において、ステップS2307で求めた最大値とステップS2309で求めた最小値のビット列比較を行い、上位0ビット目から見た最初の不一致ビットの位置を求め、差分ビット位置に設定する。
先に述べたように、図26Aの例示では、処理元の最大値は“101001”であり、処理先の最小値は“101011”であるから、差分ビット位置“4”が求められる。また、図26Bの例示では、(a)に示す処理元の最大値は“011010”であり(b)に示す処理先の最小値は“101000”であるから、差分ビット位置は“0”である。なお、処理元にも処理先にも、弁別ビット位置がこの差分ビット位置と等しいブランチノードは存在しない。
なぜならば、処理元の最大値より処理先の最小値が大きいことから処理元の最大値の差分ビット位置のビット値は0であり、もし、処理元のブランチノードに弁別ビット位置が差分ビット位置と等しいものがあるとすると処理元の最大値がノード[0]となり、最大値であることと矛盾するからである。処理先についても同様である。
なお、以下の説明では、このステップS2310で求めた差分ビット位置を単に差分ビット位置ということがある。
次にステップS2311で、ステップS2310で求めた差分ビット位置により、処理元の分割結合ノードを求める。図26Aの例示では、図26Aの(a)処理元に示すように、分割結合ノード220a+1が求められている。また、図26Bの例示では、図26Bの(a)処理元に示すように、次の分割結合ノード220が求められている。この処理の詳細は、後に図24を参照して説明する。
次にステップS2312に進み、差分ビット位置により、ステップS2311で求めた分割結合ノードを挿入するための処理先の結合位置を求める。図26Aの例示では、図26Aの(b)処理先に示すように、結合位置221fが求められている。また、図26Bの例示では、図26Bの(b)処理先に示すように、結合位置220’が求められている。この処理の詳細は、後に図25を参照して説明する。
次にステップS2313において、ステップS2312で求めた結合位置にステップS2311で求めた分割結合ノードを挿入する。この処理は、図18Bを参照して説明をした挿入処理において、ステップS1801の挿入ノードの配列番号としてステップS2311で求めた分割結合ノードの配列番号を設定し、ステップS1802の処理先の挿入位置にステップSS2312で求めた結合位置の配列番号を設定して該挿入処理を実行することにより実現される。
図26A及び図26Bの例示では、図18BのステップS1811において分割結合ノード220a+1の配列番号220a+1が挿入ノード設定エリアに設定され、ステップS1812において挿入位置設定エリアに結合位置221fの配列番号221fが設定される。次にステップS1813において、空きのノード対201kが取得され、その配列番号220kがステップS1814においてノード[0]の配列番号として設定される。
そして、ステップS1815において、挿入ノード設定エリアに設定された配列番号220a+1が指す配列要素の内容、すなわち分割結合ノード211bの内容を読み出して、ノード[0]の配列番号として設定されている配列番号220kの指す配列要素、すなわちノード210kに格納する。
さらにステップS1816において、配列番号220kに1を加えた値である220k+1をノード[1]の配列番号として設定する。そしてステップS1817で挿入位置として設定されている配列番号221fの指す配列要素、すなわちノード210hの内容を読み出し、ノード[1]の配列番号として設定された配列番号220k+1の指す配列要素、すなわちノード211kに格納する。
最後にステップS1818において、挿入位置として設定されている配列番号221fの指す配列要素、すなわちノード210hの位置に、ノード種別に0、弁別ビット位置に図23BのステップS2310で求めた差分ビット位置4、代表ノード番号にノード[0]の配列番号として設定されている配列番号220kを設定して新たなブランチノードを生成し、図26Bの(b)に示す結合後の処理先の構造が得られている。
また、図26B及び図26Cの例示では、図26Bの(a)に示す処理元の最大値“011010”と(b)に示す処理先の最小値“101000”の差分ビット位置が“0”であることから、次の分割結合ノードとしてノード220が設定される。図18BのステップS1811において次の分割結合ノード220の配列番号220が挿入ノード設定エリアに設定され、ステップS1812において挿入位置設定エリアに結合位置220’の配列番号220’が設定される。次にステップS1813において、図26Cの(b)に示すように、空きのノード対201mが取得され、その配列番号220mがステップS1814においてノード[0]の配列番号として設定される。
そして、ステップS1815において、挿入ノード設定エリアに設定された配列番号220が指す配列要素の内容、すなわち次の分割結合ノード210aの内容を読み出して、ノード[0]の配列番号として設定されている配列番号220mの指す配列要素、すなわちノード210mに格納する。
さらにステップS1816において、配列番号220mに1を加えた値である220m+1をノード[1]の配列番号として設定する。そしてステップS1817で挿入位置として設定されている配列番号220’の指す配列要素、すなわちノード210fの内容を読み出し、ノード[1]の配列番号として設定された配列番号220m+1の指す配列要素、すなわちノード211mに格納する。
最後にステップS1818において、挿入位置として設定されている配列番号220’の指す配列要素、すなわちノード210fの位置に、ノード種別に0、弁別ビット位置に図23BのステップS2310で求めた差分ビット位置“0”、代表ノード番号にノード[0]の配列番号として設定されている配列番号220mを設定して新たなブランチノードを生成し、図26Bの(c)に示す結合後の処理先の構造が得られている。
次に図23Bによるツリー結合処理の説明に戻ると、ステップS2314において、分割ノードに、ステップS2311で求めた分割結合ノードを設定し、ステップS2315に進んで処理元より削除ノードを削除し、該ノードの親ノードを得る。ステップS2315の処理は、図21を参照して説明した削除処理を実行することにより実現される。この削除処理は、ステップS2314において分割ノードとしてステップS2311で求めた分割結合ノードを設定してから実行されるので、分割ノードを分割結合ノードと読み替えて実行したものに相当する。
次にステップS2316に進み、処理元が登録されているか判定する。登録されていればステップS2317に進み、登録されていなければ結合処理は完了したので処理を終了する。
ステップS2317では、ステップS2315で得た削除ノードの親ノードを処理元の検索開始ノードに設定してステップS2307に戻る。
図26A及び図26Bの例示では、処理元の分割結合ノード220a+1を求める処理が終了すると処理元の探索経路スタックのスタックポインタは終端ノードを指しているので、図23Bに示すステップS2315で呼び出される図21に示す削除処理のステップS2105の判定処理は「はい」となり、ステップS2107に進む。ステップS2107で親ノードの配列番号にルートノード210aの配列番号220が設定され、代表ノード番号220aが退避される。削除ノードには分割結合ノード220a+1、対ノードにはノード210bが設定される。そして、配列番号220の配列要素にノード210bの内容が格納され、代表ノード番号220aが指すノード対201bが削除されて図26Bの(a)に示す処理先となる。
図26B及び図26Cの例示では、処理元の分割結合ノード220を求める処理が終了すると、図23Bに示すステップS2315で呼び出される図21に示す削除処理のステップS2102の削除ノードはルートノードかの判定処理は「はい」となり、ステップS2111に進む。ステップS2111でルートノードの配列番号220が指すノード対201aが削除され、ルートノードの配列番号の登録が抹消されて、図26Cの(a)に示すように、処理先は消滅する。
次に、本実施例の結合処理における処理元の分割結合ノードを求める処理を説明する。分割結合ノードは、処理元がルートノードだけであるという例外を除けば、最大値検索でたどったブランチノードのうち、弁別ビット位置が図23Bに示すステップS2310で求めた差分ビット位置より下位であるもののうち最上位であるブランチノードである。
分割結合ノードをルートノードとする処理元の部分木を分割結合ノードツリーということにすると、本実施例の結合処理は、分割結合ノードツリー単位で結合処理を行うものである。
図24は、図23Bに示すステップS2311の処理元の分割結合ノードを求める処理フローを説明する図である。なお、分割結合ノードを求める処理の開始時には、処理元の探索経路スタックのスタックポインタは図23Bに示すステップS2307における最大値検索の結果、インデックスキーの最大値を格納したリーフノードの直近上位のノードを指している。
図24に示すように、ステップS2401において、処理元の探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタを1つ戻し、ステップS2402に進む。
ステップS2402では、ステップS2401で取り出したノードから弁別ビット位置を取得する。
次にステップS2403において、ステップS2402で取得した弁別ビット位置が差分ビット位置の値より小さいか(上位の位置関係か)を判定する。小さくなければステップS2401に戻り、小さければステップS2404に進む。先に述べたように、上述の弁別ビット位置と差分ビット位置が等しいことはない。
ステップS2404においては、ステップS2401で取り出したノードが終端ノードであるか判定する。終端ノードでなければステップS2405に進み、処理元の分割結合ノードの配列番号として、ステップS2401で取り出したノードの代表ノード番号を設定して処理を終了する。
ステップS2404の判定結果が終端ノードであれば、ステップS2406に進み、処理元の分割結合ノードの配列番号として、ルートノードの配列番号を設定して処理を終了する。
上記処理を図26A及び図26Bを参照して説明すると以下のとおりである。
図26Aの(a)処理元の例示においては、最大値検索の結果、図示しない探索経路スタックのスタックポインタがノード211bを指しているので弁別ビット位置“5”が取り出され、差分ビット位置が“4”であることからステップS2403の判定は「いいえ」となり、ステップS2401からの処理を繰り返して、ルートノード210aまで至り、ルートノード210aの弁別ビット位置が“0”であって差分ビット位置より上位であるからステップS2403の判定処理でステップS2404に分岐し、ステップS2405の処理により分割結合ノード220a+1が求められる。(探索経路スタック上のルートノード210aの代表ノード番号は、最大値検索を実行したのであるから220a+1に更新されている。)
図26Bの例示においては、削除ノード211bの親ノードであるルートノード210aからの処理元の最大値検索により、最大値“011010”が求められ、処理先の最小値は図26Bの(b)に示すように“101000”であるから、差分ビット位置“0”が設定される。処理元の探索経路スタックのスタックポインタはノード211cを指しているので弁別ビット位置“2”が取り出され、差分ビット位置が“0”であることからステップS2403の判定は「いいえ」となり、ステップS2401からの処理を繰り返して、ルートノード210aまで至り、ルートノード210aの弁別ビット位置が“0”であって差分ビット位置より小さくないから、さらにステップS2401からの処理を繰り返して、終端ノードまで至り、終端ノードの弁別ビット位置が“−1”であるからステップS2403の判定処理でステップS2404に分岐し、ステップS2404の判定処理でステップS2406に分岐し、ステップS2406の処理により次の分割結合ノード220が求められる。
次に、処理先の結合位置を求める処理を説明する。結合処理後の処理先には処理元のインデックスキーの最大値を格納したリーフノードが挿入されることから、差分ビット位置と等しい値の弁別ビット位置を持つブランチノードが新しく存在する。すなわち、差分ビット位置と等しい値の弁別ビット位置を持つブランチノードを最小値検索でたどった経路中に挿入することになるが、この挿入位置を処理先の結合位置とする。
カップルドノードツリーにおいては、下位のブランチノードの弁別ビット位置は上位のブランチノードの弁別ビット位置より下位であることから、差分ビット位置より直近上位の弁別ビット位置を持つブランチノードの子ノードの位置かあるいは例外的に上位の弁別ビット位置を持つブランチノードがなければルートノードが結合位置となる。
結合位置に挿入されたブランチノードの子ノード対のノード[1]側には結合前の処理先のインデックスキーの最小値を格納したリーフノードが存在し、ノード[0]は分割結合ノードである。
図25は、上記処理先の結合位置を求める処理フローを説明する図である。図25に示すように、処理先の結合位置を求める処理フローは、図24に示す処理元の分割結合ノードを求める処理フローと同じ構造である。図25の処理フローは処理先についてのものであり、求めるものは結合位置であることで異なるだけである。なお、処理先の結合位置を求める処理の開始時には、処理先の探索経路スタックのスタックポインタは図23Bに示すステップS2309における最小値検索の結果、インデックスキーの最小値を格納したリーフノードの直近上位のノードを指している。
図25に示すように、ステップS2501において、処理先の探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタを1つ戻し、ステップS2502に進む。
ステップS2502では、ステップS2501で取り出したノードから弁別ビット位置を取得する。
次にステップS2503において、ステップS2502で取得した弁別ビット位置が差分ビット位置の値より小さいか(上位の位置関係か)を判定する。小さくなければステップS2501に戻り、小さければステップS2504に進む。先に述べたように、上述の弁別ビット位置と差分ビット位置が等しいことはない。
ステップS2504においては、ステップS2501で取り出したノードが終端ノードであるか判定する。終端ノードでなければステップS2505に進み、処理先の結合位置の配列番号として、ステップS2501で取り出したノードの代表ノード番号を設定して処理を終了する。
ステップS2504の判定結果が終端ノードであれば、ステップS2506に進み、処理先の結合位置の配列番号として、ルートノードの配列番号を設定して処理を終了する。
上記処理を図26A及び図26Bを参照して説明すると以下のとおりである。
図26Aの(b)処理先の例示においては、最小値検索の結果、図示しない探索経路スタックのスタックポインタがノード210fを指しているので弁別ビット位置“3”が取り出され、差分ビット位置が“4”であることから、ステップS2503の判定は「はい」になり、ステップS2504からステップS2505に分岐し、ステップS2505の処理によりノード210fの代表ノード番号221fが結合位置の配列番号として設定される。
図26Bの例示においては、処理元の最大値“011010”と処理先の最小値“101000”の差分ビット位置が“0”であることから探索経路スタックを遡ると、終端ノードまで至り、ステップS2504において、終端ノードであると判定されてステップS2506に分岐し、ルートノード210fの配列番号220’が次の結合位置の配列番号として求められる。
以上により、第3の実施例によるカップルドノードツリーの結合処理について詳細に説明しが、第3の実施例によれば、分割結合ノードツリー単位で結合処理が行われる。すなわち、分割結合ノードを処理元から分離し、分割結合ノードの対ノードを親ノードに複写することにより分割結合ノードツリーが処理元から削除され、分割結合ノードを処理先に結合することにより分割結合ノードツリーの結合が完成する。
したがって、同じ配列を用いている限りは、分割結合ノード以外のノードについての処理は不要であり、実施例2の場合よりも処理の実行ステップ数がさらに少なくてすむ。
以上本発明を実施するための最良の形態について詳細に説明したが、本発明の実施の形態はそれに限ることなく種々の変形が可能であることは当業者に明らかである。
次に、図27A及び図27Bを参照してカップルドノードツリーに格納されたインデックスキーを昇順に取り出す処理について説明する。
図27Aは、カップルドノードツリーの任意の部分木に格納されたインデックスキーを昇順に取り出す処理を説明するフロー図である。インデックスキーを昇順に取り出す処理は、ノード対をなすノードのうちノード[0]側及びツリーの深さを優先させてノードから順次リーフノードをたどり、各リーフノードからインデックスキーを取り出していくことに相当する。
図27Aに示すように、ステップS2701で検索開始ノードを設定し、ステップS2702で探索経路スタックに終端ノードを格納してステップS2703において、図8Bに示す最小値検索を実行し、ステップS2704に進む。
ステップS2704では、ステップS2703あるいは後述のステップS2711で得た最小値であるインデックスキーを取り出す。
次にステップS2705で、探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタの値を1つ減らす。最初のステップS2705での探索経路スタックの状態は、ステップS2703の最小値検索を実行したときの状態である。
次にステップS2708で、ステップS2705で取り出したノードが終端ノードであるか判定する。該ノードが終端ノードであれば、インデックスキーの取り出しが終了したのであるから処理を終了する。
ステップS2708での判定が「終端ノードではない」であれば、ステップS2709に進み、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS2705で取り出したノードの代表ノード番号を設定する。
さらにステップS2710で、検索開始ノードのノード位置として、値“1”を設定してステップS2711に進み、図8Bに示す最小値検索を実行し、インデックスキーの最小値を取得し、ステップS2704の最小値であるインデックスキーを取り出す処理に戻る。
上記ステップS2704からステップS2711までのループ処理をステップS2708での判定が「はい」に至るまで繰り返すことにより、検索開始ノードをルートノードとする部分木のインデックスキーが昇順にとりだされる。
図27Bは、図27Aのフロー図により説明したインデックスキーを昇順に取り出す処理例を説明する図である。カップルドノードツリーは図2Bに例示したものであり、検索開始ノードはルートノード210aである。図27Bの(1)〜(8)において、インデックスキーを昇順に取り出す処理を実行する各段階における探索経路スタック310の状態及び取り出されるインデックスキーを示している。
図27B(1)は、ルートノード210aを検索開始ノードとして最小値検索処理まで実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。スタックポインタの指す位置は、終端ノードからノード210bになっている。ここでは、ノード210bの代表ノード番号220bの指すノードはリーフノード210cであるため、このノード210cのインデックスキー
“000111”が取り出され、スタックポインタの指す位置は1つ減ってノード210aとなる。そして、最小値検索における代表ノード番号に代表ノード番号220bを、ノード位置に値“1”を設定し、次の最小値検索を実行する。つまり、次の検索開始ノードは、代表ノード番号220bの指すノード対201cのノード[1]であるノード211cとなる。
図27B(2)は、ノード211cを検索開始ノードとして最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最小値検索の結果、探索経路スタック310にはノード210aの上にノード211cとノード210dが格納されている。ここでは、ノード210dの代表ノード番号220dの指すノード210eはリーフノードであるため、このノード210eのインデックスキー
“010010”が取り出され、スタックポインタの指す位置は1つ減ってノード211cとなる。そして、最小値検索における代表ノード番号に代表ノード番号220dを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図27B(3)は、代表ノード番号に代表ノード番号220dを、ノード位置に値“1”を設定して最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。ここでは、配列から取り出されたノード211eはリーフノードであるため、このノード211eのインデックスキー“010011”
が取り出され、スタックポインタの指す位置は1つ減ってノード210aとなる。そして、最小値検索における代表ノード番号に代表ノード番号221cを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図27B(4)は、代表ノード番号に代表ノード番号221cを、ノード位置に値“1”を設定して最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。ここでは、配列から取り出されたノード211dはリーフノードであるため、このノードのインデックスキー“011010”
が取り出され、スタックポインタの指す位置は1つ減って終端ノードとなる。そして、最小値検索における代表ノード番号に代表ノード番号220aを、ノード位置に値“1”を設定し、次の最小値検索を実行する。つまり、次の検索開始ノードはノード211bとなる。
図27B(5)は、ノード211bを検索開始ノードとして最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最小値検索の結果、探索経路スタック310には終端ノードの上にノード211bとノード210fが格納されている。ここでは、ノード210fの代表ノード番号220fの指すノード210gはリーフノードであるため、このノード210gのインデックスキー“100010”
が取り出され、スタックポインタの指す位置は1つ減ってノード211bとなる。そして、最小値検索における代表ノード番号に代表ノード番号220fを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図27B(6)は、代表ノード番号に代表ノード番号220fを、ノード位置に値“1”を設定して最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。ここでは、配列から取り出されたノード211gはリーフノードであるため、このノードのインデックスキー“100011”
が取り出され、スタックポインタの指す位置は1つ減って終端ノードとなる。そして、最小値検索における代表ノード番号にノード211bの代表ノード番号221bを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図27B(7)は、代表ノード番号に代表ノード番号221bを、ノード位置に値“1”を設定して最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最小値検索の結果、ノード211fが終端ノードの上に格納されている。ここでは、ノード211fの代表ノード番号221fの指すノード210hはリーフノードであるため、このノード210hのインデックスキー“101011”
が取り出され、スタックポインタの指す位置は1つ減って終端ノードとなる。そして、最小値検索における代表ノード番号に代表ノード番号221fを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図27B(8)は、代表ノード番号に代表ノード番号221fを、ノード位置に値“1”を設定して最小値検索を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示す。ここでは、配列から取り出されたノード211hはリーフノードであるため、このノード211hのインデックスキー“101100”が取り出される。そして、図27Aに示すステップS2708で、前回ステップS2705で探索経路スタック310から取り出されたノードが終端ノードであると判断され、処理を終了する。
上述の説明から理解されるように、最大値であるインデックスキーが最小値検索で得られるときには、探索経路スタックから最大値であるインデックスキーを格納したリーフノードの直近上位のブランチノードが取り出されており、次に新たにノードが終端ノードの上に格納されることはないから、次の最小値検索に進む前に図27Aに示すステップS2705で終端ノードが取り出され、ステップS2708で終端ノードであることが判定されて処理が終了する。
次に、図28A及び図28Bを参照してカップルドノードツリーに格納されたインデックスキーを降順に取り出す処理について説明する。このインデックスキーの降順取り出し処理は、先に図27A及び図27Bを参照して説明した昇順取り出し処理といわば双対の関係にあり、最小値検索に変えて最大値検索を行い、ノード位置を反転させたものに相当する。
図28Aは、カップルドノードツリーの任意の部分木に格納されたインデックスキーを降順に取り出す処理を説明するフロー図である。インデックスキーを降順に取り出す処理は、ノード対をなすノードのうちノード[1]側及びツリーの深さを優先させてノードから順次リーフノードをたどり、各リーフノードからインデックスキーを取り出していくことに相当する。
図28Aに示すように、ステップS2801で検索開始ノードを設定し、ステップS2802で探索経路スタックに終端ノードを格納してステップS2803において、図9Bに示す最大値検索を実行し、ステップS2804に進む。
ステップS2804では、ステップS2803あるいは後述のステップS2811で得た最大値であるインデックスキーを取り出す。
次にステップS2805で、探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタの値を1つ減らす。最初のステップS2805での探索経路スタックの状態は、ステップS2803の最大値検索を実行したときの状態である。
次にステップS2808で、ステップS2805で取り出したノードが終端ノードであるか判定する。該ノードが終端ノードであれば、インデックスキーの取り出しが終了したのであるから処理を終了する。
ステップS2808での判定が「終端ノードではない」であれば、ステップS2809に進み、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS2805で取り出したノードの代表ノード番号から1を減じた値を設定する。
さらにステップS2810で、検索開始ノードのノード位置として、値“0”を設定してステップS2811に進み、図9Bに示す最大値検索を実行し、インデックスキーの最大値を取得し、ステップS2804の最大値であるインデックスキーを取り出す処理に戻る。
上記ステップS2804からステップS2811までのループ処理をステップS2808での判定が「はい」に至るまで繰り返すことにより、検索開始ノードをルートノードとする部分木のインデックスキーが降順にとりだされる。
図28Bは、図28Aのフロー図により説明したインデックスキーを降順に取り出す処理例を説明する図である。カップルドノードツリーは図2Bに例示したものであり、検索開始ノードはルートノード210aである。図28Bの(1)〜(8)において、インデックスキーを降順に取り出す処理を実行する各段階における探索経路スタック310の状態及び取り出されるインデックスキーを示している。
図28B(1)は、ルートノード210aを検索開始ノードとして最大値検索処理まで実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。スタックポインタの指す位置は、終端ノードからノード211fになっている。ここでは、ノード211fの代表ノード番号221f+1の指すノード211hはリーフノードであるため、このノード211hのインデックスキー
“101100”が取り出され、スタックポインタの指す位置は1つ減ってノード211bとなる。そして、最大値検索における代表ノード番号に代表ノード番号221f+1から1を減じた値である221fを、ノード位置に値“0”を設定し、次の最大値検索を実行する。
図28B(2)は、代表ノード番号に代表ノード番号221fを、ノード位置に値“0”を設定して最大値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。ここでは、配列から取り出されたノード210hはリーフノードであるため、このノード210hのインデックスキー
“101011”が取り出され、スタックポインタの指す位置は1つ減ってノード210aとなる。そして、最大値検索における代表ノード番号に代表ノード番号221bを、ノード位置に値“0”を設定し、次の最大値検索を実行する。
図28B(3)は、代表ノード番号に代表ノード番号221bを、ノード位置に値“0”を設定して最大値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最大値検索の結果、探索経路スタック310には、ノード210aの上にノード210fが格納されている。ここでは、ノード210fの代表ノード番号220f+1が指すノード211gはリーフノードであるため、このノード211gのインデックスキー“100011” が取り出され、スタックポインタの指す位置は1つ減ってノード210aとなる。そして、最大値検索における代表ノード番号に代表ノード番号220fを、ノード位置に値“0”を設定し、次の最大値検索を実行する。
図28B(4)は、代表ノード番号に代表ノード番号220fを、ノード位置に値“0”を設定して最大値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。ここでは、配列から取り出されたノード210gはリーフノードであるため、このノード210gのインデックスキー“100010”
が取り出され、スタックポインタの指す位置は1つ減って終端ノードとなる。そして、最大値検索における代表ノード番号に代表ノード番号220aを、ノード位置に値“0”を設定し、次の最大値検索を実行する。つまり、次の検索開始ノードはノード210bとなる。
図28B(5)は、ノード210bを検索開始ノードとして最大値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最大値検索の結果、探索経路スタック310には終端ノードの上にノード210bとノード211cが格納されている。ここでは、ノード211cの代表ノード番号221c+1の指すノード211dはリーフノードであるため、このノード211dのインデックスキー“011010”
が取り出され、スタックポインタの指す位置は1つ減ってノード210bとなる。そして、最大値検索における代表ノード番号に代表ノード番号221cを、ノード位置に値“0”を設定し、次の最大値検索を実行する。
図28B(6)は、代表ノード番号に代表ノード番号221cを、ノード位置に値“0”を設定して最大値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最大値検索の結果、探索経路スタック310にはノード210bの上にノード210dが格納されている。ここでは、ノード210dの代表ノード番号220d+1の指すノード211eはリーフノードであるため、このノード211eのインデックスキー“010011”
が取り出され、スタックポインタの指す位置は1つ減ってノード210bとなる。そして、最大値検索における代表ノード番号にノード210dの代表ノード番号220dを、ノード位置に値“0”を設定し、次の最大値検索を実行する。
図28B(7)は、代表ノード番号に代表ノード番号220dを、ノード位置に値“0”を設定して最大値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。ここでは、配列から取り出されたノード210eはリーフノードであるため、このノード210eのインデックスキー“010010”
が取り出され、スタックポインタの指す位置は1つ減って終端ノードとなる。そして、最大値検索における代表ノード番号に代表ノード番号220bを、ノード位置に値“0”を設定し、次の最大値検索を実行する。
図28B(8)は、代表ノード番号に代表ノード番号220bを、ノード位置に値“0”を設定して最大値検索を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示す。ここでは、配列から取り出されたノード210cはリーフノードであるため、このノード210cのインデックスキー“000111”が取り出される。そして、図28Aに示すステップS2808で、前回ステップS2805で探索経路スタック310から取り出されたノードが終端ノードであると判断され、処理を終了する。
上述の説明から理解されるように、最小値であるインデックスキーが最大値検索で得られるときには、探索経路スタックから最小値であるインデックスキーを格納したリーフノードの直近上位のブランチノードが取り出されており、次に新たにノードが終端ノードの上に格納されることはないから、次の最大値検索に進む前に図28Aに示すステップS2805で終端ノードが取り出され、ステップS2808で終端ノードであることが判定されて処理が終了する。
次に、図29A、図29B及び図29Cを参照してカップルドノードツリーに格納されたインデックスキーを、範囲を指定して昇順に取り出す範囲指定昇順取り出し処理について説明する。
図29Aは、範囲指定昇順取り出し処理の初期処理を説明するフロー図である。インデックスキー取り出しの範囲は、予め上限キーと下限キーで指定されているものとする。
図に示すように、ステップS2901で検索開始ノードとしてルートノードを設定する。次にステップS2902で、図10A及び図10Bに示す下限値検索処理により下限キーから下限値を求め、ステップS2903で、図11A及び図11Bに示す上限値検索処理により上限キーから上限値を求める。
次にステップS2904において、探索経路スタックに終端ノード[0]を格納し、ステップS2905で検索キーとして上記ステップS2902で求めた下限値を設定して、ステップS2906に進む。
ステップS2906では、図4Bに示す検索処理により、カップルドノードツリーの配置された配列を検索してインデックスキーを求め、初期処理を終了して図29Bに示すステップS2907に移行する。
図29Bは、範囲指定昇順取り出し処理のループ処理を説明するフロー図である。
ステップS2907では、ステップS2906で得たインデックスキーあるいは後述のステップS2915で得た最小値であるインデックスキーを取り出す。
次にステップS2908で、ステップS2903で求めた上限値とステップS2907で取り出したインデックスキーが等しいか判定し、等しければ上限値までのインデックスキーの昇順取り出しは完了したのであるから、処理を終了する。
等しくなければ次にステップS2909で、探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタの値を1つ減らす。最初のステップS2909での探索経路スタックの状態は、ステップS2906の検索を実行したときの状態である。
次にステップS2910で、取り出したノードの代表番号から取り出したノードのノード位置を得る。
次にステップS2911に進み、ステップS2910で得たノード位置がノード[1]側であるか判定する。ノード[1]側であればステップS2909に戻り、ノード[0]側であればステップS2912に進む。
ステップS2912では、ステップS2909で取り出したノードが終端ノードであるか判定する。該ノードが終端ノードであれば、インデックスキーの取り出しが終了したのであるから処理を終了する。
ステップS2912での判定が「終端ノードではない」であれば、ステップS2913に進み、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS2909で取り出したノードの代表ノード番号を設定する。
さらにステップS2914で、検索開始ノードのノード位置として、値“1”を設定してステップS2915に進み、図8Bに示す最小値検索を実行し、インデックスキーの最小値を取得し、ステップS2907の最小値であるインデックスキーを取り出す処理に戻る。
上記ステップS2907からステップS2915までのループ処理をステップS2908あるいはステップS2912での判定が「はい」に至るまで繰り返すことにより、上限キーと下限キーで指定された範囲内のインデックスキーが昇順にとりだされる。
図29Cは、図29A及び図29Bのフロー図により説明したインデックスキーの範囲を指定して昇順に取り出す処理例を説明する図である。図29C(a)には図2Bに例示したカップルドノードツリーと、検索キー設定エリア270及び第2の検索キー設定エリア271にそれぞれ設定された下限キー“010100”と上限キー“101001”とが示されている。図29C(b)の(1)〜(3)において、インデックスキーを昇順に取り出す処理を実行する各段階における探索経路スタック310の状態及び取り出されるインデックスキーが示されている。
下限キー“010100”によりノード211dに格納されたインデックスキー“011010”が下限値として求められ、ノード211dが範囲指定昇順取り出し処理の探索開始ノードとなる。また、上限キー“101001”によりノード211gに格納されたインデックスキー“100011”が上限値として求められ、ノード211gが範囲指定昇順取り出し処理の探索終了ノードとなる。
次に上記下限値を検索キーとしてルートノード210aから検索を行い、探索開始ノードのインデックスキー“010100”が取り出される。このインデックスキーは探索範囲での最小値である。
図29C(b)の(1)には、この取り出されたインデックスキーと検索実行結果による探索経路スタック310のノード格納状態が示されている。今の場合、探索経路スタック310には、終端ノード[0]、ノード210a、ノード210b、ノード211cが格納されており、ノード210bとノード211cの代表ノード番号はそれぞれ1加算されている。インデックスキー“010100”は上限値“100011”より小さいので次の最小値検索を含むループ処理が実行される。
図29C(b)の(1)に示す探索経路スタック310の右側の実線の矢印が示すスタックポインタの位置のノード210aの代表ノード番号220aが、探索経路スタック310をさかのぼったときの最初のノード[0]側であるので、該代表ノード番号220aが最小値検索の検索開始ノードの属するノード対201bの代表ノード210bの配列番号として設定され、検索開始ノードのノード位置には値“1”が設定されて、最小値検索が行われる。スタックポインタは点線の矢印が示すように終端ノード[0]を指している。
図29C(b)の(2)は、上記最小値検索を実行した段階の探索経路スタック310及び取り出されるインデックスキーが示されている。最小値検索により終端ノード[0]の上にノード211bとノード210fが格納されている。そして、ノード210fの代表ノード番号220fの指すノード210gはリーフノードであるのでそのインデックスキー“100010”が取り出される。このインデックスキーも上限値より小さいのでさらにループ処理が続行する。
図29C(b)の(3)は、代表ノード番号に代表ノード番号220fを、ノード位置に値“1”を設定して最小値検索を実行した段階の探索経路スタック310及び取り出されるインデックスキーが示されている。最小値検索の結果、配列から取り出されたノード211gはリーフノードであるため、このノード211gのインデックスキー“100011”が取り出される。取り出されたインデックスキー“100011”は上限値と等しいので、処理は終了となる。ノード211gは図29C(a)に示すように、探索終了ノードであり、図29C(b)の(3)に示すように、そのインデックスキー“100011”は、探索範囲の最大値である。
次に、図30A、図30B及び図30Cを参照してカップルドノードツリーに格納されたインデックスキーを、範囲を指定して降順に取り出す範囲指定降順取り出し処理について説明する。このインデックスキーの範囲指定降順取り出し処理は、先に図29A〜図29Cを参照して説明した範囲指定昇順取り出し処理といわば双対の関係にあり、最小値検索に変えて最大値検索を行い、ノード位置及び上限と下限を反転させたものに相当する。
図30Aは、範囲指定降順取り出し処理の初期処理を説明するフロー図である。先に説明した範囲指定昇順取り出し処理の場合と同様にインデックスキー取り出しの範囲は、予め上限キーと下限キーで指定されているものとする。
図に示すように、ステップS3001で検索開始ノードとしてルートノードを設定する。次にステップS3002で、図11A及び図11Bに示す上限値検索処理により上限キーから上限値を求め、ステップS3003で、図10A及び図10Bに示す下限値検索処理により下限キーから下限値を求める。
次にステップS3004において、探索経路スタックに終端ノード[1]を格納し、ステップS3005で検索キーとして上記ステップS3002で求めた上限値を設定して、ステップS3006に進む。
ステップS3006では、図4Bに示す検索処理により、カップルドノードツリーの配置された配列を検索してインデックスキーを求め、初期処理を終了して図30Bに示すステップS3007に移行する。
図30Bは、範囲指定降順取り出し処理のループ処理を説明するフロー図である。
ステップS3007では、ステップS3006で得たインデックスキーあるいは後述のステップS3015で得た最大値であるインデックスキーを取り出す。
次にステップS3008で、ステップS3003で求めた下限値とステップS3007で取り出したインデックスキーが等しいか判定し、等しければ下限値までのインデックスキーの降順取り出しは完了したのであるから、処理を終了する。
等しくなければ次にステップS3009で、探索経路スタックからスタックポインタの指すノードを取り出し、スタックポインタの値を1つ減らす。最初のステップS3009での探索経路スタックの状態は、ステップS3006の検索を実行したときの状態である。
次にステップS3010で、取り出したノードの代表番号から取り出したノードのノード位置を得る。
次にステップS3011に進み、ステップS3010で得たノード位置がノード[0]側であるか判定する。ノード[0]側であればステップS3009に戻り、ノード[1]側であればステップS3012に進む。
ステップS3012では、ステップS3009で取り出したノードが終端ノードであるか判定する。該ノードが終端ノードであれば、インデックスキーの取り出しが終了したのであるから処理を終了する。
ステップS3012での判定が「終端ノードではない」であれば、ステップS3013に進み、検索開始ノードの属するノード対の代表ノードの配列番号として、ステップS3009で取り出したノードの代表ノード番号から値“1”を減じた値を設定する。
さらにステップS3014で、検索開始ノードのノード位置として、値“1”を設定してステップS3015に進み、図9Bに示す最大値検索を実行し、インデックスキーの最大値を取得し、ステップS3007の最大値であるインデックスキーを取り出す処理に戻る。
上記ステップS3007からステップS3015までのループ処理をステップS3008あるいはステップS3012での判定が「はい」に至るまで繰り返すことにより、上限キーと下限キーで指定された範囲内のインデックスキーが降順にとりだされる。
図30Cは、図30A、図30Bのフロー図により説明したインデックスキーの範囲を指定して降順に取り出す処理例を説明する図である。図30C(a)には図2Bに例示したカップルドノードツリーと、検索キー設定エリア270及び第2の検索キー設定エリア271にそれぞれ設定された上限キー“101001”と下限キー“011001”が示されている。図30C(b)の(1)〜(3)において、インデックスキーを降順に取り出す処理を実行する各段階における探索経路スタック310の状態及び取り出されるインデックスキーが示されている。
上限キー“101001”によりノード211gに格納されたインデックスキー“100011”が上限値として求められ、ノード211gが範囲指定降順取り出し処理の探索開始ノードとなる。また、下限キー“011001”によりノード211dに格納されたインデックスキー“011010”が下限値として求められ、ノード211dが範囲指定降順取り出し処理の探索終了ノードとなる。
次に上記上限値を検索キーとしてルートノード210aから検索を行い、探索開始ノードのインデックスキー“100011”が取り出される。このインデックスキーは探索範囲での最大値である。
図30C(b)の(1)には、この取り出されたインデックスキーと検索実行結果による探索経路スタック310のノード格納状態が示されている。今の場合、探索経路スタック310には、終端ノード[1]、ノード210a、ノード211b、ノード210fが格納されており、ノード210aとノード210fの代表ノード番号はそれぞれ1加算されている。インデックスキー“100011”は下限値“011001”より大きいので次の最大値検索を含むループ処理が実行される。
図30C(b)の(1)に示す探索経路スタック310に格納されたノード210fの代表ノード番号220f+1からノード位置がノード[1]側であると判定されるので、該代表ノード番号220f+1から1を減算した値が最大値検索の検索開始ノードの属するノード対201gの代表ノード210gの配列番号として設定され、検索開始ノードのノード位置には値“0”が設定されて、最大値検索が行われる。
図30C(b)の(2)は、上記最大値検索を実行した段階の探索経路スタック310及び取り出されるインデックスキーが示されている。そして、ノード210fの代表ノード番号220fの指すノード210gはリーフノードであるのでそのインデックスキー“100010”が取り出される。このインデックスキーも下限値より大きいのでさらにループ処理が続行する。そして、スタックポインタは、探索経路スタック310の右側の実線の矢印で示すようにノード210aを指しており、その代表ノード番号220a+1から1を減算した値が次の最大値検索の検索開始ノードの属するノード対201bの代表ノード210bの配列番号として設定され、検索開始ノードのノード位置には値“0”が設定されて、最大値検索が行われる。
図30C(b)の(3)は、代表ノード番号に代表ノード番号220aを、ノード位置に値“0”を設定して最大値検索を実行した段階の探索経路スタック310及び取り出されるインデックスキーが示されている。最大値検索開始時にはスタックポインタは探索経路スタック310の左側の点線の矢印で示すように終端ノード[1]を指しており、最大値検索の結果、その上にノード210bとノード211cが格納されている。ノード211cの代表ノード番号221c+1が指しているノード211dはリーフノードであるため、このノード211dのインデックスキー“011010”が取り出される。取り出されたインデックスキー“011010”は下限値と等しいので、処理は終了となる。ノード211dは図30C(a)に示すように、探索終了ノードであり、図30C(b)の(3)に示すように、そのインデックスキー“011010”は、探索範囲の最小値である。
次に、カップルドノードツリーに収容されたインデックスキーの前方一致検索処理について説明する。本実施形態の前方一致検索においては、上位に有意ビットを有する前方一致キーは予め指定されているものとする。
図31Aは、本実施形態の前方一致検索の処理フローを説明する図である。
図に示すように、ステップS3101で検索開始ノードにルートノードを設定し、ステップS3102で下限キーとして前方一致キーの無意ビットの値を“0”としたビット列のキーを設定し、ステップS3103において、ステップS3101及びステップS3102での設定に基づいて、図10A及び図10Bに示す下限値検索を実行し、インデックスキーの下限値を得る。
次にステップS3103aに進み、前方一致キーの有意ビットの範囲で、前方一致キーとステップS3103で得た下限値を比較し、ステップS3103bで有意ビットの範囲で一致するか判定する。一致すればステップS3104に進み、一致しなければ指定された前方一致キーで取り出すインデックスキーはないことから、検索失敗として処理を終了する。上記ステップS3103bでの判定により、ステップS3104以下の処理では、少なくとも下限値が前方一致検索でヒットすることが保証されている。
ステップS3104においては、図示しない差分ビット位置設定エリアに、前方一致キーの上位0ビット目から見た有意ビットの末尾のビット位置を設定する。
次にステップS3105に進み、探索経路スタックからノードを取り出し、探索経路スタックのスタックポインタを1つ戻す。
次にステップS3106で、ステップS3105で取り出したノードの弁別ビット位置を取り出し、ステップS3107に進む。
ステップS3107では、ステップS3106で取り出した弁別ビット位置がステップS3104で設定した差分ビット位置の値より大きいか判定する。弁別ビット位置が差分ビット位置より大きければステップS3105に戻り、大きくなければステップS3108に進む。
ステップS3108において、ステップS3105で取り出したノードが終端ノードか判定する。終端ノードでなければステップS3109に進み、終端ノードであればステップS3110に進む。
ステップS3109においては、検索開始ノードにステップS3105で取り出したノードの代表ノード番号が指すノードを設定してステップS3111に進み、ステップS3110においては、検索開始ノードにルートノードを設定してステップS3111に進む。
以上説明したステップS3105〜ステップS3110の処理は、前方一致検索でヒットするインデックスキーを格納したリーフノードを全て含み、ヒットしないインデックスキーを格納したリーフノードを含まない部分木のルートノードを、ステップS3111での検索における検索開始ノードとする処理である。
前記下限値は、上記部分木の最小値であり、該部分木のルートノードはステップS3103での下限値を求める処理により、探索経路スタックに格納されていることは明らかである。
そして探索経路スタックに格納されているブランチノードを読み出して弁別ビット位置を取り出し、ステップS3104で設定された差分ビット位置と比較したとき、弁別ビット位置が差分ビット位置より大きいと、その下位のリーフノードに格納されたインデックスキーは全て前方一致検索でヒットするものであるが、上位のブランチノードの下位に前方一致検索でヒットするインデックスキーを格納したリーフノードが存在する可能性がある。
そこでさらにブランチノードを読み出して弁別ビット位置を取り出し、差分ビット位置と比較したとき、弁別ビット位置が差分ビット位置と等しくなれば、そのブランチノードの代表ノード番号は前記下限値を含むリーフノードが存在する側のノード位置のノードを指しており、該ノードをルートノードとする部分木は、前方一致検索でヒットするインデックスキーを格納したリーフノードを全て含み、ヒットしないインデックスキーを格納したリーフノードを含まないことが容易に理解される。
差分ビット位置と等しい値の弁別ビット位置を持つブランチノードがなく、弁別ビット位置が差分ビット位置より小さいブランチノードが取り出されると、その代表ノード番号は、前記下限値を含むリーフノードが存在する側のノード位置のノードを指しており、該ノードの弁別ビット位置は差分ビット位置より大きいので、先に述べたようにその下位のリーフノードに格納されたインデックスキーは全て前方一致検索でヒットするものである。
一方、前記取り出された弁別ビット位置が差分ビット位置より小さいブランチノードの代表ノード番号の指すノードと対をなすノード側に存在するリーフノードに格納されたインデックスキーには弁別ビット位置の定義から、前方一致検索でヒットするものはない。
以上のことから、弁別ビット位置がステップS3104で設定された差分ビット位置以下となるブランチノードの直近下位のノード、すなわちその代表ノード番号の指すノードが前方一致検索でヒットするインデックスキーを格納したリーフノードを全て含み、ヒットしないインデックスキーを格納したリーフノードを含まない部分木のルートノードとなることが分かる。
ステップS3111においては、図27Aに示すインデックスキーを昇順に取り出す処理により、検索開始ノードから配列を探索して昇順にインデックスキーを取り出す。
以上の処理により、カップルドノードツリーに格納されたインデックスキーのうち前方一致キーの有意ビットの範囲でビット値が等しいインデックスキーは全て取り出される。
図31Bは、図31Aのフロー図により説明した前方一致検索の検索例を説明する図である。図31B(a)には、図2Bに例示するカップルドノードツリーのうち、本検索例に関係するルートノード210aとノード211b以下の階層の部分木と、検索キー設定エリア270、第2の検索キー設定エリア271が示されている。検索キー設定エリア270には前方一致キー“10xxxx”が設定されており、第2の検索キー設定エリア271には、前方一致キーの無意ビット“x”を“0”として得た下限キー“100000”が設定されている。
なお、前方一致キーの有意ビット、無意ビットの識別には、明示的に有意ビットのビット数を指定することのほか、インデックスキーの各ビットの前に有意ビットであるか無意ビットであるかの識別ビットを付加することにより行うこともできる。
図31B(b)には、下限値検索以後のインデックスキーの昇順取りだしによる探索経路スタック310の状態遷移(1)〜(5)と取り出されたインデックスキーが示されている。
図31B(b)の(1)は、図31Aに示すステップS3103での下限値検索を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。スタックポインタの指す位置は、終端ノードからノード210fになっている。ここでは、ノード210fの代表ノード番号220fの指すノードはリーフノード210gであるため、このノード210gのインデックスキー
“100010”が下限値として取り出されている。
一方、図示されていないが、前方一致キー“10xxxx”の有意ビットの末尾のビット位置“1”が差分ビット位置として設定されている。
そこで、探索経路スタック310に格納されたノードの弁別ビット位置がノード210fから順次差分ビット位置と比較され、ノード210aが検索開始ノードの直近上位のノード(親ノード)として取り出され、その代表ノード番号220a+1が検索開始ノード211bの配列番号として設定される。
以下、図31AのステップS3111に示すインデックスキーを昇順に取り出す処理、すなわち最小値検索を繰り返す処理が実行される。
図31B(b)の(2)は、ノード211bを検索開始ノードとして最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最小値検索の結果、探索経路スタック310には終端ノード[0]の上にノード211bとノード210fが格納されている。ここでは、ノード210fの代表ノード番号220fの指すノード210gはリーフノードであるため、このノード210gのインデックスキー
“100010”が最小値として再度取り出され、スタックポインタの指す位置は1つ減ってノード211bとなる。そして、最小値検索における代表ノード番号に代表ノード番号220fを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図31B(b)の(3)は、代表ノード番号に代表ノード番号220fを、ノード位置に値“1”を設定して最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。ここでは、配列から取り出されたノード211gはリーフノードであるため、このノード211gのインデックスキー“100011”
が取り出され、スタックポインタの指す位置は1つ減って終端ノード[0]となる。そして、最小値検索における代表ノード番号に代表ノード番号221bを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図31B(b)の(4)は、代表ノード番号に代表ノード番号221bを、ノード位置に値“1”を設定して最小値検索処理を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示している。最小値検索の結果、探索経路スタック310には終端ノード[0]の上にノード211fが格納されている。ここでは、ノード211fの代表ノード番号221fの指すノード210hはリーフノードであるため、このノード210hのインデックスキー
“101011”が取り出され、スタックポインタの指す位置は1つ減って終端ノード[0]となる。そして、最小値検索における代表ノード番号に代表ノード番号221fを、ノード位置に値“1”を設定し、次の最小値検索を実行する。
図31B(b)の(5)は、代表ノード番号に代表ノード番号221fを、ノード位置に値“1”を設定して最小値検索を実行した段階における探索経路スタック310及び取り出されるインデックスキーを示す。ここでは、配列から取り出されたノード211hはリーフノードであるため、このノード211hのインデックスキー“101100”が取り出される。そして、図27Aに示すステップS2708で、前回ステップS2705で探索経路スタック310から取り出されたノードが終端ノードであると判断され、処理を終了する。
以上に説明した本発明の実施の形態によるカップルドノードツリーの各種検索処理、分割結合処理及びその均等物をコンピュータに実行させるプログラムにより、本発明のカップルドノードツリーの各種検索方法、分割方法及び結合方法が実現可能であることは明らかである。
したがって、上記プログラム、及びプログラムを記憶したコンピュータ読み取り可能な記憶媒体は、本発明の実施の形態に含まれる。また、上述のカップルドノードツリーのツリー構造からなるデータ構造も、本発明の実施の形態に含まれる。