質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

6回答

3662閲覧

ある本で「削除が高速にできる双方向連結リスト」とあったのですが何故か?

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/06/01 01:13

双方向リストは一方向より早いのでしょうか?
それは何故でしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答6

0

双方向という事は前後へのリンク情報も保持しているという事なので削除対象が特定されている時点で削除物の前にあるデータと削除物の後にあるデータを連結して削除対象物をリストから除外するという整理操作がその場ですぐに解決できますが、例えば片方向(後方)の場合だと、削除対象が特定されていても削除物の前にあるデータは検索しないと特定できないので双方向の時に比べると検索コストが余計にかかってしまう理屈になります。

[例]
A→B→C から B を削除したい場合に
1.「Aの次がBである」を「Aの次はCである」に変更
2.「Cの前がBである」を「Cの前はAである」に変更(双方向の場合)
をしなくてはなりませんが、
・双方向ならBがAとCへのリンク情報を持っているのでBだけですぐにAとCを特定できる
・片方向ならBはCへのリンク情報しかもっていないのでAの特定には検索が必要
という違いがあります。

投稿2018/06/01 01:30

編集2018/06/01 01:38
HiroshiWatanabe

総合スコア2160

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

prev -> here -> next で現在hereをポイントしてて、hereを削除となると
削除要素のひとつ前:prevをポイントせにゃならんので速くはなさそう。

が、ゴマカシが許されるなら nextのナカミをhereにコピーしたのちnextを削除することで hereが削除されたようにみせかけることができます。
ただし、
1.コピーのコストが大きいと速くない(ポインタ張替えの方が速いなら、双方向の方が速いことになる)
2.末尾要素が削除できない

投稿2018/06/01 11:03

編集2018/06/01 11:05
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2018/06/01 11:36 編集

おお! その削除の方法は気付かなかったのでベストアンサーにしようかと思ったのですがプログラムの他のところにhere,nextをポイントして使ってる部分があったらバグになっちゃうのかと思ったのですがどうでしょうか。
episteme

2018/06/01 12:55

ですね、どっかヨソでnextをポイントしてる誰かさんに迷惑をかけることになります。 とはいえ、双方向でも here をポイントしてる誰かさんに迷惑をかけるわけだし。
yumetodo

2018/06/01 16:42

いや、消す要素が全体に比べて少ないものの膨大な場合は削除処理を非同期化できるというメリットが・・・
yumetodo

2018/06/02 10:58

あーいや、なんでもない、間違って読んでいた
guest

0

一方向は逆方向にたどれないし、削除と言ってもリンクの付替えだけで済むから。

投稿2018/06/01 01:19

y_waiwai

総合スコア87747

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

解決済みですが。

皆様おっしゃられる通り、以下のようなリストを考えます。
head->p1->・・・->p11->p12->p13->・・・
ここでp12を削除する場合を考えると、p11のポインタを書き換える必要があります。しかし、フォーカス(巡回用ポインタ)がp12を指示しているならば、先頭から辿らないとp11のポインタを変更できないので手間がかかります。

ただし、これはフォーカスの運用次第です。

フォーカスを二つ使うとか、先読運用(例えばp11を指しているときにp12に対する処理を行う。)とか、解決する方法がないわけではありません。

蛇足

非常に変則な形ですが、フォーカスだけ双方向ポインタをもち、これを中心にリストの向きを変更していくといったリストの使い方もあります。

head<-p1<-・・・<-p11<-[focus]->p12->p13->・・・

これはメモリ容量が小さいときに使われていた小手先の技術なので推奨はしません。読み取りだけでもデータ改変が必要なので、現在はむしろ悪手です

投稿2018/06/01 15:21

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

単方向リストで、「ポインタが指している要素を削除する」という関数を実装することを考えてみると分かるかと。根本から、その要素までず~~~と辿らないといけない。

投稿2018/06/01 04:09

otn

総合スコア84499

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

多分に推測になりますが、双方向連結リストで「削除が高速にできる」の比較対象は一方向リストではなく、配列などリストでないデータ構造なのではないかと思います。

配列であれば途中の削除は「残りを全部ずらす」しかないのでリスト構造のほうが有利ですが、一方向リストに対しては優位になりません。

投稿2018/06/01 01:23

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2018/06/01 01:25

ただ、ポインタで指したような「この要素」を削除したいとなった場合は、双方向リストであればそこから両方向のポインタをたどって削除すればいいのに対して、一方向リストの場合は「前」がわからないので、リストを改めてたどる必要が出てきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問