线性数据结构的遍历
let arr = [1,2,3,4]
// 数组的基本遍历
function traverse(arr) {
if (arr == null) return
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
}
traverse(arr)
function Node(value) {
this.value = value
this.null = null
}
let node1 = new Node(1)
let node2 = new Node(2)
let node3 = new Node(3)
let node4 = new Node(4)
let node5 = new Node(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
// 链表遍历
function traverseLink(root) {
let temp = root
while (true) {
if (temp != null){ // 严格判断下 undefined!==null 所以要使用 !=
console.log(temp.value)
} else {
break
}
temp = temp.next
}
}
traverseLink(node1)
变形:递归遍历
let arr = [1, 2, 3, 4, 5, 6]
// function traverseArr(arr) {
// if (arr == null) return
// for (let i = 0; i < arr.length; i++) {
// console.log(arr[i])
// }
// }
// 数组递归遍历
function traverseArr(arr, i) {
if (arr == null || arr.length <= i) return
console.log(arr[i])
traverseArr(arr, i + 1)
}
traverseArr(arr, 0)
function Node(value) {
this.value = value
this.next = null
}
let node1 = new Node(1)
let node2 = new Node(2)
let node3 = new Node(3)
let node4 = new Node(4)
let node5 = new Node(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
//链表递归遍历 注:必须有出口
function traverseLink(root) {
if (root == null) return
console.log(root.value)
traverseLink(root.next)
}
// traverseLink(node1)
链表逆置
-
总体思路:用 4 和 5 来举例子,本来是 4 指向 5, 现在需要让 5 指向 4, 然后 4 指向空;进而比较 3 和 4, 2 和 3, 1 和 2,结束标志是由最开始的 5 指向空变为 1 指向空。
-
操作链表时,要注意链表不能断。
-
递归需要满足:
- 递归元素操作相同
- 存在出口
-
指向改变的顺序问题:以 4 和 5 为例,如果4 先指向 null,那么需要5 指向 4 的时候,将找不到 5, 因为 5 是根据 4找到的(指向的)。所以正确的顺序是先从5指向4,再从 4指向 null,保证链表不能断。
-
判断出口问题:
let result = reverseList(root.next)
调用了函数,所以执行了 1,2,3,4的指向改变,最后由5指向了4,而4在之前已经已经指向了3,也就不存在4指向null的问题,result缓存的是最后的结果,也就是出口,所以最终返回的result就是出口5(newRoot)。
function Node(value) {
this.value = value
this.next = null
}
let node1 = new Node(1)
let node2 = new Node(2)
let node3 = new Node(3)
let node4 = new Node(4)
let node5 = new Node(5)
node1.next = node2
node2.next = node3
node3.next = node4
node4.next = node5
// 先找递归出口,在往下递归
function reverseList(root) {
if (root == null || root.next == null) return root
// 暂存下一步操作,避免污染
// 表面上,从root开始操作;实际上,从newRoot开始操作
// 只不过操作到newRoot的时候,其他元素已经默默地改变指向了
let result = reverseList(root.next)
root.next.next = root
root.next = null
return result
}
let newRoot = reverseList(node1)
function traverseLink(root) {
if (root == null) return
console.log(root.value)
traverseLink(root.next)
}
traverseLink(newRoot)