java 循环链表倒置_循环控制-链表反转(与创建链表)

0.目录

1.循环控制

循环书写方法:

定义循环不变式,并在循环体每次结束后保持循环不变式

先一般 ,后特殊

每次 必须 向前推进循环不变式中涉及的变量值

每次推进的规模必须为 1

循环不表示(loop invariant):是一句断言定义各变量所满足的条件

2.Java代码实现

2.1 创建链表和递归反转实现

前面已经写过递归的版本了,传送门:

递归控制-链表反转

本篇结点和创建链表的实现同前文 递归控制-创建链表

2.2 循环反转思路

1.先考虑循环中的某一个情况——循环到3时,应该要实现哪些操作?

097614acf64c483e0a0649a1af29a70d.png

2.此时应该要把3 → 4的指针改为3 → 2,而4作为剩下的第一个结点。

为了实现这一功能,加入两个指针newHead(指向反转成功的链表)和curHead(指向还没有反转的链表):

76e7c91b670656c5fd8786afead876df.png

3.所以每一次循环做的操作就是跟随两个指针往后移:

b5728b4eff0bca07738182e867fe5817.png

4.总体来看就是用两个指针从头循环到尾一步步地反转链表:

7cdd1f9110a6049e4d71f8a3740d0798.png

2.3 链表反转的实现

依据反转思路实现循环代码即可。

public Node reverseLinkedList(Node head) {

Node newHead = null;

Node curHead = head;

// Loop invariant:

// newHead points to the linked list already reversed.

// curHead points to the linked list not yet reversed.

while (curHead != null) {

// Loop invariant holds.

Node next = curHead.getNext();

curHead.setNext(newHead);

newHead = curHead;

curHead = next;

// Loop invariant holds.

}

// Loop invariant holds.

return newHead;

}

ps:不需要在开头处理:if(head = null),程序也能够很好的处理特殊情况。

验证在循环最后一步时程序的正确性:

while (curHead != null) {

// Loop invariant holds.

Node next = curHead.getNext(); // next = null

curHead.setNext(newHead); // curHead.next reversed

newHead = curHead; // newHead points to last

curHead = next; // curHead = null

// Loop invariant holds.

}

2.4 测试用例

测试程序是否正确运行(采用之前递归实现的测试用例):

public static void main(String[] args) {

LinkedListCreator creator = new LinkedListCreator();

LinkedListReverser reverser = new LinkedListReverser();

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(new ArrayList<>())));

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(Arrays.asList(1))));

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(Arrays.asList(1, 2, 3, 4, 5))));

}

运行结果为

ac45b09068246adc2e195d50176aeab3.png

main所在java文件全部代码:

import java.util.ArrayList;

import java.util.Arrays;

import interview.common.Node;

import interview.recursion.LinkedListCreator;

public class LinkedListReverser {

public Node reverseLinkedList(Node head) {

Node newHead = null;

Node curHead = head;

// Loop invariant:

// newHead points to the linked list already reversed.

// curHead points to the linked list not yet reversed.

while (curHead != null) {

// Loop invariant holds.

Node next = curHead.getNext();

curHead.setNext(newHead);

newHead = curHead;

curHead = next;

// Loop invariant holds.

}

// Loop invariant holds.

return newHead;

}

public static void main(String[] args) {

LinkedListCreator creator = new LinkedListCreator();

interview.recursion.LinkedListReverser reverser = new interview.recursion.LinkedListReverser();

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(new ArrayList<>())));

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(Arrays.asList(1))));

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(Arrays.asList(1, 2, 3, 4, 5))));

}

}

2.5 循环控制-创建链表

最后再把创建链表的递归实现也改为循环实现:

public Node createLargeLinkedList(int size) {

Node prev = null;

Node head = null;

for (int i = 1; i <= size; i++) {

Node node = new Node(i);

if (prev != null) {

prev.setNext(node);

} else {

head = node;

}

prev = node;

}

return head;

}

测试一下:

public static void main(String[] args) {

LinkedListCreator creator = new LinkedListCreator();

interview.recursion.LinkedListReverser reverser = new interview.recursion.LinkedListReverser();

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(new ArrayList<>())));

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(Arrays.asList(1))));

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLinkedList(Arrays.asList(1, 2, 3, 4, 5))));

Node.printLinkedList(reverser.reverseLinkedList(

creator.createLargeLinkedList(100)));

}

运行结果:

f801c4cb7b4b09d51f7e519f97734470.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
双向链表是一种常见的数据结构,与单向链表相比,它可以在节点之间进行双向遍历。在Java中,我们可以使用类来实现双向链表。 下面是一个简单的Java程序,演示如何创建和输出双向链表: ```java // 双向链表节点类 class Node { public int data; public Node prev; public Node next; public Node(int data) { this.data = data; this.prev = null; this.next = null; } } // 双向链表类 class DoubleLinkedList { public Node head; public Node tail; public DoubleLinkedList() { this.head = null; this.tail = null; } // 在链表头部插入节点 public void insertAtHead(int data) { Node newNode = new Node(data); if (head == null) { head = newNode; tail = newNode; return; } newNode.next = head; head.prev = newNode; head = newNode; } // 在链表尾部插入节点 public void insertAtTail(int data) { Node newNode = new Node(data); if (tail == null) { head = newNode; tail = newNode; return; } newNode.prev = tail; tail.next = newNode; tail = newNode; } // 输出链表 public void printList() { Node current = head; while (current != null) { System.out.print(current.data + " "); current = current.next; } System.out.println(); } } // 测试类 public class Main { public static void main(String[] args) { DoubleLinkedList list = new DoubleLinkedList(); list.insertAtHead(1); list.insertAtHead(2); list.insertAtTail(3); list.insertAtTail(4); list.printList(); // 输出:2 1 3 4 } } ``` 在上面的程序中,我们首先定义了一个`Node`类来表示双向链表的每个节点,其中包含了当前节点的值、前一个节点和后一个节点。接着,我们定义了`DoubleLinkedList`类来表示整个双向链表,其中包含了头节点和尾节点。 在`DoubleLinkedList`类中,我们定义了`insertAtHead`和`insertAtTail`方法来在链表头部和尾部插入节点,分别需要创建一个新节点,并将它与当前链表的头节点或尾节点进行连接。 最后,我们定义了`printList`方法来输出整个链表,只需要从链表的头节点开始遍历,依次输出每个节点的值即可。 在`Main`类中,我们通过`DoubleLinkedList`类创建了一个双向链表,并向其中插入了四个节点。最后,我们调用`printList`方法输出整个链表

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值