[実施形態]
図1を参照して、この実施形態のシステムの機能構成を概説する。
このシステムは、複数のノードから構成される木構造を管理する。ノードを構成するデータの例としてはXML要素がある。この例では、XML文書中のそれらXML要素が構成する構造を、それらノードからなる木構造として表現される。
このシステム間は、ノード入力部10,ノード登録部12,分割必要性判断部14,クラスタ分割部16,クラスタ構成部18,クラスタ保持部20,検索対象ノード入力部22,クラスタ検索部24,先祖・子孫判定部26を備える。
ノード入力部10は、クラスタ保持部20内に保持された既存の木(ツリー)に対して新たに追加するノードの入力を行う入力装置である。新たなノードの追加には、例えば、既存の木構造において、追加対象のノードの親のノードを指定すればよい。ノード入力部10は、例えば、既存の木構造を表す図を表示し、その表示上でマウス等の操作により追加対象のノードの親のノードの指定を受け付ければよい。ノード入力部10は、入力された新たなノードを表す情報(例えば既存のどのノードに子が追加されたかを示す情報)を、ノード登録部12に送る。
また、別の例として、XMLエディタなどを用いて既存のXML文書中のある要素の中にその要素の子要素が新たに追加される場合を考えると、ノード入力部10は、XMLエディタから新たに追加された子要素の情報(例えば既存のどの要素の子として追加されたかを示す情報)を取得し、その情報をノード登録部12に送る。
ノード登録部12は、ノード入力部10に入力された新たなノードを、クラスタ保持部20に保持された管理対象の既存の木構造に登録するための処理を行う。詳しい処理の内容は後述する。
クラスタ保持部20には、管理対象の木構造を表す情報が記憶される。ここで、この実施形態では、木構造を1以上の部分木に分けて管理する。部分木は、木の一部であり、それ自体が木の構造をなすものをいう。以下では、部分木のことをクラスタと呼ぶ。すなわち、クラスタは、元の木構造の一部分であり、木の構造をなす1以上のノードを含んでいる。クラスタ保持部20には、木の各ノードがそれぞれどのクラスタに属するかを表す情報など、管理対象の木構造に含まれる各クラスタについての情報も登録されている。クラスタ保持部20が保持するデータの種類や内容、構造などについては、後で説明する。
このように、この実施形態では、管理対象の木構造をクラスタに分割して別々に管理することにより、木構造に対する操作を、クラスタごとに並列して実行可能としている。例えば、XML文書を要素間の木構造を用いて管理する場合では、クラスタ分割の手法を用いることで、クラスタ毎にロックをかけることで、1つのクラスタは1人しか操作できないが、異なるクラスタについては並列して操作が可能となる。また、クラスタ分割の手法を用いる場合、例えば、一度にメモリ上に展開する範囲を1乃至少数のクラスタに絞ることで、転送速度の遅いハードディスクへのアクセスを少なくして処理の高速化を図ってもよい。
分割必要性判断部14は、ノード登録部12による新たなノードの登録(追加)により、クラスタを分割する必要があるかどうかを判定する。
すなわち、新たなノードを管理対象の木構造中の指定されたノードの子として追加する場合、新たなノードは指定されたノードのクラスタ内に追加することとなる。ここで、この実施形態では、コンピュータ上或いはネットワークを跨る情報処理システム上でのクラスタの取扱を容易にするために、クラスタのサイズ(ノード数、又はデータ量など)を制限する。以下の例では、クラスタ内に含まれるノードの数を、あらかじめ定めた上限値以下に制限する。この制限のために、分割必要性判定部14は、新たなノードの追加により、追加先のクラスタを分割する必要があるかどうかを判断する。
分割必要性判断部14によりクラスタの分割が必要と判断されれば、クラスタ分割部16により、そのクラスタが複数のクラスタに分割される。クラスタ分割部16によりクラスタを分割した場合、クラスタ構成部18により、分割後の複数のクラスタの間の関係が構成される。クラスタの分割結果や、分割結果のクラスタ間の関係の情報は、クラスタ保持部20に登録される。
また、このシステムは、上述のようにして構築され管理される管理対象の木構造、及びクラスタの情報を用いることで、2つのノード同士の間に先祖・子孫関係(それら2つのノードの一方が他方の先祖である(言い換えれば他方が一方の子孫である)という関係)があるかどうかを判定する機能を備える。この機能は、検索対象ノード入力部22,クラスタ検索部24,及び先祖・子孫判定部26により提供される。
検索対象ノード入力部22は、先祖・子孫関係の有無の判定対象となる2つのノードの指定を受け付ける。検索対象ノード入力部22は、例えば、管理対象の木構造を表す図を表示し、その表示上でマウス等の操作に応じて2つのノードの指定を受け付ける。検索対象ノード入力部22に入力された、判定対象の2つのノードを示す情報(すなわち、それら各ノードの識別情報)は、クラスタ検索部24に渡される。
また、管理対象の木構造、又はその木構造の元になったデータ(例えばXML文書等の構造化文書)に対して処理を行うプログラムから、その処理のためにその木構造内の2つのノードが先祖・子孫関係にあるかどうかの問合せを受けた場合に、検索対象ノード入力部22は、そのプログラムからの問合せに含まれる2つのノードの識別情報を受け取り、クラスタ検索部24に渡す。
クラスタ検索部24は、それら2つのノードの関係を判定するために、クラスタ単位での先祖・子孫関係を調べる。先祖・子孫判定部26は、1つのクラスタ内のノード間の先祖・子孫関係の有無を判定する。クラスタ検索部24と先祖・子孫判定部26とが協働して、判定対象の2つのノードが先祖・子孫関係にあるかどうかを判定する。
以上、システムの概略を説明した。次に、このシステムを構成する各構成要素の詳細を説明する。
<ノードの登録>
以下に説明する例では、管理対象の木構造を構成する各ノードに対して、それぞれ識別情報として、当該ノードがその木構造に登録(追加)された順番を示す通し番号が割り当てられているものとする。この通し番号を以下ではノード番号と呼ぶ。ノード番号は、木構造の中でノードを位置に特定する番号である。以下の例では、最初に登録されたノードのノード番号を0番とする。なお、通し番号は説明のための一例に過ぎず、ノードの識別情報は通し番号以外の仕方で付与しても構わない。
ノード入力部10は、登録対象のノードの親ノードの指定を受け付け、当該親ノードのノード番号をノード登録部12に通知する。
ノード登録部12は、登録対象のノードをクラスタ保持部20内の管理対象の木構造に登録するために、ノード入力部10から通知された親ノード番号をキーとして、クラスタ保持部20からその親ノードを保持するクラスタの情報を取得する。そして、登録対象のノードを、そのクラスタ内のその親ノードの子ノードとして登録するための処理を行う。ここで、ノード登録部12は、登録対象のノードに対して一意なノード番号を付与する。
クラスタ保持部20には、図2に例示する実ノード情報42,クラスタ情報52,及び参照ノード情報62が記憶されている。
実ノード情報42は、図2に例示する管理対象の木構造30に含まれる各ノード40の情報である。図2中で白抜きの丸印で表現したノード40は、木構造30を用いて管理する対象データを構成するデータ要素に対応する、木構造30上での要素である。例えば、対象データがXML文書である場合、ノード40は、そのXML文書中の文書要素に対応する。なお、後述するクラスタ50を参照する参照ノード60(図中では黒塗りの丸印で表現した)との区別のために、管理対象データの要素と対応づけられたノード40のことを「実ノード」と呼ぶことにする。1つの実ノード40を表す実ノード情報42には、当該実ノード40自身のノード番号と、親ノードのノード番号(図中の「親ノード番号」)と、当該実ノード40が表すデータ要素のデータ内容(図中の「データ」)とが含まれる。各ノードが持つ自身のノード番号と親ノード番号との対応関係の集まりが、木構造30を表現する。
この実施形態では、木構造30を、複数のクラスタ50に分割して管理する。図2では、破線で示した三角形の中に含まれるノード群が構成する木が1つのクラスタ50である。
クラスタ情報52は、木構造30内の個々のクラスタ50を表す情報である。クラスタ情報52には、当該クラスタ自身のクラスタ番号と、当該クラスタに含まれるノード集合の情報(「保持するノード集合の情報」)と、当該クラスタを参照する参照ノード60のノード番号である参照ノード番号とを含む。クラスタ番号は、木構造30内の各クラスタ50の識別情報である。以下では、説明のための一例として、クラスタ番号として、クラスタ50が生成された順番に付与される通し番号を用いている。また、「保持するノード集合の情報」は、例えば当該クラスタに含まれるノードのノード番号のリストなどである。
参照ノード60は、クラスタ50を表すために導入したノードである。この実施形態では、1つのクラスタ50を生成すると、これに応じて1つの参照ノード60を生成する。このようにクラスタ50と参照ノード60は一対一に対応している。このような関係を「参照ノード60がクラスタ50を参照する」と呼ぶこととする。図2では、参照ノード60とこれに参照されるクラスタ50との間の、参照・被参照の関係を破線で表現している。前述の実ノードは、システム外から入力されたデータを構成する構成要素に対応しているのに対し、参照ノードは、この実施形態のシステムの内部処理でのみ使用する。なお、木構造30におけるノード同士の親子の関係は実線で表示している。
参照ノード60にも、識別情報としてノード番号が付与される。以下の例では、実ノード40も参照ノード60も分け隔て無く、当該ノードが登録された順序を表す通し番号をノード番号とする(但しこれは一例に過ぎない)。
参照ノード60を表す参照ノード情報62は、当該参照ノード自身のノード番号、当該参照ノードが参照するクラスタ50のクラスタ番号、及び当該参照ノードの親ノードのノード番号を含む。参照ノード60の親は、別の参照ノードである場合もあれば、実ノードである場合もある。
この実施形態では、参照ノード60同士の木構造を実ノードの木構造30とは別に構築するか、又は参照ノード60を木構造30内に組み込むようにしている。そして、参照ノード60もいずれかのクラスタ50内に含まれるようにする。すなわち、この実施形態では、参照ノード60を木構造に組み込むことで、ノードだけでなくクラスタも木構造を構成させる役目を果たしている。
1つの参照ノード60は1つのクラスタ50を代表しているので、第1のクラスタを代表する参照ノード60を別の第2のクラスタ50に含めることは、第1のクラスタを第2のクラスタ内に入れ子にすることに相当する。また、この実施形態では、参照ノードを含んだクラスタを参照する別の参照ノードが別のクラスタに含まれる場合もあり、これはクラスタが多重に入れ子構造をなす場合に相当する。
図1の説明に戻ると、ノード登録部12は、登録対象のノードに一意なノード番号を付与し、そのノードの実ノード情報42を作成して、クラスタ保持部20に登録する。その実ノード情報42は、付与したノード番号と、親ノードとして指定されたノードのノード番号と、登録対象のノードのデータ内容とが含まれる。このように新たなノードの実ノード情報42を登録することで、そのノードがクラスタ保持部20内の木構造30に追加されることになる。
また、ノード登録部12は、指定された親ノードを含んだクラスタのクラスタ情報52の「保持するノード集合の情報」に、新たに登録したノードのノード番号を追加する。
<クラスタの分割>
上述のようにしてクラスタ保持部20内の木構造30へノードの追加を行うと、ノードの追加先のクラスタ50内のノード数が増える。この実施形態ではクラスタ50内のノード数を上限値未満に抑えるようにしているので、ノードの追加によりクラスタ50内のノード数が上限値に達すると、そのクラスタ50を分割することとなる。
分割必要性判断部14は、このようなクラスタ分割の必要性の判断を行う。すなわち、分割必要性判断部14は、ノード登録部12によりノードが追加されたクラスタのクラスタ情報52の「保持するノード集合の情報」内のノードの数を調べ、その数が上限値以上になると、クラスタ分割の必要があると判断する。クラスタ内のノード数が上限値未満であれば、クラスタ分割は不要と判断する。
以下に説明する例では、クラスタ内のノード数の上限値は10とする(もちろんこの上限値は一例に過ぎない)。例えば、図3Aに例示したクラスタC0はノード数が10に達しているので、分割必要性判断部14により分割が必要と判断される。なお、図3A以降の図において、実ノード40を表す白抜き丸印、及び参照ノード60を表す黒塗り丸印の中の数字は、当該ノードのノード番号を示す。
分割が必要と判断されたクラスタはクラスタ分割部16にて分割される。以下では、クラスタを2分割する場合を例にとって説明する。
クラスタの分割は、例えば、元のクラスタの構造を保存したままで、部分木を抜き出す形で行われる。すなわち、この例では、元のクラスタの中の一部の部分木を抜き出し、抜き出した部分木を新たなクラスタとするのである。このために、クラスタ分割部16は、クラスタC0中の各ノードについて、そのノードをルートノードとした場合のクラスタC0内での部分木に含まれるノード数を数える。図3AのクラスタC0についての計算結果は、図3Bに例示するようなものとなる。この計算結果をもとに、クラスタ分割部16は、例えば、ノード数がなるべく半分に近いところでクラスタC0を分割できるノードを探す。
図3A及び図3Bの例ではノード番号5のノードが、クラスタC0のノード数10の半分となる5つのノードからなる部分木のルートノードとなり得るので、クラスタ分割部16は、ノード番号4とノード番号5の間でクラスタを分割すると決定する。
クラスタ分割部16によりクラスタ分割位置が決定されると、クラスタ構成部18が、その位置で分割されたクラスタを構成する。すなわち、この例ではクラスタC0から新たなクラスタC1を分割し、分割後のクラスタC0及びC1を表すクラスタ情報52をそれぞれ構成する。また、1つの例では、クラスタ構成部18は、そのクラスタC0及びC1の再構成と同時に、新たにクラスタC2を生成して、クラスタC0を参照するノード10と、クラスタC1を参照するノード11を登録する(図4A参照)。これら参照ノード10及び11はクラスタを参照するものであり、データ内容は持たない。分割により新たに生成されたクラスタC1はノード5をルートとする。ノード4とノード5との親子関係は保存される。
このとき、クラスタ構成部18は、ノード0〜4を含むクラスタC0のクラスタ情報52と、ノード5〜9を含むクラスタC1のクラスタ情報52とを生成し、クラスタ保持部20に格納する。クラスタ構成部18は、新たに生成したクラスタにはクラスタ番号を付与し、このクラスタ番号をクラスタ情報52に含める。また、クラスタに対応する参照ノードを生成した場合は、その参照ノードのノード番号を、クラスタ情報52の「このクラスタを参照する参照ノード番号」として含める。
また、クラスタ構成部18は、クラスタC0を参照する参照ノード10とクラスタC1を参照する参照ノード11との参照ノード情報62をそれぞれ生成すると共に、それら参照ノード10及び11を含んだクラスタC2のクラスタ情報52を生成する。参照ノード10と11の各参照ノード情報62には、各々に付与した一意な参照ノード番号を「自身のノード番号」として組み込むとともに、「参照するクラスタ番号」の欄に参照先のクラスタ番号C0及びC1をそれぞれ書き込む。また、参照ノード11の参照ノード情報62の「親ノード番号」の欄には、親である参照ノード10のノード番号「10」を記録する。参照ノード10は、親ノードを持たないので「親ノード番号」の欄は空値となる。
なお、クラスタC2を参照する参照ノードは、クラスタC2を生成したときに生成してもよいし、後でそのクラスタC2を分割する際に生成してもよい。
また、以上の例では、分割前のクラスタC0には参照ノードを対応づけず、クラスタC0を分割した際に、分割後のクラスタC0に対応する参照ノード10を生成したが、この代わりに、クラスタC0を最初に生成したとき(クラスタC0を分割する前)に、これを参照する参照ノードを生成しておいてもよい。
また、クラスタは、ノードが1つしかない時点では作成せず、ノードが2以上の予め定めた数以上になったときに生成するようにしてもよい。例えば、クラスタC0を生成した時点でこれを参照する参照ノードを生成したとしても、その参照ノードを含むクラスタはこの時点では作成しなくてもよい。
次に、以下での説明で用いるクラスタ間の関係の種類を説明する。図5Aの例では、クラスタC0内の参照ノード60aがクラスタC1を参照しているが、このときクラスタC0をクラスタC1の上位クラスタといい、クラスタC1をクラスタC0の下位クラスタという。すなわち、参照ノードを含んだクラスタC0は、その参照ノードが参照するクラスタC1の上位クラスタと呼ばれる。
一方、図5Bの例では、クラスタC0内のノードN0はクラスタC1内のルートノードN1の親となっているが、このときクラスタC0はクラスタC1の親クラスタといい、クラスタC1はクラスタC0の子クラスタという。すなわち、あるクラスタC1のルートノードの親ノードを含んだクラスタC0は、クラスタC1の親クラスタと呼ばれる。なお、この場合、ノードN0とN1は、実ノード、参照ノードのいずれであってもよい。
図4Aの例では、例えば、クラスタC2内の参照ノード10からクラスタC0が参照されているので、クラスタC2はクラスタC0の上位クラスタであり、クラスタC0はクラスタC2の下位クラスタである。クラスタC2、クラスタC1の間にも同じ関係が成り立つ。また、クラスタC0内のあるノードがクラスタC1のルートノードの親となっている状況から、クラスタC0はクラスタC1の親クラスタであり、クラスタC1はクラスタC0の子クラスタである。
この実施形態では、2つのクラスタが親子(すなわち親クラスタと子クラスタ)の関係を持つ場合、それらクラスタを参照する2つの参照ノード同士も親子関係となるようにする。すなわち、親クラスタを参照する参照ノードは、子クラスタを参照する参照ノードの親となる。図4Aの例では、クラスタC1はC0の子なので、C1を参照する参照ノード11は、C0を参照する参照ノード10の子とする(すなわち、参照ノード11の参照ノード情報62の「親ノード番号」を「10」とする)。
さて、図4Aに示した状態から、クラスタC0に更に実ノードが追加され、クラスタC0のノード数が再び上限値10に達した場合を考える(図4B参照)。この場合、クラスタ分割部16は、クラスタC0をノード2と3の間で分割すると決定し、これに応じクラスタ構成部18が、クラスタC0からノード3,4,14〜16を削除し、それら削除されたノード群を含んだクラスタC3を生成する(図4C参照)。また、クラスタ構成部18は、生成したクラスタC3を参照する参照ノード17を生成する。ここで、生成したクラスタC3はC0の子であり且つC1の親であるので、C3を参照する参照ノード17は、C0を参照する参照ノード10の子、且つC1を参照する参照ノード11の親となる位置に挿入される。すなわち、クラスタ構成部18は、生成したクラスタC3の参照ノード情報62の親ノード番号をC0とし、既存のクラスタC1の親ノード番号をC0からC3に書き換える。
さて、実ノードが更に追加されていき、参照ノードで構成されるクラスタC2内のノード数が上限値10に到達したとする。この実施形態では、参照ノードを含んだクラスタについても、クラスタ内のノード数が上限値に達したら分割を行う。図6に、クラスタC2からクラスタC11が分割され、更にC2とC11を参照する参照ノード60及び62を含んだクラスタC12が生成された状態を示す。図6に示すように、実ノードのなす木構造及びクラスタC0,C1等を第1層とすると、その第1層のクラスタを参照する参照ノードがなす木構造及びクラスタC2,C11は第1層に対して一段階上位の第2層となる。そして、第2層のクラスタを参照する参照ノードがなす木構造及びクラスタC12は第2層より1段階上位の第3層となる。
図6の状況から更に実ノードが追加され、第3層のクラスタが分割されると、第3層のクラスタを参照する参照ノードからなる第4層の木構造及びクラスタが生成される。
以上のように、この実施形態では、ある層(第n層:nは1以上の整数)LnのあるクラスタCLn1のノード数が上限値に達するとそのクラスタCLn1が分割される。この分割によって生成された子クラスタCLn2を参照する参照ノードRLn2が、クラスタCLn1を参照する参照ノードRLn1の子として、1段上位の層L(n+1)内のクラスタCL(n+1)1に追加される。この追加によりクラスタCL(n+1)1のノード数が上限に達し、クラスタCL(n+1)1が分割されると、分割により生成された子クラスタCL(n+1)2を参照する参照ノードRL(n+1)2が、クラスタCL(n+1)1を参照する参照ノードRL(n+1)1の子として、更に上位の層L(n+2)内のクラスタCL(n+2)1に追加される。この実施形態では、実ノードが追加されると、以上のような処理が第1層から順に上位層に向かって、クラスタの分割が生じなくなるまで繰り返される。
以上の例では、第1層,第2層,第3層,・・・の各階層におけるクラスタのノード上限数をすべて同じ値(具体例としては10)としたが、これは必須ではなく、クラスタ内のノード上限数を階層ごとに変えてもよい。
また、以上の例では、クラスタを2分割した場合、分割後の2つのクラスタのうちの親の方が元のクラスタのクラスタ番号を引き継いだが、これは必須ではない。この代わりに、子の方が元のクラスタのクラスタ番号を引き継ぐようにし、親の方が新たなクラスタ番号を割り当てられるようにしてもよい。また、分割後の2つのクラスタについてそれぞれ新たなクラスタ番号を付与してもよいが、この場合それら2つのクラスタのうちの一方のクラスタ情報52の内容は、上述の例における元のクラスタの分割後のクラスタ情報52の内容と同じものになるので、結局は、元のクラスタのクラスタ番号が変わるだけにすぎない。したがって、この明細書では、分割後のクラスタのうちの1つが元のクラスタのクラスタ番号を引き継ぐ場合の例のみを説明する。
また、以上の例では、クラスタを分割する場合の分割数は2分割であったが、これは必須ではない。クラスタを3以上のクラスタに分割してもよい。クラスタ(分割前クラスタと呼ぶ)をk個(kは2以上の整数)のクラスタ(分割後クラスタと呼ぶ)に分割した場合、それらk個のうちの1つが元のクラスタのクラスタ番号を引き継ぐ。そして、残りの(k−1)個の分割後クラスタが新たに生成され、新たなクラスタ番号の割り当てを受けるとともに、それら(k−1)個の分割後クラスタのそれぞれについて、当該分割後クラスタを参照する参照ノードが生成される。クラスタ構成部18は、それら新たに生成された(k−1)個の分割後クラスタと、元のクラスタのクラスタ番号を引き継いだ分割後クラスタとにそれぞれ対応する合計k個の参照ノードが、それら各参照ノードに対応する各分割後クラスタ同士の分割前クラスタ内での親子関係を反映した親子関係を持つようにする。すなわち、ある分割後クラスタCaのルートノードが別の分割後クラスタCb内のノードの子である場合に、クラスタCaを参照する参照ノードRaがクラスタCbを参照する参照ノードRbの子になるようにする(すなわちRaの参照ノード情報62の親ノード番号を、Rbのノード番号とする)。k個の分割後クラスタは1つの分割前クラスタの木構造を分割したものなので、それら分割後クラスタを参照するk個の参照ノードは木構造をなす。
また、分割前クラスタと別のクラスタとの親子関係は、分割後クラスタにも引き継がれる。例えば、分割前クラスタが別のクラスタCxの子であれば、クラスタ構成部18は、k個の分割後クラスタのうち、クラスタCx内のノードの子を持つ分割後クラスタを参照する参照ノード(言い換えれば、k個の参照ノードがなす木構造のルートの参照ノード)を、クラスタCxを参照する参照ノードの子とする。また分割前クラスタが別のクラスタCyの親であれば、k個の分割後クラスタのうちクラスタCyのルートノードの親のノードを含んだ分割後クラスタを参照する参照ノードを、クラスタCyを参照する参照ノードの親とする。
また、クラスタ構成部18は、分割前クラスタの分割により新たに生成した(k−1)個の参照ノードを、分割前クラスタを参照する参照ノードが属するクラスタCzに所属させる。すなわち、クラスタ構成部18は、クラスタCzのクラスタ情報52に、新たに生成した(k−1)個の参照ノードのノード番号を追加する。この追加により、クラスタCzのノード数が上限値に達するか、又は上限値を超えると、クラスタ分割部16はクラスタCzを分割する。
<先祖・子孫関係検索>
次に、このシステムの、先祖・子孫関係検索の機能について説明する。
ここで、木構造の中から任意の2つのノードA、Bを選択した場合に、一方のノードAからルートノードに向かって木構造を辿って行く際に通る経路上にもう一方のノードBが存在する場合これらのノードは先祖・子孫関係にあるという。この場合ノードAが子孫、ノードBが先祖である。
図1の例では、検索対象ノード入力部22がユーザから先祖・子孫関係の有無の判定対象とする2つのノードを受け付け、クラスタ検索部24と先祖・子孫判定部26とが協働して、それら2つのノードが先祖・子孫関係にあるかどうかを判定する。
この判定のためにクラスタ検索部24及び先祖・子孫判定部26が実行する処理手順の例を、図7及び図8に示す。図7が先祖・子孫判定部26の処理手順の例を、図8がクラスタ検索部24の処理手順の例を、それぞれ示す。
検索対象ノード入力部22が検索対象の2つのノード(以下、ノードA,Bと呼ぶ)の指定を受けると、クラスタ検索部24は、それらノードA,Bについて図8の処理を開始する(S0)。まずクラスタ検索部24は、それら2つのノードA,Bを、それぞれ順に注目ノードa,bに代入する(S10)。この処理では、クラスタ検索部24は、まずクラスタ保持部20に記憶された各クラスタ情報52の「保持するノード集合の情報」を調べることにより、それら2つの注目ノードa,bが同一クラスタに属しているか否かを判定する(S11)。前述のクラスタ分割処理の例から判るように、1つのノードが複数のクラスタに属することは起こらない。
ノードa,bが同一クラスタに属していると判った場合、クラスタ検索部24はステップS13に進む。
一方、ノードa,bが同一クラスタに属していないと判った場合、クラスタ検索部24はステップS12の処理を行う。ステップS12では、クラスタ検索部24は、ノードaが属するクラスタを求め、そのクラスタを参照する参照ノードが属するクラスタを求め、更にこのクラスタを参照する参照ノードの属するクラスタを求め、というように、ノードaの属するクラスタを起点として1つずつ上位クラスタへと遡上する。そして、これ以上上位へと遡れなくなるまでこの遡上を繰り返し、その過程で通過するノードaの上位の各階層の参照ノード及びクラスタを記録する。ノードbについても、同様の遡上を行い、ノードbの上位の各階層の参照ノード及びクラスタを特定する。そして、ノードaの上位の各階層のクラスタとノードbの上位の各階層のクラスタの中で、下位側から見て最初の共通のクラスタを求め、その共通クラスタに含まれるノードa及びノードbそれぞれの上位階層の参照ノードa’,b’を特定する。このように特定した参照ノードa’,b’は、同一クラスタに属している。クラスタ検索部24は、特定した参照ノードa’,b’を、それぞれ、新たな注目ノードa,bとし、ステップS13の処理を行う。したがって、ステップS13で操作の対象となる注目ノードa,bは同一クラスタに属するものとなっている。
ステップS13では、クラスタ検索部24は、先祖・子孫判定部26を呼び出し、そのノードbがノードaの子孫であるかどうかを判定させる。
呼び出された先祖・子孫判定部26は、図7の手順を実行する。図7は、判定対象の2つのノードのうちのノードbを起点として、ノードbがノードaの子孫であるか否かを判定する処理を示している。このように、図7自体はノードbを起点とする処理であるが、先祖・子孫判定部26は、ノードaを起点とした場合についても同様の処理手順を行い、ノードaがノードbの子孫であるかどうかも確認する。以下、図7の手順を詳細に説明する。
図7の手順では、先祖・子孫判定部26は、まずノードbを、図7の手順における着目ノードとする(S1)。次に、着目ノード(現段階ではノードb)が、ノードaであるか否かを判定する(S2)。この判定では、着目ノードとノードaのノード番号同士が同じかどうかを調べればよい。この判定結果が肯定(YeS)の場合、先祖・子孫判定部26は、ノードbはノードaの子孫であると判定する(S5)。これは、ノードaとbとが同一ノードである場合である。
ステップS2の判定結果が否定(No)の場合、先祖・子孫判定部26は、着目ノードがルート(根)ノードであるかどうかを判定する(S3)。この判定では、着目ノードの実ノード情報42に含まれる親ノード番号を調べればよい。着目ノードの親ノード番号が空値(NULL。すなわち親がない)である場合、着目ノードはルートノードであると判定される(判定結果が肯定)。この場合、先祖・子孫判定部26は、ノードbがノードaの子孫ではないと判定する(S6)。
ステップS3の判定結果が否定の場合、先祖・子孫判定部26は、着目ノードを親ノードに移動する(S4)。すなわち、現在の着目ノードの親ノードを新たな着目ノードとする。この処理において、着目ノードの親ノードは、着目ノードの実ノード情報42の親ノード番号から特定される。そして、先祖・子孫判定部26は、再びステップS2に戻り、着目ノードがノードa又はルートノードのいずれかであることが判明するまで、ステップS2〜S4の処理を繰り返す。この繰り返しは、ノードbを起点に、着目ノードを1つずつ先祖に遡らせていく処理である。この繰り返しにより、着目ノードがノードaに一致したことがステップS2で判明すると、ノードbはノードaの子孫であると判定することができる(S5)。一方、繰り返しにより、着目ノードが、ノードaに一致しないまま、ルートノードまで達したことがステップS3で判明すると、ノードbはノードaの子孫ではないと判定することができる(S6)。
ノードbを起点とする図7の処理が完了(すなわちS5又はS6のいずれかに到達)すると、先祖・子孫判定部26は、aとbを読み替え、ノードaを起点として図7の処理をもう一度実行する。このように、ノードb,aをそれぞれ起点とした場合の図7の処理により、(ア)ノードbがノードaの子孫である、(イ)ノードaがノードbの子孫である、(ウ)ノードaとノードbは互いに先祖でも子孫でもない、のいずれかの結果が得られる。(ア)と(イ)の場合はノードaとノードbとの間に先祖・子孫関係があるが、(ウ)の場合はノードaとノードbとの間に先祖・子孫関係がない。
このようにして、注目ノードa,bについての先祖・子孫判定部26の判定処理が終わると、その結果がクラスタ検索部24に返される。クラスタ検索部24は、その判定処理の結果を図8ステップS13の判定結果として、処理を進める。
再び図8の説明に戻ると、ステップS13での先祖・子孫係判定部26の判定にて、ノードaとbの間に先祖・子孫関係がないと判定される(S13の判定結果が否定)と、クラスタ検索部24は、最終的にノードaとノードbとの間に先祖・子孫関係がないと判定する。この判定結果は、検索対象ノード入力部22に対して検索対象のノードを入力したユーザに対して提示してもよい。この提示は、例えば、検索対象ノード入力部22を備えたコンピュータの画面上にその判定結果を表示することにより行ってもよい。
一方、ステップS13での先祖・子孫判定部26の判定にて、ノードa,bの間に先祖・子孫関係があると判定されると、クラスタ検索部24は、ノードa,bのうちの先祖側のノードが参照ノードであるかどうかを判定する(S14)。この判定は、当該先祖側のノードのノード番号に対応するノード情報が実ノード情報42と参照ノード情報62のいずれであるかに基づき行えばよい。
ステップS14で、ノードa,bのうちの先祖側のノードが参照ノードでない(判定結果が否定(No))、すなわち実ノードであると判定された場合、クラスタ検索部24は、検索対象ノード入力部22から入力された検索対象のノードA,B間に先祖・子孫関係があると最終的に判定する。この判定結果は、検索対象ノード入力部22に対して検索対象のノードを入力したユーザに対して提示してもよい。この提示は、例えば、検索対象ノード入力部22を備えたコンピュータの画面上にその判定結果を表示することにより行ってもよい。
ステップS14で、ノードa,bのうちの先祖側のノードが参照ノードであると判定された場合、クラスタ検索部24はステップS15の処理を実行する。
ステップS15では、まずノードA,Bのうちの先祖側のノードを特定し、特定した先祖側のノードを次の処理ループにおける新たなノードAとする。前述のステップS12では、ノードA,Bを起点としてクラスタを上位階層へと遡上したが、ノードA,Bのうち、その遡上の結果現在の注目ノードa及びbのうちの先祖側のノードに到達した方のノードを、新たなノードAとするのである。
またステップS15では、現在の注目ノードaとb(これらは先祖・子孫関係にある)とを結ぶ木の経路上のノードの中から、注目ノードaとbのうちの先祖側のノードの直近の子孫ノード(すなわち子)に該当するノードを特定し、特定したノードが参照するクラスタのルートノードを求める。この処理では、例えば、先祖側のノードの直近の子孫ノード(これは参照ノードである)の参照ノード情報62の「参照するクラスタ番号」を調べ、このクラスタ番号に対応するクラスタ情報52の「保持するノード集合の情報」から、当該クラスタのルートノードを求めればよい。そして、求めたルートノードが参照ノードであれば、そのルートノードが参照するクラスタのルートノードを求める。求めたルートノードが実ノードであることが判明するまで、この処理を繰り返す。そして、最終的に求められた実ノードであるルートノードを、次の処理ループにおける新たなノードBとする。求められた新たなノードBは、元のノードA,Bのうちの子孫側のノードに対する先祖に該当する。なぜなら、上述の求め方から判るように、新たなノードBが属するクラスタは、元のノードBが属するクラスタの先祖であり、新たなノードBはその先祖のクラスタのルートであるからである。
このように、ステップS15では、ノードA,Bのうちの先祖側を新たなノードAとして残し、子孫側のノードから遡った先祖のノードを新たなノードBとするのである。新たなノードAが新たなノードBの先祖であれば、新たなノードAは、元のノードA,Bのうちの子孫側のノードの先祖である。したがって、新たなノードAと新たなノードBとが先祖・子孫関係を持つかどうかを判定すれば、元のノードAと元のノードBが先祖・子孫関係を持つかどうかが判る。
そこで、クラスタ検索部24は、ステップS0に戻り、ステップS15で求めた新たなノードA,Bを対象として図8の処理を繰り返す。
クラスタ検索部24は、以上のような処理を、ステップS13の判定結果が否定、又はステップS14の判定結果が否定になるまで繰り返す。これにより、検索対象ノード入力部22から入力された検索対象のノード同士が先祖・子孫関係にあるか否かが判定される。
次に、上述したクラスタ検索部24及び先祖・子孫判定部26の処理手順を、図6に例示した木構造中のノード同士の先祖・子孫関係の判定に用いた場合の具体例を説明する。
まず第1の例として、図6の木構造(第1層)中の実ノード46と実ノード43とを検索対象ノードとした場合の処理の流れを説明する。
この場合、実ノード46と実ノード43は同じクラスタC8に属していることがステップS11で判る。同じクラスタ内の2つのノードの先祖・子孫関係判定は図7に示すように、片方のノードAからクラスタのルートノードに向かって辿っていき、もう片方のノードBに突き当たれば、ノードAはノードBの子孫であり、逆にノードBからルートノードに向かって辿っていき、ノードAに突き当たれば、ノードBはノードAの子孫である。片方のノードを起点として先祖・子孫判定部26が図7の手順を実行し、その結果先祖・子孫関係がみつからなかった場合はもう片方を起点として同じ手順を実行する。第1の例のノード46とノード43はこの先祖・子孫関係判定により先祖・子孫関係にないことが明らかとなる。
次に、第2の例として、図6において実ノード46と実ノード31が先祖・子孫関係にあるか検索する。ノード46とノード31は、それぞれクラスタC8、C6と、所属するクラスタが異なる。そこでクラスタC8とC6をそれぞれ参照する参照ノードを辿り、直近の共通する先祖クラスタ中のノードを取得する。
クラスタ保持部20はクラスタC8が参照ノード47に参照されているという情報(クラスタ情報52)を持っている。クラスタ検索部24は、これを用いて参照ノード47を特定し、参照ノード47を保持するクラスタをクラスタ保持部20に問い合わせてそれがクラスタC11であることを知る。更に、同様にクラスタC11を参照する参照ノード62と、それを保持するクラスタがC12であるという情報も取得する。このようにして、クラスタのなす階層をクラスタC8から上位へと遡っていった場合に得られる最上位階層のクラスタまでのクラスタの系列(連なり)はC8(46)→C11(47)→C12(62)となる。括弧内の番号は、括弧の前に示したクラスタ内の参照ノードであって、その系列における1段階下位のクラスタを参照する参照ノードを示す(ただし、最下位のクラスタについての括弧内の番号は、実ノードを示す)。クラスタ検索部24は、求めたC8(46)→C11(47)→C12(62)というクラスタ系列を記憶する。
同様に、クラスタ検索部24は、クラスタC6から上位階層へと遡上した場合のルートクラスタまでのクラスタの系列、C6(31)→C11(35)→C12(62)、を求めて記憶する。
そして、クラスタ検索部24は、それら2つのクラスタ系列同士の間で、最も下位で共通するクラスタを特定する。例えば、クラスタ検索部24は、2つの系列の一方、例えばクラスタC8から開始する系列を選択し、最下位のクラスタを選択する。そして、選択したクラスタと同じものをもう一方の系列から探す。見つからなければ、選択した系列から、選択したクラスタよりも1つ上位のクラスタを選択し、この選択したクラスタと同じものをもう一方の系列から探す。選択した系列から選択したクラスタと同じものがもう一方の系列から見つかるまで、以上の処理を繰り返す。クラスタは階層構造をなしているので(図6参照)、選択した系列から選択したクラスタと同じものがもう一方の系列から必ず見つかる。
具体的には、C8を選択すると、もう一方の系列はC6、C11、C12であるので共通する先祖クラスタは存在しない。次にC11を選択するともう一方の系列の2番目にC11が存在することを発見する。これが両系列に共通する最下位のクラスタである。これより上位のクラスタC12も両系列で共通のクラスタであるが、共通する最下位のクラスタが判ればよいので、処理はC11が見つかった段階で終了してよい。
次の注目ノードは、C11内の参照ノード47、35となる(図8のS12)。同じクラスタ上の2つのノードに対しては先祖・子孫関係判定処理(図7)が適用可能であるので、この処理により判定を行う。検索の結果ノード35と47は先祖・子孫関係にあることが判る(図8のS13)。ここでノード35、47は参照ノードであり、実ノードではない(図8のS14)。そこでクラスタ検索部24は、両者のうちの先祖側のノード35の直近の子孫ノードがノード41であることを求め、そのノード41が参照するクラスタC7のルートノード36の親ノード32を取得する(図8のS15)。このノード32は実ノードである。また、検索対象の実ノード46と31のうち、現在の注目ノード35、47のうちの先祖側のノード35に対応するノードはノード31である。
そこで、クラスタ検索部24は、次にノード31,32を新たなノードA,Bとし(図8のS0)、これらノードA,Bについて図8の手順を行って先祖・子孫関係を調べる。ノード31、32は同じクラスタに属し、先祖・子孫関係にある(図8のS11、S13)。またこれらのノードは参照ノードでない(図8のS14の判定結果が否定)。したがって、ノード31はノード32の先祖であることが分かり、ノード32はノード46の先祖であるので、最終的に検査対象のノード46とノード31は先祖・子孫関係にあると判定される。ここで検索処理を終える。
更に第3の例として、実ノード13と実ノード46の先祖・子孫関係の判定処理の流れを説明する。
クラスタ検索部24は、ノード13とノード46がそれぞれクラスタC0とC8に属し、同一のクラスタに属しないことを求める(図8のS11)。そこで、ノード13、46が属するクラスタを参照する参照ノードを辿り、直近の共通する先祖クラスタ中のノードを取得する。それぞれクラスタの系列はC0(13)→C2(10)→C12(60)、及びC8(46)→C11(47)→C12(62)であるので、前述同様にして直近の共通する祖先クラスタはC12と判明し、C12内での注目ノードはノード60,62になる(図8のS12)。そして、クラスタ検索部24は、先祖・子孫判定部26に、ノード60と62を対象として先祖・子孫関係判定(図7)を行わせ、この結果ノード60、62は先祖・子孫関係にあることが判明する(図8のS13)。ここで、先祖側のノード60は参照ノードであるので、クラスタ検索部24は、当該先祖側ノード60の直近の子孫ノード62が参照するクラスタC11のルートノード35を取得し、更にノード35は参照ノードであるので、ノード35が参照するクラスタC6のルートノード30を取得して、その親ノード16を取得する(図8のS15)。このノード16は実ノードであるので、これを新たなノードBとする。また、検索対象として指定されたノード13及び46のうち、先祖側の注目ノード60に対応するノード13を、新たなノードAとする。
そして、クラスタ検索部24は、それら新たな対象ノードA,Bであるノード13,ノード16について、図8の手順を実行する。ノード13,16はそれぞれクラスタC0、C3に属しており同一クラスタには属さない(図8のS11)。そこでクラスタ検索部24は、ノード13とノード16が属するクラスタを参照する参照ノードを辿り、直近の共通する先祖クラスタ中のノードを取得する。それぞれクラスタ系列はC0(13)→C2(10)→C12(60)、及びC3(16)→C2(17)→C12(60)であるので前述同様の方法でC2が直近(最下位)の共通クラスタであり、その共通クラスタ内の注目ノードがノード10、17であることをつきとめる(図8のS12)。次に、それらノード10,17を対象として、先祖・子孫判定部26が先祖・子孫関係の検索処理(図7)を実施し、その結果両ノードが先祖・子孫関係にあると判定される(図8のS13)。ここで、注目ノードのうちの先祖側のノード10は参照ノードであるので、クラスタ検索部24は、当該ノード10の直近の子孫ノード17が参照するクラスタC3のルートノード3を取得し、ルートノード3の親ノード2を取得する。ノード2は実ノードである。
次に、クラスタ検索部24は、このノード2と、検索対象のノードのうちの先祖側であるノード13とを対象として、図8の処理を再び行う。ここで、ノード2,13は同一クラスタC0に属しているので、クラスタ検索部24は、先祖・子孫判定部26に判定を行わせる。この判定の結果、結果ノード13,2は先祖・子孫関係に無いことが判明し、ステップS13により、検索対象のノード13とノード46とは先祖・子孫関係に無いことが最終的に判明する。
<処理に要する計算量>
ノード13とノード46の先祖・子孫関係判定を行うとき、階層的なクラスタ構造を用いた本実施形態の検索処理を用いず、単にノード群がなす木構造のみ(すなわち図8の第1層における実ノード間の関係のみ)を用いて検索を行う場合を考える。この場合、ノード46から木構造のルートノードまで14回のノード移動を行わねばならない。このようにルートノードまで移動する経路にノード13が現れないことで、初めてノード13がノード46の先祖でないことが判明する。
これに対し、この実施形態の仕組みを使った場合、最上位クラスタ(第3層)で1回(ノード62→60)、次位のクラスタ(第2層)で1回(ノード17→10)、最下位(第1層)のクラスタで2回(ノード2→0)と、合計4回のノード移動を行えば、先祖・子孫関係が判別される。
より一般的に説明すると、この実施形態で用いるクラスタの階層数Lは実ノード数Nとクラスタあたりのノード上限数Tを使ってL=floor(log(N/T)+2)と表せる。floor()は小数点以下を切り捨てる床関数である。ノード数Nの増加に対してlogNのオーダーで階層Lが増加する。図8のS12は、2つのノードが同一クラスタに納まるまで上位クラスタ中の参照ノード取得を繰り返す。この処理は最大で階層Lの回数分繰り返す。また図8のS13(すなわち図7の処理)の処理時間は1クラスタ中のノード数上限数Tに依存する。よって、この実施形態の方法での検索時間は、階層数Lと、1つのクラスタ内のノード上限数Tにより決まる。従って、この方法は、実ノード数Nの増加に対して検索時間が増加しにくい方法であると言える。また、この方法では、階層Lとクラスタ内ノード上限数Tにより最遅の検索時間が決まるので、木構造上の検索対象の2ノードが近い場所にあっても、離れた場所にあっても、変動の小さい一定範囲内の検索時間が見積もられる。
[変形例]
上述の実施形態ではクラスタ分割を行った際、分割により新しく生成されたクラスタを参照する参照ノードを上位クラスタに追加した。これに対し、変形例ではクラスタを分割する際、元のクラスタから分割により取り出された新たなクラスタの部分木が元のクラスタの部分木にて占めていた位置に、その新たなクラスタを参照する参照ノードを追加する。ここで、分割により取り出された新たなクラスタの部分木が元のクラスタの部分木にて占めていた位置とは、元のクラスタ内のノード位置であり、かつ当該新たなクラスタの根ノードの親ノード(これは元のクラスタ内のノードである)の子となる位置である。したがって、この実施形態では、分割により生成された新たなクラスタを参照する参照ノードは、当該新たなクラスタの親クラスタ(すなわち元のクラスタから新たなクラスタを除いたもの)に追加されることになる。
この変形例のための装置構成は、図1に示したものと同様でよい。また、クラスタ保持部20が保持する実ノード情報42,クラスタ情報52及び参照ノード情報62のデータ構造は、図2に示したものと同様でよい。変形例において実施形態と異なるのは、クラスタ構成部18の処理の内容であり、他の構成要素については実施形態の場合と同様でよい。
以下、変形例における各フェーズの処理について説明する。
<ノードの登録>
実ノードの登録処理は、上述実施形態と同じでよい。
<クラスタの分割>
クラスタ構成部18は、クラスタを分割する場合、元のクラスタから分割した新たなクラスタを参照する参照ノードを、元のクラスタ内の、当該新たなクラスタが占めていた位置に入れる。すなわち、クラスタ構成部18は、新たなクラスタのクラスタ情報52を作成すると共に、その新たなクラスタを参照する参照ノードの参照ノード情報62を作成し、元のクラスタのクラスタ情報52の[保持するノード集合の情報」から新たなクラスタに含まれるノードを削除し、代わりにその参照ノードを追加する。
図3Aに例示するように、実ノードの追加により、あるクラスタ中のノード数が上限値(この例では10)に達したらクラスタを分割する(図9A参照)。実施形態の場合と同様、クラスタ分割部16が、元のクラスタ内のノード数のなるべく半分に近いところで分割する。図9Aの例ではノード5のところで分割すると、分割後の各部分木のノード数が元のちょうど半分になる。そこで、ノード5をルートノードとする部分木を元のクラスタC0から分割して新たなクラスタC1とする。
この分割の際、クラスタ構成部18は、元のクラスタC0の中のノード5が存在した場所に、新たなクラスタC1を参照する参照ノード10を追加する。図9Aでは、この参照ノード10とクラスタC1との対応関係が破線で示されている。また、このように分割されても、ノード4と5の間の親子関係は維持される(図では実線で示している)。
このようにしてできたクラスタC1はクラスタC0の参照ノード10に参照されているので、クラスタC0はクラスタC1の上位クラスタ、クラスタC1はクラスタC0の下位クラスタの関係になる。また、クラスタC1のノード5の親ノードはクラスタC0のノード4であるので、クラスタC0はクラスタC1の親クラスタ、クラスタC1はクラスタC0の子クラスタという関係も併せ持つ。
このように、変形例では、分割により生成された子クラスタを参照する参照ノードが親クラスタに入るので、クラスタ同士の親子関係がすなわちクラスタ同士の上位・下位の関係となる。
この分割の後、クラスタC0に更にノードが追加され、クラスタC0内のノード数がノード上限数10に再び到達した状態を図9Bに示す。この場合、クラスタ分割部16は、ノード3をルートとする部分木をクラスタC0から分割すればよいと判定する。クラスタ構成部18は、ノード3をルートとする部分木(すなわち新たなクラスタC2)をクラスタC0から削除し、クラスタC0においてノード3が存在した箇所に、分割により生じた新たなクラスタC2を参照する参照ノード15を挿入する。クラスタC2には1回目のクラスタ分割で生成された参照ノード10が含まれる。この分割の結果を図9Cに示す。
<先祖・子孫関係検索>
この変形例では、クラスタの上位・下位関係がクラスタの親子関係へと縮退しただけであり、上位・下位の関係の情報は存在しているので、先祖・子孫関係の検索には、実施形態と同じく、図8及び図7に示した手順を実行すればよい。
処理の具体例を、図9Cの木構造を例にとって説明する。
第1の例として、その木構造中の実ノード9と実ノード12とが検索対象ノードとして指定された場合を考える。以下では簡単の為、ノード9を子孫側候補とした場合の処理の流れを説明するが、実際はノード12を子孫側候補とした場合の処理も同様に行う。
この例では、ノード9はクラスタC1に、ノード12はクラスタC0に属しており同一のクラスタに無い(図8のS11)。そこで、クラスタ検索部24は、ノード9、12が属するクラスタを参照する参照ノードをそれぞれ辿り、直近の共通する先祖クラスタ中の参照ノードを取得する。ここで、ノード9に対するクラスタ系列はC1(9)→C2(10)→C0(15)である。一方、ノード12が属するクラスタC0を参照する参照ノードが存在しない(C0はルートクラスタ)ので、ノード12に対応するクラスタ系列はC0(12)となる。
実施形態と同様にして、両系列で共通する最下位のクラスタを求める。この例では、クラスタC0がその最下位の共通クラスタであることが分かり、その共通クラスタ内での注目ノードは15、12であると求められる(図8のS12)。なお、図8のS12では、判定対象の実ノードのうちの一方が共通クラスタに含まれる場合、その実ノード自身を注目クラスタとする。なお、判定対象の2つの実ノードの両方が同じクラスタに含まれる場合は、S11からS13に進むので、ステップS12の処理は行われない。先祖・子孫判定部26が、それら注目ノード15、12に対して先祖・子孫関係の有無を判定する。この結果、先祖・子孫関係に無いことが分かる(図8のS13)ので、最終的に判定対象のノード9と12とは先祖・子孫関係に無いと判定される。
<処理に要する計算量>
変形例で生成されるクラスタの数Cは、実ノード数Nとクラスタあたりのノード上限数Tを使うとC=floor(N/T+1)で表せる。floor()は小数点以下を切り捨てる床関数である。この式から分かるように、ノード数Nの増加に対してNのオーダーでクラスタ数Cが増加する。変形例では図8のS12により2つの注目ノードが同じクラスタに納まるまで親(上位)クラスタ中の参照ノードの遷移を繰り返し、同じクラスタ内では図8のS13によりクラスタ内のノードを遷移する。従ってクラスタ数Cとクラスタ内ノード数により最遅の検索時間が決まる。よって変形例と比較して木構造のノード数増加による検索時間への増加影響が大きい。また、検索対象ノード間の距離が大きくなるほど、検索時間が長くなる傾向を持つ。
しかし、変形例は、クラスタの上位・下位関係を用いるので、実ノードの親子関係のみから検査対象ノード間の先祖・子孫関係を判定するよりも、計算量は少なくて済む。
また、参照ノードの数に着目すると、この実施形態は、実施形態の第2層のクラスタ群がもつ参照ノードと同じ数の参照ノードを持つ。しかし、実施形態の第3層以上の階層にある参照ノードに相当するノードは、変形例では生成しない。したがって、必要な記憶容量は上記実施形態よりも少ない。
[第2の変形例]
上述の変形例を改良した第2の変形例を以下に説明する。第2の変形例のための装置構成は図1に示したものでよい。この改良例は、クラスタ構成部18の処理内容が上述の変形例と異なるが、他の要素の処理内容は上位変形例及び実施形態と同様でよい。
以下、この改良例における各フェーズの処理を説明する。
<ノードの登録>
実ノードの登録処理は、上述実施形態と同じでよい。
<クラスタの分割>
上記変形例では、図9B及び図9Cに示す通り、クラスタC0をノード2と3の間で分割してクラスタC2を新たに生成する際に、ノード3をルートとする部分木に含まれる参照ノード10を新たなクラスタC2に含めた。
これに対し、この改良例では、図10Aに示す通り、参照ノード10を分割元のクラスタC0に残し、新たなクラスタC2からは除いた。
なお、この改良例では、参照ノード10をクラスタC0に残すので、クラスタC0の分割位置の決め方が以下の2つの点で上記変形例と異なる。
(1)参照ノードをまたいで部分木のノード数をカウントしない。
(2)クラスタ内ノード上限数の半分からの距離が同じ場合は、部分木に参照ノードを含まない方を分割対象として選択する。
この決め方により、図10Aの例では、ノード1と2の間でクラスタを分割している。
分割により生成された新たなクラスタC2を参照する参照ノード15は、元のクラスタC0においてクラスタC2の部分木が占めていた位置(すなわち元のクラスタC0内の、ノード1の子となり且つノード10の親となる位置)に挿入される。したがって、参照ノード10は参照ノード15の子となる。
クラスタ構成部18は、上述のような分割後のクラスタC0,C2が構成されるよう、クラスタC2のクラスタ情報52と参照ノード15の参照ノード情報62を生成し、更にクラスタC0のクラスタ情報52(特に「保持するノード集合の情報」)と参照ノード10の参照ノード情報62(特に親ノード番号)を修正する。
クラスタ分割後の図10Aの木構造では、参照ノード10がクラスタC1を参照していることから、クラスタC0はクラスタC1の上位クラスタ、クラスタC1はクラスタC0の下位クラスタという関係にある。同様にクラスタC0はクラスタC2の上位クラスタ、クラスタC2はクラスタC0の下位クラスタの関係にある。また、ノード5の親ノードはノード4であるので、クラスタC2はクラスタC1の親クラスタ、クラスタC1はクラスタC2の子クラスタの関係にある。同様にクラスタC0はクラスタC2の親クラスタ、クラスタC2はクラスタC0の子クラスタの関係にある。従ってクラスタC2、C1を参照する参照ノード15、10の親子関係はクラスタの親子関係に対応したものになる。
図10Bに、更に実ノードが増えてクラスタ分割が繰り返された結果、クラスタC0のノードが参照ノードにより飽和(ノード上限数に到達)した状態の例を示す。この場合は参照ノードも分割対象となる。この例では、最も分割に適したノードとして参照ノード30が選択され、クラスタC0内の参照ノード30をルートとする部分木が、新たなクラスタC10としてC0から分割される(図10C参照)。この場合、新たなクラスタC10を参照する参照ノード45を、クラスタC0内でそのクラスタC0の部分木が占めていた位置に挿入する。
<先祖・子孫関係検索>
この第2の変形例でも、クラスタの上位・下位関係がクラスタの親子関係へと縮退しただけであり、上位・下位の関係の情報は存在しているので、先祖・子孫関係の検索には、実施形態と同じく、図8及び図7に示した手順を実行すればよい。
例えば、図10Aにおいて、実ノード9と実ノード12とが先祖・子孫関係にあるか調べる場合の処理の例を以下に示す。この例では、ノード9はクラスタC1に、ノード12はクラスタC0に属しており同一のクラスタに無い(図8のS11)。そこでノード9、12が属するクラスタを参照する参照ノードを辿り、直近の共通する先祖クラスタ中のノードを取得する。上記変形例と同様、ノード9に対応するクラスタ系列はC1(9)→C0(10)であり、ノード12に対応するクラスタ系列はC0(12)であることが分かる。両系列で共通する最下位のクラスタはC0となる(図8のS12)。また、その共通クラスタC0内の注目ノードはノード10と12であることも求められる。先祖・子孫判定部26がそれら注目ノード10と12に対して先祖・子孫関係の有無を判定し、この結果それら両者には先祖・子孫関係に無いことが明らかとなる(図8のS13)。以上から判定対象である実ノード9と実ノード12は先祖・子孫関係に無いことが判定される。
もう1つの例として、図10Aの木構造において実ノード9と実ノード14が先祖・子孫関係にあるか調べる場合を以下に示す。ノード9、14はそれぞれクラスタC1、C2に属しており同一のクラスタに無い(図8のS11)。そこでノード9、14が属するクラスタを参照する参照ノードを辿り、直近の共通する先祖クラスタ中のノードを取得する。これにより、ノード9、14に対応するクラスタ系列はそれぞれC1(9)→C0(10)、C2(14)→C0(15)であることが求められる。これら両系列の比較から、直近の共通する先祖クラスタはC0であることが分かり、注目ノードは10、15であることが求められる。先祖・子孫判定部26が、それら注目ノード10、15に対して先祖・子孫関係の有無を判定し(図8のS13)、それら注目ノード15、10は先祖・子孫関係にあることが判明する。そこで、クラスタ検索部24は、注目ノード15,10の内先祖側であるノード15は参照ノードであるので(図8のS14)、当該注目ノード15の直近の子孫であるノード10が参照するクラスタC1のルートノード5の親ノード4を取得する(図8のS15)。取得したノード4は実ノードなので、クラスタ検索部24は、ステップS0に戻り、新たに取得した実ノード4と、判定対象のうちの先祖側である実ノード14と、を判定対象として、図7及び図8に例示した処理を繰り返す。この場合、実ノード14の方が実ノード4の先祖側であることを前提として処理を行えばよい。この例では、ノード4、14は同一のクラスタC2に属しているので(図8のS11)、図8のS13に進み、先祖・子孫判定部26によりそれらノード4,14間に先祖・子孫関係があるかどうかを判定する。この場合、図10Aの例では、ノード4はノード14の親なので一見先祖・子孫関係があるように見えるが、上述のようにこの繰り返しではノード14の方がノード4よりも先祖側であることが前提であり、ノード4がノード14の親であるという関係はこの前提に矛盾する。したがって、ノード4とノード14とは先祖・子孫関係にないと判定される。図7の手順に即して言えば、子孫側であるノード4を起点として図7の処理により部分木を遡っていっても、ノード14には到達できないので、ノード4と14とは先祖・子孫関係に無いと判定されることになる。以上から判定対象であるノード9、14は先祖・子孫関係に無いと判定される。
ノード9と12の先祖・子孫検索において、上述の変形例ではクラスタC1からクラスタC2の参照ノード10を取得することと、更にクラスタC0の参照ノード15を取得することとで、合計2回の参照ノード取得を行った。これに対し、この変形例2ではクラスタ階層が少なくなるようにクラスタ分割を行っている成果として、クラスタC1からクラスタC0の参照ノード10の1回のみの取得で済んでいる。
このように、変形例2では、クラスタの親子関係の層をなるべく増加しないようにクラスタ構成を行っているので、上記変形例よりも早く同一クラスタに到達できることが期待できる。
<コンピュータへの実装>
以上に例示したシステムは、例えば、汎用のコンピュータに上述の各機能モジュールの処理を表すプログラムを実行させることにより実現される。ここで、コンピュータは、例えば、ハードウエアとして、CPU等のマイクロプロセッサ、ランダムアクセスメモリ(RAM)およびリードオンリメモリ(ROM)等のメモリ(一次記憶)、HDD(ハードディスクドライブ)を制御するHDDコントローラ、各種I/O(入出力)インタフェース、ローカル・エリア・ネットワークなどのネットワークとの接続のための制御を行うネットワークインタフェース等が、たとえばバスを介して接続された回路構成を有する。また、そのバスに対し、例えばI/Oインタフェース経由で、CDやDVDなどの可搬型ディスク記録媒体に対する読み取り及び/又は書き込みのためのディスクドライブ、フラッシュメモリなどの各種規格の可搬型の不揮発性記録媒体に対する読み取り及び/又は書き込みのためのメモリリーダライタ、などが接続されてもよい。上に例示した各機能モジュールの処理内容が記述されたプログラムがCDやDVD等の記録媒体を経由して、又はネットワーク等の通信手段経由で、ハードディスクドライブ等の固定記憶装置に保存され、コンピュータにインストールされる。固定記憶装置に記憶されたプログラムがRAMに読み出されCPU等のマイクロプロセッサにより実行されることにより、上に例示した機能モジュール群が実現される。なお、それら機能モジュール群のうちの一部又は全部を、専用LSI(Large Scale Integration)、ASIC(Application Specific Integrated Circuit、特定用途向け集積回路)又はFPGA(Field Programmable Gate Array)等のハードウエア回路として構成してもよい。