一起学习数据结构与算法:链表

266 阅读2分钟

class Node {
    constructor (node) {
        if (Node.isNode(node)) {
            [this.data, this.next] = [node.data, node.next]
        } else {
            [this.data, this.next] = [node, null]
        }
    }
    static isNode (node) {
        return !!(node && Object.isPrototypeOf.call(Node.prototype, node))
    }
}
/* eslint-disable no-param-reassign, object-curly-newline, no-continue*/
class LinkList
 {
    constructor (...nodeArray) {
        if (!nodeArray.length) this.head = null
        else this.append(...nodeArray)
    }
    // 追加数据
    append (...nodeArray) {
        while (nodeArray.length) {
            const newNode = new Node(nodeArray.shift())
            if (!newNode) continue
            if (!this.head) {
                this.head = newNode
                continue
            }
            let curNode = this.head
            while (curNode && curNode.next) {
                curNode = curNode.next
            }
            curNode.next = newNode
        }
    }
    // 查找节点
    find (node) {
        if (!node) return
        let target = null
        let curNode = this.head
        while (curNode) {
            if (curNode.data === node) {
                target = curNode
                break
            }
            if (!curNode.next) break
            curNode = curNode.next
        }
        return target
    }
    // 在某个节点后面插入数据
    insert (target, node) {
        if (!node) return
        if (!target) return this.append(node)
        const nodeCopy = new Node(node)
        const targetNode = this.find(target)
        if (!targetNode) return this.append(node)
        const targetNextNode = targetNode.next
        nodeCopy.next = targetNextNode
        targetNode.next = nodeCopy
    }
    // 在某个节点前面后面插入数据
    insertBefore (target, node) {
        if (!node) return
        if (!target) return this.append(node)
        let curNode = this.head
        let lastNode = null
        while (curNode && curNode.next) {
            if (target === curNode.data) {
                break
            } else {
                lastNode = curNode
                curNode = curNode.next
            }
        }
        if (lastNode) {
            const newNode = new Node(node)
            newNode.next = lastNode.next
            lastNode.next = newNode
        } else {
            this.append(node)
        }
    }
    // 删除某个节点
    delete (target) {
        if (!target) return
        if (target.next) {
            target.data = target.next.data
            target.next = target.next.next
        } else if (target === this.head) {
            this.head = null
        } else {
            let curNode = this.head
            while (curNode && curNode.next && curNode.next.next) {
                curNode = curNode.next
            }
            if (curNode.next === target) {
                curNode.next = null
            }
        }
    }
    // 删除重复的节点
    deleteRepeatNode () {
        const map = {}
        if (this.head && this.head.next) {
            // 计数
            let curNode = this.head
            while (curNode) {
                map[curNode.data] = map[curNode.data] ? map[curNode.data] + 1 : 1
                curNode = curNode.next
            }
            // 遍历删除节点
            curNode = this.head
            while (curNode) {
                if (map[curNode.data] > 1) {
                    map[curNode.data]--
                    this.delete(curNode)
                } else {
                    curNode = curNode.next
                }
            }
        }
    }
    // 遍历链表
    browse (type = 'push', node = this.head) {
        if (!node) return []
        let curNode = this.head
        const result = []
        while (curNode) {
            result[type](curNode.data)
            curNode = curNode.next
        }
        return result
    }
    // 反转链表
    reverse () {
        if (!this.head) return
        let curNode = null
        let reversedList = this.head
        while (this.head && this.head.next) {
            curNode = this.head.next
            this.head.next = curNode.next
            curNode.next = reversedList
            reversedList = curNode
        }
        this.head = reversedList
        return this
    }
}
const myLinkList = new LinkList(0, 8, 1, 2)
console.log(myLinkList.browse())
myLinkList.insert(1, 3)
myLinkList.insertBefore(3, 4)
console.log(myLinkList.browse())
console.log(myLinkList.browse('unshift'))
console.log(myLinkList.reverse().browse())
const node2 = myLinkList.find(2)myLinkList.delete(node2)
console.log(myLinkList.browse())myLinkList.append(3, 4, 3, 6, 7)
console.log(myLinkList.browse())myLinkList.deleteRepeatNode()
console.log(myLinkList.browse())

/**约瑟夫环问题
 * @description 0,1,...,n-1这n个数字排成一个圆圈,从数字0开始,每次从这个圆圈里删除第m个数字。求出这个圆圈里剩下的最后一个数字。
 * @sum 总数,一共多少个节点 * @order 每次数到几,就删除这个节点。(从1开始数,每一轮从删除节点的下一个节点开始)
 * @returns 返回最后剩下的数字
 */
const josephCircle = (sum, order) =>  {
    // 创建链表环
    const circleList = new LinkList(...Array.from({ length: sum }, (val, index) => index))
    const node = circleList.find(sum - 1)
    node.next = circleList.head
    // 遍历
    let curNode = node
    while (curNode.next !== curNode) {
        for (let i = 0; i < order - 1; i++) {
            curNode = curNode.next
        }
        curNode.next = curNode.next.next
    }
    return curNode.data
}
console.log(josephCircle(10, 3))