public class LinkedListManual {

    // Node: satu kotak data plus satu tautan ke node berikutnya.
    static class Node {
        String data;
        Node next;

        Node(String data) {
            this.data = data;
        }
    }

    private Node kepala;
    private int ukuran;

    // Penghitung node yang dikunjungi: deterministik, bukan pengukuran waktu.
    static long kunjungan;

    public static void main(String[] args) {
        LinkedListManual list = new LinkedListManual();
        list.tambahBelakang("Budi");
        list.tambahBelakang("Siti");
        list.tambahBelakang("Dewi");
        list.tambahBelakang("Andi");
        list.tambahBelakang("Rina");

        System.out.print("Isi list: ");
        cetak(list.kepala);
        System.out.println("Ukuran  : " + list.ukuran);

        System.out.println();
        System.out.println("Akses per indeks (jumlah node yang dikunjungi):");
        for (int indeks : new int[] {0, 2, 4}) {
            kunjungan = 0;
            String nilai = list.ambil(indeks);
            System.out.printf("  ambil(%d) -> %s, node dikunjungi: %d%n",
                    indeks, nilai, kunjungan);
        }

        System.out.println();
        System.out.println("Hapus node di tengah:");
        kunjungan = 0;
        boolean terhapus = list.hapus("Dewi");
        System.out.printf("  hapus Dewi -> %s, node dikunjungi: %d%n",
                terhapus ? "berhasil" : "gagal", kunjungan);
        System.out.print("Isi list: ");
        cetak(list.kepala);
        System.out.println("Ukuran  : " + list.ukuran);
    }

    void tambahBelakang(String data) {
        Node baru = new Node(data);
        if (kepala == null) {
            kepala = baru;
        } else {
            Node sekarang = kepala;
            while (sekarang.next != null) {
                sekarang = sekarang.next;
            }
            sekarang.next = baru;
        }
        ukuran++;
    }

    String ambil(int indeks) {
        Node sekarang = kepala;
        for (int i = 0; i < indeks; i++) {
            sekarang = sekarang.next;
            kunjungan++;        // satu lompatan tautan
        }
        kunjungan++;            // node tujuan juga dikunjungi
        return sekarang.data;
    }

    boolean hapus(String data) {
        Node sekarang = kepala;
        Node sebelum = null;
        while (sekarang != null) {
            kunjungan++;
            if (sekarang.data.equals(data)) {
                if (sebelum == null) {
                    kepala = sekarang.next;     // node pertama digeser keluar
                } else {
                    sebelum.next = sekarang.next; // tautan dilewati satu node
                }
                ukuran--;
                return true;
            }
            sebelum = sekarang;
            sekarang = sekarang.next;
        }
        return false;
    }

    static void cetak(Node kepala) {
        Node sekarang = kepala;
        StringBuilder sb = new StringBuilder();
        while (sekarang != null) {
            sb.append(sekarang.data);
            if (sekarang.next != null) {
                sb.append(" -> ");
            }
            sekarang = sekarang.next;
        }
        System.out.println(sb);
    }
}
