6.链表

263 阅读1分钟

链表

数组的缺点

在java语言下, 数组的性能存在缺陷

  1. 数组定以后长度较为固定, 当进行插入和删除操作后都要对长度进行修改
  2. 数组删除和插入后,其他元素也要修改位置, 使得操作的消耗性能高

链表

链表是一堆节点的集合,每一个节点都有一个对象来指向他的后继,这样链接起来的节点就是链表 指向下一个节点的索引称为链

  • 链表删除: 上一个节点指向下一个节点
  • 链表插入: 上一个节点指向新的节点,新的节点指向下一个节点
function Node(element) {
        this.element = element
        this.next = null
    }
    function LList() {
        this.head = new Node('head')
    }
    LList.prototype = {
        find: function(item) {
            var currNode = this.head
            while(currNode.element != item) {
                currNode = currNode.next
            }
            return currNode
        },
        findPrev: function(item) {
            var current = this.head
            while(current.next != null && current.next.element != item) {
                current = current.next
            }
            return current
        },
        insert: function(newElement, item) {
            var newNode = new Node(newElement)
            var current = this.find(item)
            newNode.next = current.next
            current.next = newNode
        },
        remove: function(item) {
           var prevNode = this.findPrev(item)
           var currentNode = this.find(item)
           prevNode.next = currentNode.next
        },
        display: function() {
            var arr = []
            var current = this.head
            while(current.next != null) {
                arr.push(current.element)
                current = current.next
            }
            return arr
        }
    }
    var cities = new LList
    cities.insert('Conway', 'head')
    cities.insert('Russellvitlle', 'Conway')
    cities.insert('Alma', 'Russellvitlle')
    cities.display()
    cities.remove("Russellvitlle")

双向链表

    function Node(element) {
        this.element = element
        this.prev = null
        this.next = null
    }
    function DLList() {
        this.head = new Node('head')
    }
    DLList.prototype = {
        find: function (item) {
            var current = this.head
            while (current.element != item) {
                current = current.next
            }
            return current
        },
        findLast: function () {
            var current = this.head
            while (current.next != null) {
                current = current.next
            }
            return current
        },
        insert: function (newElement, item) {
            var newNode = new Node(newElement)
            var current = this.find(item)
            newNode.next = current.next
            newNode.prev = current
            current.next = newNode
        },
        remove: function (item) {
            var prevNode = this.find(this.find(item).prev.element)
            var nextNode = this.find(this.find(item).next.element)
            var target = this.find(item)
            prevNode.next = target.next
            nextNode.prev = target.prev
            target.prev = null
            target.next = null
        },
        display: function () {
            var arr = []
            var current = this.head
            while (current.next != null) {
                arr.push(current.element)
                current = current.next
            }
            arr.push(current.element)
            return arr
        },
        displayReverse: function () {
            var arr = []
            var lastNode = this.findLast()
            while (lastNode.prev != null) {
                arr.push(lastNode.element)
                lastNode = lastNode.prev
            }
            arr.push(current.element)
            return arr
        },
        advance: function (element, n) {
            var currentNode = this.find(element)
            var i = 0
            var targetNode = this.find(element)
            while (i < n) {
                targetNode = targetNode.prev
                i++
            }
            console.log(currentNode, targetNode)
            this.remove(currentNode.element)
            this.insert(currentNode.element, targetNode.prev.element)
        }
    }
    var step = new DLList()
    step.insert('create', 'head')
    step.insert('test','create')
    step.insert('open', 'test')
    step.insert('use', 'open')
    step.insert('end', 'use')
    step.advance('use', 3)
    step.display()

循环链表

循环链表类似于单项链表 在定义时 head.next = head

display: function() {
    var arr = []
    var current = this.head
    while(current.next!= null && current.next.element != 'head') {
        arr.push(current.element)
        current = current.next
    }
    return arr
}

advance

将当前节点提前N个位置,首先找到当前节点和目标节点
将当前节点删除,然后将他插入在目标节点的前面
advance: function (element, n) {
    var currentNode = this.find(element)
    var i = 0
    var targetNode = this.find(element)
    while (i < n) {
        targetNode = targetNode.prev
        i++
    }
    console.log(currentNode, targetNode)
    this.remove(currentNode.element)
    this.insert(currentNode.element, targetNode.prev.element)
}

完整代码

