大滝本4.10

午前試験免除制度対応!基本情報技術者試験のeラーニング【独習ゼミ】
まきさん  
(No.1)
持っている方いらっしゃるなら教えてください。
aに入るのtemp.nextなのは何故なのでしょうか。
BからDにつなげるイメージが付きません

current.nextはCなのでCから矢印が出ると思いますが・・・
2024.02.14 23:16
まきさん  
(No.2)
a) temp.next←curent.next ならCからBにつなげるイメージしか持てないのですが・・・
①BからDに行くイメージが湧きません
2024.02.15 11:57
SUTさん 
(No.3)
こんにちは。
私、この問題は最初盛大な勘違いしておりました。

何回か解いているうちに自身の勘違いに気づいた点も含めてお伝えさせていただければと思います。

今回は単方向リストのCのリストを先頭に持ってくる処理になるのでkeyは「C」と定義してトレースしていきます。
※前提として大域変数first(リストの先頭の要素)が定義されてます。
※一部略称を使用してます。

以下の箇所に注目してください。

while(currが未定義ではない)
if(keyがcurr.keyと等しい)
if(currがfirstと等しくない)

ここの部分なのですが、2行目の条件を満たさなかった時点で3行目の処理は行われず、
更に下にある「else」の処理に移行します。
何故なら「if(currがfirstと等しくない)」は「if(keyがcurr.keyと等しい)」に内包されているからです。
よって「if(keyがcurr.keyと等しい)」を満たさない時点でif内にある処理は行われません。

つまり1回目の処理は、「else」の処理になります。

temp←curr(first(A))
curr←curr.next(B)

temp(A) curr(B)

While文なので2回目の処理のためにWhileの先頭に戻ります。

