Membalikkan Senarai Terpaut di Java

1. Pengenalan

Dalam tutorial ini, kami akan melaksanakan dua algoritma pembalikan senarai terpaut di Java.

2. Struktur Data Senarai Berkaitan

Senarai terpaut adalah struktur data linier di mana penunjuk dalam setiap elemen menentukan urutan. Setiap elemen senarai tertaut mengandungi medan data untuk menyimpan data senarai dan medan penunjuk untuk menunjuk ke elemen seterusnya dalam urutan. Kita juga boleh menggunakan penunjuk kepala untuk menunjukkan elemen permulaan senarai terpaut:

Setelah kami membalikkan senarai yang dipautkan, kepala akan menunjuk ke elemen terakhir dari senarai yang dipautkan yang asal, dan penunjuk setiap elemen akan menunjuk ke elemen sebelumnya dari senarai yang dipautkan yang asal:

Di Java, kami mempunyai kelas LinkedList untuk menyediakan pelaksanaan senarai dua kali ganda antara muka List dan Deque . Walau bagaimanapun, kami akan menggunakan struktur data senarai berangkai tunggal dalam tutorial ini.

Mari mulakan dahulu dengan kelas ListNode untuk mewakili elemen senarai terpaut:

public class ListNode { private int data; private ListNode next; ListNode(int data) { this.data = data; this.next = null; } // standard getters and setters }

The ListNode kelas mempunyai dua bidang:

  • Nilai integer untuk mewakili data elemen
  • Penunjuk / rujukan ke elemen seterusnya

Senarai terpaut mungkin mengandungi banyak objek ListNode . Sebagai contoh, kita boleh membina senarai terpautkan di atas dengan gelung:

ListNode constructLinkedList() { ListNode head = null; ListNode tail = null; for (int i = 1; i <= 5; i++) { ListNode node = new ListNode(i); if (head == null) { head = node; } else { tail.setNext(node); } tail = node; } return head; }

3. Pelaksanaan Algoritma Iteratif

Mari kita laksanakan algoritma berulang di Java:

ListNode reverseList(ListNode head) { ListNode previous = null; ListNode current = head; while (current != null) { ListNode nextElement = current.getNext(); current.setNext(previous); previous = current; current = nextElement; } return previous; }

Dalam algoritma berulang ini, kami menggunakan dua pemboleh ubah ListNode , sebelumnya dan semasa , untuk mewakili dua elemen bersebelahan dalam senarai terpaut. Untuk setiap lelaran, kami membalikkan dua elemen ini dan kemudian beralih ke dua elemen seterusnya.

Pada akhirnya, penunjuk semasa akan menjadi sifar, dan penunjuk sebelumnya akan menjadi elemen terakhir dari senarai lama yang dipautkan. Oleh itu, sebelumnya juga merupakan penunjuk utama senarai terpaut terbalik, dan kami mengembalikannya dari kaedah.

Kami dapat mengesahkan pelaksanaan berulang ini dengan ujian unit mudah:

@Test public void givenLinkedList_whenIterativeReverse_thenOutputCorrectResult() { ListNode head = constructLinkedList(); ListNode node = head; for (int i = 1; i <= 5; i++) { assertNotNull(node); assertEquals(i, node.getData()); node = node.getNext(); } LinkedListReversal reversal = new LinkedListReversal(); node = reversal.reverseList(head); for (int i = 5; i>= 1; i--) { assertNotNull(node); assertEquals(i, node.getData()); node = node.getNext(); } }

Dalam ujian unit ini, pertama-tama kita membina senarai senarai terpaut dengan lima nod. Kami juga mengesahkan bahawa setiap nod dalam senarai yang dipautkan mengandungi nilai data yang betul. Kemudian, kita memanggil fungsi berulang untuk membalikkan senarai yang dipautkan. Akhirnya, kami memeriksa senarai pautan terbalik untuk memastikan data terbalik seperti yang diharapkan.

4. Pelaksanaan Algoritma Rekursif

Sekarang, mari kita laksanakan algoritma rekursif di Java:

ListNode reverseListRecursive(ListNode head) { if (head == null) { return null; } if (head.getNext() == null) { return head; } ListNode node = reverseListRecursive(head.getNext()); head.getNext().setNext(head); head.setNext(null); return node; }

Dalam fungsi reverseListRecursive , kita secara berulang-ulang melawat setiap elemen dalam senarai yang dipautkan sehingga kita mencapai yang terakhir. Elemen terakhir ini akan menjadi ketua baru senarai terpaut terbalik. Juga, kami menambahkan elemen yang dikunjungi ke hujung senarai pautan yang terbalik sebahagiannya.

Begitu juga, kita dapat mengesahkan pelaksanaan rekursif ini dengan ujian unit mudah:

@Test public void givenLinkedList_whenRecursiveReverse_thenOutputCorrectResult() { ListNode head = constructLinkedList(); ListNode node = head; for (int i = 1; i <= 5; i++) { assertNotNull(node); assertEquals(i, node.getData()); node = node.getNext(); } LinkedListReversal reversal = new LinkedListReversal(); node = reversal.reverseListRecursive(head); for (int i = 5; i>= 1; i--) { assertNotNull(node); assertEquals(i, node.getData()); node = node.getNext(); } }

5. Kesimpulan

Dalam tutorial ini, kami menerapkan dua algoritma untuk membalikkan senarai terpaut. Seperti biasa, kod sumber untuk artikel tersebut terdapat di GitHub.