【算法】反转单向链表 链表和数组的区分 时间复杂度
链表vs数组
链表:
- 是一种物理结构(非逻辑结构),类似于数组,内存空间是零散的
- 链表节点的数据结构{value,next?,prev?} 单向链表只有next 双向的有prev
- 查询慢,删除和新增快
数组:
- 需要一段连续的内存空间,而链表是零散的
- 查询快,删除和新增慢(最后删除最后新增很快)
都是有序结构
Set 是无序的 Object是无序的 Map 是有序结构
React Fiber 中使用了链表
思路
反转,即节点next 指向前一个节点
但这容易造成nextNode 的丢失
代码
/**
* @description 反转单向链表
* @author superrui
*/
// 定义列表结构
interface ILinkListNode {
value: number
next?: ILinkListNode
}
/**
* 反转单向列表,并返回反转之后的head node
* @param listNode list head node
*/
function reverseLinkList(listNode: ILinkListNode):ILinkListNode{
//定义三个指针
let prevNode: ILinkListNode | undefined = undefined
let curNode: ILinkListNode | undefined = undefined
let nextNode: ILinkListNode | undefined = undefined
//以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!
}
/**
* 根据数组创建链表
* @param arr number arr
*/
function createLinkList(arr: number[]): ILinkListNode {
const length = arr.length
if (length === 0) throw new Error('arr is empty')
let curNode: ILinkListNode = {
value: arr[length - 1]
}
if (length === 1) return curNode
for (let i = length - 2; i >= 0; i--) {
curNode = {
value: arr[i],
next: curNode
}
}
return curNode
}
const arr = [100, 200, 300, 400, 500]
const list = createLinkList(arr)
console.info('list', list)