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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

1回答

1955閲覧

Java Node作成について

coala

総合スコア8

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2021/05/03 04:24

編集2021/05/03 05:04

ダブルリンクドリストで最後に新しいノードを追加したいのですが、Nodeクラスのコンストラクターは一つしかありません。
Nodeクラスのコンストラクターを使ってどのように新しいノードを追加すればいいのでしょうか。

Node.java

public class Node { public Node next; public Node prev; private String t; public Node(Node next, Node prev, String token) { this.next = next; this.prev = prev; this.t = token; }

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

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

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

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

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

TakaiY

2021/05/03 04:57

Node.jsは関係ないので、消しておきましょう。
guest

回答1

0

ベストアンサー

末尾のノードのnextに何が設定されているのかわかりませんが、nullとしておきましょう。

  • 末尾のノードをつかまえる。Tとする。
  • 新規のノードを作成する。Nとする。
    nextはnull, prevにはTを指定する。
  • TのnextにNを設定する。

これでよいかと。


こんな感じ? 上に書いた通りですが。

java

1t = // リストの末尾 2 3Node n = new Node(null, t, "hoge") 4t.next = n

もとのリストがどのように表現されているかわからないので、とりあえず、末尾がわかっているとしときました。


質問でもらったソースをできるだけ生かせばこんな感じでしょうか。

python

1public boolean add(String obj) throws NullPointerException{ //boolean -> void 2 if(obj == null) { 3 throw new NullPointerException("obj cannot store a null reference!"); 4 } 5 else { 6 // currentの設定はここにあってはだめ。 7 Node newNode = new Node(null, null, obj); //このタイミングではではprevを決められないのでnullとしておく。 8 if(head == null) { 9 head = newNode; 10 tail = newNode; // tailの更新を追加。 空だったときはどちらも同じノードを指す。 11 // 単一ノードなので、newNodenのnextもprevもnullの儘 12 } 13 else { 14 Node current = head; //currentの設定はここに移動。 15 while(current.next != null) { 16 current = current.next; 17 } 18 current.next = newNode; 19 newNode.prev = current //ここでnewNodeのprevが設定できる。 20 tail = newNode; // tailは、最後のノードそのものを指している。 newNode.next ではrnullになっちゃう。 21 } 22 } 23 return true; 24}

さて、そもそもtailで末尾を持っているのだから、末尾を捜す処理は不要なので、こんな感じ。

python

1public boolean add(String obj) throws NullPointerException{ //boolean -> void 2 if(obj == null) { 3 throw new NullPointerException("obj cannot store a null reference!"); 4 } 5 else { 6 7 Node newNode = new Node(null, null, obj); 8 9 if(head == null) { 10 head = newNode; 11 tail = newNode; 12 } 13 else { 14 tail.next = newNode; 15 newNode.prev = tail; 16 tail = newNode; 17 } 18 } 19 return true; 20} 21

投稿2021/05/03 04:56

編集2021/05/04 03:43
TakaiY

総合スコア13847

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

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

coala

2021/05/03 05:08

早々にご回答ありがとうございます。 ダブルリンクドリストの初心者で申し訳ないのですが、コードで説明いただけると大変助かります。 よろしくお願い致します。
coala

2021/05/03 06:09

早々に追記ありがとうございます。 他のクラスでリストの末尾はNode tail;で定義してあります。 その場合、TakaiYさんのを参考にさせていただくと Node n = new Node(null, tail, "hoge"); tail.next =n; ありがとうございます。nextをnullで定義する発想がありませんでした。大変助かりました、ありがとうございます。
TakaiY

2021/05/03 06:14

よかったです。 tailが保持されているのであればさらに tail = n というふうにtailも更新しておく必要がありますね。
coala

2021/05/03 07:36

tailに対して新しいNodeを作成する必要があるということでしょうか。 tail.next = n;として上でその後 tail = n;が必要という理解でよかったでしょうか。 headも定義されているので私の中で以下のコードでダブルリンクドリストの最後に新しいノードが追加できると考えました。 どうでしょうか。もしよければコード見ていただけないでしょうか。 public void add(String obj){ Node current = head; Node newNode = new Node(null, current, obj); if(head == null){ head = newNode; } else{ while(current.next != null){ current = current.next; } current.next = newNode; } }
dodox86

2021/05/03 07:41

横からすみません。混乱させるつもりはありませんが、双方向リストでかつ明示的なheadがあるのであれば、headのprevで末尾のNodeを指すようにしておくことで、一発で最後のNodeに辿り着くことができます。
coala

2021/05/03 08:03

補足ありがとうございます。 tailのnextではなく、headのprev、確かにそうですね。 tail.nextとするとheadに戻ってしまうという理解でよかったですか。 dodox86さんのおっしゃられるようにコードを変更すると以下の理解であっていますか。 public void add(String obj){ Node current = head; Node newNode = new Node(null, current, obj); if(head.prev == null){ current = newNode; } }
TakaiY

2021/05/03 11:04 編集

まず、ノードを循環させる(headとtailをつなぐ)話は置いておきましょう。 3つ前のコードは前提が崩れています。 どこかでtailを保持しているのであれば、前に示したとおり、最後にNodeを追加したのであれば、そのtailが指しているものを更新する必要があるということです。 3つまえのコードは、taliは保持しておらず、currentが末尾になるまで回しています。 毎回そのように末尾を捜すのであれば、そもそも末尾は保持していないので、更新もいらなくなります。 前提が崩れればコードは変ります。 3番目のコードはいくつか問題があります。たとえば、 Node current = head; としていますが、headがnullだった場合、currentが更新されない場合があるので、後で例外が発生する可能性があります。ここを変えようとすると他も変えなければなりません。 headにリストの先頭を持っていて、リストが未生成の場合(head=null)のことも考えるのであれば、もっとロジックを検討する必要があります。 - headがnullなら、新規のノードを生成してそれをheadに入れて返す - headがnullでないなら、nextがnullになるまで辿って(=末尾を探して)新規ノードを先述のようにくっつける。 という処理になるでしょう。 dodox86さんの指摘のようにリストを循環させる方法もありますが、末尾の検出の方法がまったく異なり、また、ノードを追加するには、一度切り離して間に嵌め込む必要があるので、かなり複雑になります。 この場合もロジックはきちんと検討しなければうまく動きません。
dodox86

2021/05/03 10:10 編集

そうですね。TakaiYさんのコメントのように、まずはもとの考えのまま、一貫して完成させた方が良いと思います。(混乱させるかと思いましたが、大分惑わせてしまったようです。失礼しました)明示的にheadがある場合、headと言う特別なNodeがあるかたちでも、headは循環したリスト中のNodeのいずれかへの参照として別にとっておくかたちでも、様々な方法が考えられます。前提が崩れるのは確かなので、私の案は脇へおいてください。
coala

2021/05/04 02:37

詳細なアドバイスありがとうございます。 ご指摘いただいたようにコードを作成しました。 参照いただけないでしょうか。 public boolean add(String obj) throws NullPointerException{ //boolean -> void if(obj == null) { throw new NullPointerException("obj cannot store a null reference!"); } else { Node current = head; Node newNode = new Node(null, current, obj); if(head == null) { head = newNode;//headがnullなら、新規のノードを生成してそれをheadに入れて返す } else { while(current.next != null) { current = current.next; } current.next = newNode;//headがnullでないなら、nextがnullになるまで辿って(=末尾を探して)新規ノードを先述のようにくっつける。 tail = newNode.next;//どこかでtailを保持しているのであれば、前に示したとおり、最後にNodeを追加したのであれば、そのtailが指しているものを更新する } } return true; 最後のtailの部分ですが、 public Node head; private Node tail; public int data; として定義しています。
TakaiY

2021/05/04 03:34

- headがnullだったときにcurrent.nextにアクセスしたところで落ちます。 前にも指摘しています。currentは末尾を捜すために必要なだけなので、elseに入れればよい。 - tailの更新が漏れているし、間違えています。 そもそも、tailがあるのであれば、currentのループは不要です。どこかから流用したコードと思いますけど。 コードの修正版を回答に入れました。 動かしていないので、バグってるかもしれませんが。
coala

2021/05/04 04:51

TakaiYさんコードの修正版まで作成していただきわかりやすい説明ありがとうございました。ご指摘いただきました内容完全に理解できました。 お時間を作っていただきありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問