リスト内の一つ一つのデータはノード (node) または要素 (element) と呼ばれ、 ノードを実現するクラスの内容は以下のとおりである。 なお、簡単化のため、この例ではリストの中に入れるデータは文字列としている。 element はノードに入れる情報本体である。 next は同じ Node クラスのオブジェクトであり、 あるノードから見た「次のノードへの参照 (在りか) 」を示す変数である。
さらに、ノードの情報を初期化するコンストラクタ、 ノードの情報を登録/参照するメソッドを用意し、 次のようなクラスで表すことができる。 (ファイル名 Node.java)
public class Node {
    private String element;
    private Node next;
    /** コンストラクタ */
    public Node() { }
    public Node(String element, Node next) {
	this.element = element;
	this.next = next;
    }
    /** 次のノードへの参照を登録する */
    public void setNext(Node next) {
	this.next = next;
    }
    /** 次のノードへの参照を返す */
    public Node getNext() {
	return next;
    }
    /** ノードの中身の情報を登録する */
    public void setElement(String element) {
	this.element = element;
    }
    /** ノードの中身の情報を返す */
    public String getElement() {
	return element;
    }
}
上で定義したクラス Node を使い簡単なリストを作ることを考える。 リストは次のように宣言し、最初のノードを加えることができる。
Node head = null;                     // リストの先頭を保持する変数を宣言、最初は空
head = new Node("Copernicus", null);  // 先頭にCopernicusを追加
次に2番目、3番目、4番目の要素を末尾に加えるには次のように書くことができる。
// リストの末尾に 2番目の要素 Newton を追加
head.setNext(new Node("Newton", null));
// リストの末尾に 3番目の要素 Heisenberg を追加
Node second = head.getNext();
second.setNext(new Node("Heisenberg", null));
// リストの末尾に 4番目の要素 Einstein を追加
Node third = second.getNext();
third.setNext(new Node("Einstein", null));
以上の処理を実行するとリストには
[head] → Copernicus → Newton → Heisenberg → Einstein → (null)
という順にデータが並んでいることになる。
リストを管理するための変数は、先頭を表す head だけである。 先頭の要素さえ分かっていれば、参照をたどることによってすべてのノードに到達できる。 リストのノードを順番にアクセスする方法で代表的なのは、 次のようにリストの先頭から順に調べていく方法である。
Node p = head;
while (p != null) {
    リストのノード p に関する処理;
    p = p.getNext();
}
次の例は、リストの中身を順番に表示する処理の例である。
// リスト全体を表示
Node p = head;
while(p != null) {
    System.out.println(p.getElement());
    p = p.getNext();
}
データが並んだリストから、ノードを削除する方法を考える。 削除対象のノードによって、以下の2とおりに処理を分けて考えると良い。
以下のノードが存在するリストがあるとする。
[head] → Copernicus → Newton → Heisenberg → Einstein → (null)
先頭のノード Copernics を削除することを考える。 (教科書 p.290 の図9-13参照) プログラムは以下のとおりである。head はリストの先頭を指しているとする。
if (head != null)
    head = head.getNext();
先頭以外のノードの削除を考える。例えば Heisenberg を削除するとする。 (教科書 p.293 の図9-15参照)
まず、削除したい一つ前のノードを探す。この例では Newton である。 「一つ前」というのは不自然な設定であるが、 能率良く処理を行うためにはやむを得ない。 リストは、前に進むのは容易であるが、後ろに戻るのは困難であるからである。 削除したいノードを指定するようにすると、 一つ前のノードを求めるのに時間がかかる。 (この不便を解消するには双方向リストを用いる)
(あらかじめ、削除対象の Heisenberg の一つ前 (Newton) を探し、p に代入しておく)
if (p != null) {
    Node target = p.getNext();  // target: 削除対象のノード
    Node q = target.getNext();  // q: 削除対象の「次」のノード
    p.setNext(q);
}
=================
各変数が指すノード:
[head]  → Copernicus → Newton → Heisenberg → Einstein → (null)
                          [p]      [target]      [q]
