この質問に対する私の2 番目の回答を見ることをお勧めします。しかし、私はこの答えが間違っていると言っているわけではありません。これも正しいです。
メモリ効率の良いリンク リストは、 XOR リンク リストとも呼ばれます。
それはどのように機能しますか
XOR (^) リンク リストは、ポインタnext
とback
ポインタを格納する代わりに、 1 つのnext
ポインタを使用してポインタとポインタの両方の仕事を行うリンクリストback
です。まず、XOR 論理ゲートのプロパティを見てみましょう。
|-------------|------------|------------|
| Name | Formula | Result |
|-------------|------------|------------|
| Commutative | A ^ B | B ^ A |
|-------------|------------|------------|
| Associative | A ^ (B ^ C)| (A ^ B) ^ C|
|-------------|------------|------------|
| None (1) | A ^ 0 | A |
|-------------|------------|------------|
| None (2) | A ^ A | 0 |
|-------------|------------|------------|
| None (3) | (A ^ B) ^ A| B |
|-------------|------------|------------|
例を挙げてみましょう。A、B、C、D の4 つのノードを持つ双方向リンク リストがあります。外観は次のとおりです。
ご覧のとおり、各ノードには 2 つのポインターと、データを格納するための 1 つの変数があります。したがって、3 つの変数を使用しています。
多数のノードを持つ双方向リンク リストがある場合、使用するメモリが多すぎます。より効率的にするには、Memory-Efficient Doublely Linked Listを使用します。
メモリ効率の高い双方向リンク リストは、XOR とそのプロパティを使用して前後に移動するために 1 つのポインターのみを使用するリンク リストです。
ここに絵の表現があります:
どのように前後に移動しますか?
一時変数があります (ノードにはなく、1 つだけです)。ノードを左から右にトラバースしているとしましょう。したがって、ノード A から開始します。ノード A のポインターには、ノード B のアドレスを格納します。次に、ノード B に移動します。ノード B に移動する間、一時変数にノード A のアドレスを格納します。
ノード B のリンク (ポインター) 変数のアドレスはA ^ C
です。前のノードのアドレス (A) を取得し、それを現在のリンク フィールドと XOR すると、C のアドレスが得られます。論理的には、次のようになります。
A ^ (A ^ C)
式を単純化してみましょう。次のような連想プロパティにより、括弧を削除して書き直すことができます。
A ^ A ^ C
これをさらに単純化することができます
0 ^ C
2 番目の (表に記載されている「なし (2)」) プロパティのためです。
最初の (表に記載されている「なし (1)」) プロパティのため、これは基本的に
C
これらすべてを理解できない場合は、単に 3 番目のプロパティ (表に記載されている「なし (3)」) を参照してください。
これで、ノード C のアドレスを取得しました。これは、戻る場合と同じプロセスになります。
ノード C からノード B に移動するとします。ノード C のアドレスを一時変数に格納し、上記のプロセスをもう一度実行します。
注:A
、B
、などはすべてC
アドレスです。明確にするように言ってくれたBathshebaに感謝します。
XOR リンク リストの短所
Lundin が述べたように、すべての変換は from/to で行う必要がありますuintptr_t
。
Sami Kuhmonen が述べたように、ランダムなノードだけでなく、明確に定義された開始点から開始する必要があります。
ノードをジャンプすることはできません。あなたは順番に行かなければなりません。
また、ほとんどの場合、XOR 連結リストは二重連結リストよりも優れているわけではないことに注意してください。
参考文献