/**
     * 链表
    */
    // function Node(element) {
    //     this.element = element
    //     this.next = null
    // }
    // function LList() {
    //     this.head = new Node('head')
    // }
    // LList.prototype = {
    //     find: function(item) {
    //         var currNode = this.head
    //         while(currNode.element != item) {
    //             currNode = currNode.next
    //         }
    //         return currNode
    //     },
    //     findPrev: function(item) {
    //         var current = this.head
    //         while(current.next != null && current.next.element != item) {
    //             current = current.next
    //         }
    //         return current
    //     },
    //     insert: function(newElement, item) {
    //         var newNode = new Node(newElement)
    //         var current = this.find(item)
    //         newNode.next = current.next
    //         current.next = newNode
    //     },
    //     remove: function(item) {
    //        var prevNode = this.findPrev(item)
    //        var currentNode = this.find(item)
    //        prevNode.next = currentNode.next
    //     },
    //     display: function() {
    //         var arr = []
    //         var current = this.head
    //         while(current.next != null) {
    //             arr.push(current.element)
    //             current = current.next
    //         }
    //         return arr
    //     }
    // }
    // var cities = new LList
    // cities.insert('Conway', 'head')
    // cities.insert('Russellvitlle', 'Conway')
    // cities.insert('Alma', 'Russellvitlle')
    // cities.display()
    // cities.remove("Russellvitlle")

    /* 
    * 双向链表
    */
    // function Node(element) {
    //     this.element = element
    //     this.prev = null
    //     this.next = null
    // }
    // function DLList() {
    //     this.head = new Node('head')
    // }
    // DLList.prototype = {
    //     find: function (item) {
    //         var current = this.head
    //         while (current.element != item) {
    //             current = current.next
    //         }
    //         return current
    //     },
    //     findLast: function () {
    //         var current = this.head
    //         while (current.next != null) {
    //             current = current.next
    //         }
    //         return current
    //     },
    //     insert: function (newElement, item) {
    //         var newNode = new Node(newElement)
    //         var current = this.find(item)
    //         newNode.next = current.next
    //         newNode.prev = current
    //         current.next = newNode
    //     },
    //     remove: function (item) {
    //         var prevNode = this.find(this.find(item).prev.element)
    //         var nextNode = this.find(this.find(item).next.element)
    //         var target = this.find(item)
    //         prevNode.next = target.next
    //         nextNode.prev = target.prev
    //         target.prev = null
    //         target.next = null
    //     },
    //     display: function () {
    //         var arr = []
    //         var current = this.head
    //         while (current.next != null) {
    //             arr.push(current.element)
    //             current = current.next
    //         }
    //         arr.push(current.element)
    //         return arr
    //     },
    //     displayReverse: function () {
    //         var arr = []
    //         var lastNode = this.findLast()
    //         while (lastNode.prev != null) {
    //             arr.push(lastNode.element)
    //             lastNode = lastNode.prev
    //         }
    //         arr.push(current.element)
    //         return arr
    //     },
    //     advance: function (element, n) {
    //         var currentNode = this.find(element)
    //         var i = 0
    //         var targetNode = this.find(element)
    //         while (i < n) {
    //             targetNode = targetNode.prev
    //             i++
    //         }
    //         console.log(currentNode, targetNode)
    //         this.remove(currentNode.element)
    //         this.insert(currentNode.element, targetNode.prev.element)
    //     }
    // }
    // var step = new DLList()
    // step.insert('create', 'head')
    // step.insert('test','create')
    // step.insert('open', 'test')
    // step.insert('use', 'open')
    // step.insert('end', 'use')
    // step.advance('use', 3)
    // step.display()

    /*
    * 循环链表 约瑟夫问题
    */
    function Node(element) {
        this.element = element
        this.next = null
    }
    function CyLList() {
        this.head = new Node('head')
        this.head.next = this.head
    }
    CyLList.prototype = {
        find: function (item) {
            var currNode = this.head
            while (currNode.element != item) {
                currNode = currNode.next
            }
            return currNode
        },
        findPrev: function (item) {
            var current = this.head
            while (current.next != null && current.next.element != item) {
                current = current.next
            }
            return current
        },
        insert: function (newElement, item) {
            var newNode = new Node(newElement)
            var current = this.find(item)
            newNode.next = current.next
            current.next = newNode
        },
        remove: function (item) {
            var prevNode = this.findPrev(item)
            var currentNode = this.find(item)
            prevNode.next = currentNode.next
        },
        display: function () {
            var arr = []
            var current = this.head
            while (current.next != null && current.next.element != 'head') {
                arr.push(current.element)
                current = current.next
            }
            arr.push(current.element)
            return arr
        }
    }
    // 约瑟夫问题,N个人围成一圈,从头数数,数到M的人去死,然后从头数数
    function test(n, m) {
        var cycle = new CyLList()
        var people = []
        for (let i = 0; i < n; i++) {
            people.push(new Node(i))
            if (i == 0) {
                cycle.insert(i, 'head')
            } else {
                cycle.insert(i, i - 1)
            }
        }
        var index = 0
        var len = cycle.display().length - 1
        while (cycle.display().length - 1 > m || cycle.display().length - 1 == m) {
            index = (index + m - 1) % len
            console.log(index, people[index].element + '  killed')
            cycle.remove(people[index].element)
            // people.splice(index,1)
            console.log(cycle.display())
        }
    }

    // 约瑟夫问题的数组解法
    function countOff(num, m) {
        let players = [];
        for (let i = 1; i <= num; i++) {
            players.push(i);
        }
        let flag = 0
        while (players.length >= m) {
            let length = players.length
            flag = (flag + m - 1) % length
            console.log(`${players[flag]} is out`, flag)
            players.splice(flag, 1)  
            console.log("剩下:" + players);
        }
    }
    countOff(5, 3)