=================
上で取り上げた、リストへのデータの追加、削除 リスト全体の表示を含めたプログラム全体を示す。 各自実行して動作を確認すること。
なお、クラス Node は、例題1のものを使う。
public class LinkedListSample {
    public static void main(String[] args) {
	Node head = null;
	// 最初の要素 Copernicus の追加
	head = new Node("Copernicus", null);
	// リストの末尾に 2番目の要素 Newton を追加
	head.setNext(new Node("Newton", null));
	// リストの末尾に 3番目の要素 Heisenberg を追加
	Node second = head.getNext();
	second.setNext(new Node("Heisenberg", null));
	// リストの末尾に 4番目の要素 Einstein を追加
	Node third = second.getNext();
	third.setNext(new Node("Einstein", null));
        // リスト先頭の要素 (Copernics) を削除
        if (head != null)
            head = head.getNext();
        Node p;
        // リストの2番めの要素 (Heisenberg) を削除
        p = head; // 削除対象の1つ前 (Newton) のノードをpと置く
        if (p != null) {
            Node target = p.getNext();  // target: 削除対象のノード
            Node q = target.getNext();  // q: 削除対象の「次」のノード
            p.setNext(q);
        }
	// リストの内容を表示
        // この時点でのリストは Newton -> Einstein
	p = head;
	while(p != null) {
	    System.out.print(p.getElement());
	    p = p.getNext();
	}
	System.out.println();
    }
}
提出先: /home/submit/JavaLib/[出題日]/[学籍番号]
[注意] 本課題では、1つクラスを1つのファイルとして作成することを想定している。 ファイル名は、「public宣言を行ったクラスの名前.java」 である。 ファイルが別々であっても、同じディレクトリにあるpublic宣言されたクラスは、 相互に利用することができる。 (詳しく知りたい人は、「パッケージ」について調べると良い)
リスト内のデータとリストのさまざまな機能 (データの追加、リスト全体の表示) を 1つのクラスとして設計し実装しなさい。
これまで利用してきた、Javaのクラスライブラリの LinkedList の機能縮小版を自分で作ると考えれば良い。 良いアルゴリズムや良いプログラムを考えるためには、 ソフトウェアの基本的なメカニズムは理解してもらいたい。 この勉強には基本的なデータ構造を自分で作成してみることが一番である。
クラス名 MyLinkedList とし、次のような機能を備えるようにする。
addLast, remove の2つのメソッドを作成しなさい。
作成したプログラムが正しく動作するかどうか、必要かつ十分なテストを行うこと。 少なくとも、次のような main メソッドで動作を確認すること。 (提出ファイル名: MyLinkedList.java)
public class MyLinkedListMain {
    public static void main(String[] args) {
	MyLinkedList list = new MyLinkedList();
	list.addLast("Copernicus");
	list.addLast("Newton");
	list.addLast("Heisenberg");
	list.addLast("Einstein");
        // この時点でのリスト: Copernics -> Newton -> Heisenberg -> Einstein
	list.print();
        // Copernics と Einstein を削除
        list.remove("Copernicus");
	list.remove("Einstein");
	System.out.println("=========[削除後]=========");
        // この時点でのリスト: Newton -> Heisenberg
	list.print();
    }
}
クラス MyLinkedList の大枠は次のようになる。
public class MyLinkedList {
    private Node head;
    public MyLinkedList() {
	head = null;
    }
    public void addLast(String elem) {
        // ここを考える
    }
    public void remove(String elem) {
        // ここを考える
    }
    public void print() {
        Node p = head;
        while (p != null) {
            System.out.print(p.getElement() + " ");
            p = p.getNext();
        }
        System.out.println();
    }
}
ある文字列 string1 が、別の文字列 string2 の内容と等しいかどうかを判定するには、 equals を使う。例を以下に示す。
if (string1.equals(string2)) {
    string1 と string2 が等しいときの処理
}