反转单向链表
定义一个函数,输入一个单向链表的头节点,反转该链表,并输出反转之后的头节点
链表
链表是一种物理结构(非逻辑结构),是数组的补充。
数组需要一段连续的内存空间,而链表不需要。
数据结构
- 单向链表 `{ value, next }`
- 双向链表 `{ value, prev, next }`
两者对比
- 链表:查询慢,新增和删除较快
- 数组:查询快,新增和删除较慢
应用场景
React Fiber 就把 vdom 树转换为一个链表,这样才有可能随时中断、再继续进行。<br>
如果 vdom 是树,那只能递归一次性执行完成,中间无法断开。
分析
反转链表,画图很好理解。没有捷径,遍历一边,重新设置 next 指向即可。
但实际写代码,却并不简单,很容易造成 nextNode 丢失。
因此,遍历过程中,至少要存储 3 个指针 `prevNode` `curNode` `nextNode`
时间复杂度 `O(n)`
- 链表
- 链表和数组的不同
- 内存占用
- 查询、新增、删除的效率
- 如何保证 nextNode 不丢失
export interface ILinkListNode { value: number, next?: ILinkListNode } // 反转单向链表 export 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 && prevNode) { curNode.next = prevNode } // 整体向后移动指针 prevNode = curNode curNode = nextNode nextNode = nextNode?.next } // 最后一个的补充:当 nextNode 空时,此时 curNode 尚未设置 next curNode!.next = prevNode return curNode! } // 根据数组创建单向链表 export function createLinkList(arr:number[]): ILinkListNode { const len = arr.length if (len === 0) { throw new Error('arr is empty') } let curNode: ILinkListNode = { value: arr[len - 1] } if(len === 1) return curNode for (let i = len-2; i >= 0; i--) { curNode = { value: arr[i], next: curNode } } return curNode } // 测试 const arr = [100, 200, 300, 400, 500] const list = createLinkList(arr) console.log('list', list) const list1 = reverseLinkList(list) console.info('list1:', list1)
单测
import { ILinkListNode, reverseLinkList, createLinkList } from '../反转单向链表' describe('反转单向链表', () => { it('单个元素', () => { const node: ILinkListNode = { value: 100 } const node1 = reverseLinkList(node) expect(node1).toEqual({ value: 100 }) }) it('多个元素', () => { const node = createLinkList([100, 200, 300]) const node1 = reverseLinkList(node) expect(node1).toEqual({ value: 300, next: { value: 200, next: { value: 100 } } }) }) })