教科書が間違っています。リストの最初のメンバーには使用可能な「前の」ポインターがないため、要素がチェーンの最初である場合は、要素を見つけてリンクを解除するために追加のコードが必要です(通常、要素の30%がチェーンの先頭です。 N = M、(N個のアイテムをM個のスロットにマッピングする場合。各スロットには個別のチェーンがあります。))
編集:
バックリンクを使用するよりも良い方法は、私たちを指すリンクへのポインターを使用することです(通常、リスト内の前のノードの->次のリンク)
struct node {
struct node **pppar;
struct node *nxt;
...
}
その後、削除は次のようになります。
*(p->pppar) = p->nxt;
また、このメソッドの優れた機能は、チェーンの最初のノード(ppparポインターがノードの一部ではないポインターを指している)でも同様に機能することです。
更新2011-11-11
人々は私の主張を理解できないので、私は説明しようとします。例として、ハッシュテーブルtable
(基本的にはポインタの配列)と多数のノードone
がありtwo
、three
そのうちの1つを削除する必要があります。
struct node *table[123];
struct node *one, *two,*three;
/* Initial situation: the chain {one,two,three}
** is located at slot#31 of the array */
table[31] = one, one->next = two , two-next = three, three->next = NULL;
one->prev = NULL, two->prev = one, three->prev = two;
/* How to delete element one :*/
if (one->prev == NULL) {
table[31] = one->next;
}
else {
one->prev->next = one->next
}
if (one->next) {
one->next->prev = one->prev;
}
これで、上記のコードがO(1)であることは明らかですが、厄介なことがあります。それでもarray
、とインデックスが必要な31
ので、ほとんどの場合、ノードは「自己完結型」であり、ノードへのポインタで削除できます。チェーンの最初のノードである場合を除いて、チェーンからのそれ。その後、を検索するために追加情報が必要になりtable
ます31
。
次に、ポインタからポインタへのバックリンクを使用した同等の構造を検討します。
struct node {
struct node *next;
struct node **ppp;
char payload[43];
};
struct node *table[123];
struct node *one, *two,*three;
/* Initial situation: the chain {one,two,three}
** is located at slot#31 of the array */
table[31] = one, one-next = two , two-next = three, three->next = NULL;
one->ppp = &table[31], two->ppp = &one->next, three->ppp = &two-next;
/* How to delete element one */
*(one->ppp) = one->next;
if (one->next) one->next->ppp = one->ppp;
注:特別な場合はなく、親テーブルを知る必要もありません。(ハッシュテーブルが複数あるが、ノードタイプが同じである場合を考えてみてください。削除操作では、ノードをどのテーブルから削除する必要があるかを知る必要があります)。
多くの場合、{prev、next}シナリオでは、二重リンクリストの先頭にダミーノードを追加することで、特殊なケースを回避できます。しかし、それも割り当てて初期化する必要があります。