「if(keyがcurr.keyと等しい」⇒key=C curr.key=B

条件に合致しないため再びelseの処理に向かいます。

temp←curr(B)
curr←curr.next(C)


temp(B) curr(C)

While文なので3回目の処理のためにWhileの先頭に戻ります。

「if(keyがcurr.keyと等しい)」⇒key=C curr.key=C

条件を満たしましたので、次の条件式の処理に移ります。

「if(currがfirstと等しくない)」⇒curr(C)、first(A)

条件を満たしましたので、次の条件式の処理に移ります。


①「a」←curr.next
②curr.next←「b」
③first←「c」

「a」「b」「c」に入る変数を考えていきます。

・「a」
→現在currは「C」ですので元のリストでcurr.nextは「D」になります。
テキストの図を見ていただくと分かるかと思いますが、処理後の図では「D」は「B」の後ろに来ます。
現在「B」は変数「temp」に格納されておりますので、これの次に来る必要がありますので、
「a」には「temp.next」が入ります。

・「b」
→現在currは「C」です。処理後の図では「C」の後に「A」が来ています。
「C→A」と続く必要がありますのでcurr「C」の次のcurr.nextには大域変数として定義されている「first」が入ります。

・「c」
→firstにはリストの先頭要素が格納されます。つまり「curr」(C)が入ります。

全ての処理を満たす選択肢は「エ」しかないので、
答えはは「エ」になります。

参考にしていただければ幸いです。
分かりづらかったらすみません。
2024.02.15 13:33
まきさん  
(No.4)
この投稿は投稿者により削除されました。(2024.02.15 19:41)
2024.02.15 19:41
まきさん  
(No.5)
>SUTさん
大変詳しい解説ありがとうございました。
ただ1点分からない点があります。

Cがキーで前に行きCAB→DEとなるから、
temp.next←curr.nextとなるんですが
    B        D

この書き方ではBからDに変えるイメージが湧きません

temp.next←curr.nextとなるなら
    B         D
current.next←first
   D           A
first←current
   C     C

ということですか?やっていることが意味不明です
2024.02.15 19:44
SUTさん 
(No.6)
この投稿は投稿者により削除されました。(2024.02.15 21:16)
2024.02.15 21:16
SUTさん 
(No.7)
すみません。あまり説明がうまくないのですが、もう一度掻い摘んで説明します。

「a」←curr.next
curr.next←「b」
first←「c」

上記の処理を行う前の段階で、変数が以下のようになっているのは分かりますか?

first=A
temp=B
curr=C

この前提の元、1つずつ処理を行います。

★「a」←curr.next
→curr.nextは「D」になります。
変更後のリストでは「D」は「B」のnextです。
現在「B」はどこに入ってるかというと「temp」です。
つまり「temp」のnextで「D」を指定します。
よって、「temp.next←curr.next」になります。


★curr.next←「b」
→curr.nextはcurrである「C」の次に置くべき変数を指定します。
変更後のリストでは「C」の次には「A」が来てますので、curr.nextには「first」を入れます。


★first←「c」
→firstには単方向リストの先頭の要素が入ってます。
変更後のリストでは、最初が「C」になるので、firstには「curr」を入れます。



>>temp.next←curr.nextとなるなら
    B         D

→これはtemp(B)のnextに、curr.next(D)を定義するということです。BがDで上書きされるわけではありません。

>>current.next←first
   D           A

→上と同じくcurr(C)のnextにfirst(A)を定義します。

>>first←current
   C     C
→firstはまだ「A」です。
first(A)だったものを「C」にするということです。
2024.02.15 21:17
まきさん  
(No.8)
>SUTさん
なんど解説ありがとうございました。

first=A
temp=B
curr=C    ここまではOKです

★「a」←curr.next
→curr.nextは「D」になります。
変更後のリストでは「D」は「B」のnextです。
現在「B」はどこに入ってるかというと「temp」です。
つまり「temp」のnextで「D」を指定します。    (ここまでOK)
ーーーーーーーーーーーーーーーーーーーーーーー
よって、「temp.next←curr.next」になります。
            ↓   ↓     ↓        
            B   ( D)  ←D
                ↑ここにDをつなげる
呼出前はnextの部分はC

>これはtemp(B)のnextに、curr.next(D)を定義するということです
    えっとリストなのでB(D)

    ↑nextの部分ですか
bはCが動いて最初にくるから次はAになる

>>first←current
    A      C        
cはAだったものをCに切り替えするという解釈ですか?

解説ありがとうございました。考えるだけ本当に嫌になってくる問題ですね。
2024.02.15 22:13
jjon-comさん 
FE ゴールドマイスター
(No.9)
> first=A
> temp=B
> curr=C
> ここまではOKです

いいえ、OKではないです。
「ポインタ」と「ポインタが指す値」を区別していません。

以下では、ポインタが次のような番地を指すものと仮定して説明します。
表示が横ズレして見にくいなら等幅フォントのテキストエディタなどに貼り付けてください。
        .key  .next
        +―+――+
1000番地|A|2000|
        +―+――+
2000番地|B|3000|
        +―+――+
3000番地|C|4000|
        +―+――+
4000番地|D|5000|
        +―+――+

first, temp, curr はすべてポインタですから、
first=1000, temp=2000, curr=3000 です。
first=A, temp=B, curr=C ではありません。

A、B、C である実体は、
first.key つまり「first=1000が指す番地のkey」が A、
temp.key つまり「temp=2000が指す番地のkey」が B、
curr.key つまり「curr=3000が指す番地のkey」が C です。

----
> よって「temp.next←curr.next」になります。

というのは、
curr.next つまり「3000番地のnext」つまり 4000(次の図の☆印)を、
temp.next つまり「2000番地のnext」(次の図の★印)に代入したのです。
              .key  .next
              +―+―――+
      1000番地|A|2000  |
              +―+―――+
temp=2000番地|B|4000★|
              +―+―――+
curr=3000番地|C|4000☆|
              +―+―――+
      4000番地|D|5000  |
              +―+―――+
これにより、ポインタで結ばれた連結リストは、
(firstは1000番地)→ 1000番地のA → 2000番地のB → 4000番地のD となって
リスト要素C は リストの連鎖から外れたことになります。

----
私はその参考書を持っていないので、以降はご自分で考えてみていただけますか。
ポインタ変数には番地が格納されている、ことが分かったなら、
ややこしい問題ではあるだろうけれど、
> 考えるだけ本当に嫌になってくる問題
という思いは軽減されるように思います。
2024.02.15 23:33
SUTさん 
(No.10)
この投稿は投稿者により削除されました。(2024.02.16 07:52)
2024.02.16 07:52
SUTさん 
(No.11)
>>jjon-comさん
細かく補足いただきありがとうございます。
説明を省略してしまったことでかえって分かりづらくしてしまったようです。
申し訳ございません。

尚、問題文では以下のようにリストが構成されております。

next→次の要素の参照
key→要素に格納する文字(探索のキー値)
Value→要素に格納する正の整数値(要素の値)

nextが次の番地になるので「Aが格納されている番地」、「Cが格納されている番地」等と表記したほうが良かったかもしれません。

今後問題を解く際の参考にいたします。
ありがとうございました。
2024.02.16 08:03
jjon-comさん 
FE ゴールドマイスター
(No.12)
この投稿は投稿者により削除されました。(2024.02.16 08:49)
2024.02.16 08:49
jjon-comさん 
FE ゴールドマイスター
(No.13)
No.11を拝見した上で補足です。

その参考書に「ポインタ」という用語が登場しないのなら
No.9 の「ポインタ」を「参照」という用語に置き換えてください。

ちなみに,
> Value→要素に格納する正の整数値(要素の値)
は,このスレッドの流れの中で登場していませんでしたので,その存在を私はいま知りました。
2024.02.16 08:50
SUTさん 
(No.14)
>>jjon-comさん

私も参考書が手元にある大前提で不明と思われる部分だけを書いてしまいましたが、この問題は処理の最後に

return curr.value(厳密には「return current.value」)

と記述があるため

ここでcurrのvalueを出力するという処理が行われて、プログラムが終了します。
2024.02.16 09:04
まきさん  
(No.15)
>jjon-comさん
詳細に解説ありがとうございました。
ポインタをよく理解してないから自分もこんなにも混乱していたことに気づけました。

> 考えるだけ本当に嫌になってくる問題という思いは軽減されるように思います。
少しだけ楽になりましたです。リストの問題が全般的にあまり得意ではないから
2024.02.16 10:49
boyonboyonさん 
FE ブロンズマイスター
(No.16)
こちらの掲示板に興味を持ったので考えてみました。
はじめより、情報量がかなり増えたので推察しやすくなりました。
自分の考えたことを述べさせていただきます。

アドレス  1
要素  A(key,value):keyは、Aとかぶります。
次の要素の参照(next)  2
の時、略記として1A-2と表記します。

この問題の初期設定は、
1A-2
2B-3
3C-4
4D-5
5E--
first=1  (リストの先頭の要素の参照かな)
プログラムは、
keyが、Cである要素を取り出しリストの先頭に持ってくる。
抜けたところは、前に詰める。
という処理をしていると考えます。
*本がなく、こちらの掲示板を見ての推測です。

結果としては、
1A-2
2B-4*
3C-1*
4D-5
5E--
first=3*
というリストができると思います。
変化しているのは、*のところです。

プログラムの流れとしては、
currを先頭から順にたどっていき、curr.keyとkeyが一致したら、参照の付け替えを行うということかと思います。
やってみます。
key←C
curr←first=1  不適
curr.nextは2なので、
temp←1 (currの1つ前の要素の参照を保持するため)
curr←2
curr.key=B  不適
temp←2
curr←3
curr.key=C  適なので参照を付け替えます。

「a」←curr.next
curr.next←「b」
first←「c」
の手順ですが、

初期状態
1A-2
2B-3*  ここがtemp
3C-4*  ここがcurr、curr.nextは、4
4D-5
5E--
first=1*

処理の流れ
1A-2
2B-4*  curr.nextの4が、temp.nextに入る。①  3Cを抜かす。
3C-1*  curr.nextにfirst(1)が入る。②  元の先頭を後ろに従え、☆
4D-5
5E--
first=3*  currが入る。③  ☆自分が先頭になる。
①②③の順に処理が行われます。順番を変えると変になります。

こんな感じです。ABCDEだけで考えるより、自分ではわかりやすいと思います。
いかがでしょうか。
2024.02.16 11:06
まきさん  
(No.17)
>皆様
解説ありがとうございました。また分からないことがありましたご質問致します
よろしくお願いいたします。
2024.02.16 11:10

返信投稿用フォーム

スパム防止のためにスレッド作成日から30日経過したスレッドへの書込みはできません。

その他のスレッド


Pagetop