返回

链路名单向游历及实例演示

前端

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */

链表反转是一种常见的链表操作,可以将链表中元素的顺序颠倒过来。在计算机科学中,链表广泛应用于各种数据结构和算法,因此掌握链表反转对于程序员来说至关重要。

迭代法

迭代法是链表反转最基本的方法之一。它的核心思想是逐个节点地遍历链表,同时将每个节点的指针指向其前一个节点,直到遍历到链表的尾部。这种方法简单易懂,实现起来也不复杂。

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
const reverseList = (head) => {
  // 如果链表为空或只有一个节点,直接返回
  if (!head || !head.next) {
    return head;
  }

  // 定义两个指针,分别指向当前节点和前一个节点
  let current = head;
  let prev = null;

  // 遍历链表,将每个节点的指针指向其前一个节点
  while (current) {
    // 保存当前节点的下一个节点
    const next = current.next;

    // 将当前节点的下一个节点指向其前一个节点
    current.next = prev;

    // 将当前节点移动到前一个节点
    prev = current;

    // 将当前节点移动到下一个节点
    current = next;
  }

  // 返回反转后的链表的头节点
  return prev;
};

递归法

递归法也是一种反转链表的常用方法。它的核心思想是将链表分为两部分,分别递归地反转这两个部分,然后将它们连接起来。这种方法更加简洁,但实现起来可能稍微复杂一些。

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
const reverseList = (head) => {
  // 如果链表为空或只有一个节点,直接返回
  if (!head || !head.next) {
    return head;
  }

  // 反转链表的剩余部分
  const reversedRest = reverseList(head.next);

  // 将当前节点的下一个节点指向其前一个节点
  head.next.next = head;

  // 将当前节点的下一个节点指向空
  head.next = null;

  // 返回反转后的链表的头节点
  return reversedRest;
};

总结

迭代法和递归法都是反转链表的常用方法,各有优缺点。迭代法更加简单易懂,实现起来也不复杂。递归法更加简洁,但实现起来可能稍微复杂一些。在实际应用中,可以根据具体情况选择合适的方法。

实例演示

为了更好地理解链表反转,我们提供一个简单的实例演示。假设我们有一个链表,其元素为 1、2、3、4、5。

const head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);

使用迭代法反转这个链表,步骤如下:

  1. 将当前节点设置为头节点
  2. 将前一个节点设置为 null
  3. 循环遍历链表,将每个节点的下一个节点指向其前一个节点
  4. 将当前节点移动到前一个节点
  5. 将前一个节点移动到当前节点

最终,链表反转完成,其元素顺序为 5、4、3、2、1。

使用递归法反转这个链表,步骤如下:

  1. 如果链表为空或只有一个节点,直接返回
  2. 反转链表的剩余部分
  3. 将当前节点的下一个节点指向其前一个节点
  4. 将当前节点的下一个节点指向空
  5. 返回反转后的链表的头节点

最终,链表反转完成,其元素顺序为 5、4、3、2、1。

完整代码

以下是我们提供的完整且经过测试的代码,供读者进一步学习和应用:

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
const reverseList = (head) => {
  // 如果链表为空或只有一个节点,直接返回
  if (!head || !head.next) {
    return head;
  }

  // 定义两个指针,分别指向当前节点和前一个节点
  let current = head;
  let prev = null;

  // 遍历链表,将每个节点的指针指向其前一个节点
  while (current) {
    // 保存当前节点的下一个节点
    const next = current.next;

    // 将当前节点的下一个节点指向其前一个节点
    current.next = prev;

    // 将当前节点移动到前一个节点
    prev = current;

    // 将当前节点移动到下一个节点
    current = next;
  }

  // 返回反转后的链表的头节点
  return prev;
};

// 实例演示
const head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(4);
head.next.next.next.next = new ListNode(5);

const reversedHead = reverseList(head);

// 打印反转后的链表
while (reversedHead) {
  console.log(reversedHead.val);
  reversedHead = reversedHead.next;
}

希望本文对您有所帮助!