算法:定义一个JS函数,反转单向链表

33 阅读2分钟

链表

  • 链表是一个物理结构(非逻辑结构),类似于数组
  • 数组需要一段连续的内存区间,而链表是零散的
  • 链表节点的数据结构{value, next?, prev?}

image.png

创建链表代码

interface ILinkListNode {
  value: number
  next?: ILinkListNode
}

function createLinkList(arr: number[]): ILinkListNode {
  const length = arr.length
  if (length === 0) {
    throw new Error('array is empty')
  }
  let curNode:ILinkListNode = { value: arr[length - 1] }
  if (length === 1) return curNode
  for (let i = arr[length - 2]; i >= 0; i--) {
    curNode = {
      value: arr[i],
      next: curNode,
    }
  }
  return curNode
}

const arr = [1, 2, 3, 4, 5]
const list = createLinkList(arr)
console.info(list)

image.png

链表vs数组

  • 都是有序结构
  • 链表:查询慢O(n),新增和删除快O(1)
  • 数组:查询快O(1),新增和删除慢O(n)

前端在链表的应用

image.png

解题思路

  • 反转,即节点next指向前一个节点
  • 但这很容易造成nextNode的丢失
  • 需要三个指针 prevNode curNode nextNode

image.png

反转单向链表代码:

interface ILinkListNode {
  value: number
  next?: ILinkListNode
}
function reverseLinkList(listNode: ILinkListNode): ILinkListNode {
  // 定义三个指针
  let prevNode: ILinkListNode | undefined = undefined
  let curNode: ILinkListNode | undefined = undefined
  let nextNode: ILinkListNode | undefined = listNode
  // 以nextNode为主,遍历列表
  while (nextNode) {
    // 第一个元素,删掉next,防止循环引用
    if (curNode && !prevNode) {
      delete curNode.next
    }
    // 反转指针
    if (curNode && nextNode) {
      curNode.next = prevNode
    }
    prevNode = curNode
    curNode = nextNode
    nextNode = nextNode?.next
  }
  // 最后一个的补充:当nextNode为空时,此时 curNode 尚未设置next
  curNode!.next = prevNode

  return curNode!
}

结果:

image.png

全部代码:

interface ILinkListNode {
  value: number
  next?: ILinkListNode
}
function reverseLinkList(listNode: ILinkListNode): ILinkListNode {
  // 定义三个指针
  let prevNode: ILinkListNode | undefined = undefined
  let curNode: ILinkListNode | undefined = undefined
  let nextNode: ILinkListNode | undefined = listNode
  // 以nextNode为主,遍历列表
  while (nextNode) {
    // 第一个元素,删掉next,防止循环引用
    if (curNode && !prevNode) {
      delete curNode.next
    }
    // 反转指针
    if (curNode && nextNode) {
      curNode.next = prevNode
    }
    prevNode = curNode
    curNode = nextNode
    nextNode = nextNode?.next
  }
  // 最后一个的补充:当nextNode为空时,此时 curNode 尚未设置next
  curNode!.next = prevNode

  return curNode!
}

function createLinkList(arr: number[]): ILinkListNode {
  const length = arr.length
  if (length === 0) {
    throw new Error('array is empty')
  }
  let curNode: ILinkListNode = { value: arr[length - 1] }
  if (length === 1) return curNode
  for (let i = arr[length - 2]; i >= 0; i--) {
    curNode = {
      value: arr[i],
      next: curNode,
    }
  }
  return curNode
}

const arr = [1, 2, 3, 4, 5]
const list = createLinkList(arr)
console.log(list)
const list1 = reverseLinkList(list)
console.log(list1)