日界线是指日期的分界线,国际规定180度经线,但这不是一条直线,是一条曲线
又是一个别人开心ipo痛哭的日子呜呜呜图片描述

先讲个故事,公元1世纪犹太战争,犹太人被包围了,不想被俘虏的“勇士”宁可自杀,首领指着最近的一个说

‘从你开始往后数,数到第三个,他就自杀,再从他下一个开始数,数到第三个自杀,后面的一样,开始吧’

其中聪明的两个人想办法插队,不想就这样死了(其中一个就是约瑟夫)

呵呵这是在告诉我“最困难的一刻,只要去想,总有解决的办法”

来吧,看聪明的ipo怎么解决的

通用的,n个人,第m个自杀,留下的是第几个呢

 /*
    实例
    使用循环链表解决约瑟夫环问题
     */
    function lastTwo(n, m) {
        var list = new LList();
        list.insert(1, "head");
        for (var i = 2; i <= n; i++) {
            list.insert(i, i - 1);
        }
        var currNode = list.head.next;
        var removeNode = null;
        while (list.length >= m) {
            removeNode = move(currNode, m);
            list.remove(removeNode.value);
            currNode = removeNode.next;
        }
        return list.display();
    }

    function move(currNode, m) {
        for (var i = 1; i < m; i++) {
            if (currNode.value === 'head') {
                i -= 1;
            }
            currNode = currNode.next;
        }
        return currNode;
    }
    lastTwo(3, 3);

实现原理是什么的,慢慢从基础理解

  1. 单向链表

    主要阐述了链表是怎么一回事:节点+链

    上代码:

function Node(elem) {
//两个类:Node当前节点数据以及下一个节点的引用,LList头节点以及操作链表的方法
    this.elem = elem;
    this.next = null;
}

function LList() {
    this.head = new Node("head");
    this.find = find;
    this.findPrevious = findPrevious;
    this.insert = insert;
    this.remove = remove;
    this.display = display;
}

function find(item) {
    var currNode = this.head;
    while (currNode.elem !== item) {
        currNode = currNode.next;
    }
    return currNode;
}

function findPrevious(item) {
    var currNode = this.head;
    while (currNode.next !== null && currNode.next.elem !== item) {
        currNode = currNode.next;
    }
    return currNode;
}

function insert(newElem, item) {
    var newNode = new Node(newElem);
    var currNode = this.find(item);
    newNode.next = currNode.next;
    currNode.next = newNode;
}

function remove(item) {
    var prevNode = this.findPrevious(item);
    if (prevNode.next !== null) {
        prevNode.next = prevNode.next.next;
    }
}

function display() {
    var currNode = this.head;
    while (currNode.next !== null) {
        console.log(currNode.next.elem);
        currNode = currNode.next;
    }
}
/*
创建一个实例
 */
var cities = new LList();
cities.insert("Conway", "head");
cities.insert("Russellville", "Conway");
cities.display();

今天进行了如下优化,封装,继承

/*
        链表=节点+链
        节点=节点值+next(节点的引用指向后继)
        链=头结点声明初始化+方法+属性
         */
(function(window) {
    function Node(value) {
        this.value = value;
        this.next = null;
    }

    var uList = function() {
        this.head = new Node("head");
        this.length = 0;
    };
    uList.prototype.find = function(value) {
        if (value === "head") {
            return this.head;
        }
        var currNode = this.head.next;
        while (currNode !== null) {
            if (currNode.value === value) {
                return currNode;
            } else {
                currNode = currNode.next;
            }
        }
        return -1;
    };
    uList.prototype.insert = function(newValue, currValue) {
        var newNode = new Node(newValue);
        var currNode = this.find(currValue);
        if (currNode !== -1) {
            newNode.next = currNode.next;
            currNode.next = newNode;
        } else {
            alert("未找到要插入的位置元素");
        }
    };
    uList.prototype.findPrevious = function(value) {
        if (value === "head") {
            return -1;
        }
        var currNode = this.head;
        while (currNode.next !== null) {
            if (currNode.next.value === value) {
                return currNode;
            } else {
                currNode = currNode.next;
            }
        }
        return -1;
    };
    uList.prototype.remove = function(value) {
        var currNode = this.find(value);
        if (currNode !== -1) {
            var preNode = this.findPrevious(value);
            if (preNode !== -1) {
                preNode.next = currNode.next;
            } else {
                alert("未找到删除的元素");
            }
        } else {
            alert("未找到删除的元素");
        }
    };
    uList.prototype.display = function() {
        var currNode = this.head.next;
        while (currNode !== null) {
            console.log(currNode.value);
            currNode = currNode.next;
        }
    };

    var List = function() {
        uList.call(List);
    };
    List.prototype = new uList();
    window.List = List;
})(window);
/*
试一下
 */
var mylist = new List();
mylist.insert(1, "head");
mylist.display();

单向链表是最简单的链表,JS中把数组搞成对象,性能势必不行了,可以自己造个链表替代数组。不过随机访问一个元素还是数组好些。

  • 双向链表
    双向链表比单向链表相比node多了前置引用,方法删除操作修改next的同时要修改pre

function Node(elem){
    this.elem=elem;
    this.previous=null;
    this.next=null;
}
function LList(){
    this.head=new Node("head");
    this.find=find;
    this.findPrevious=findPrevious;
    this.insert=insert;
    this.remove=remove;
    this.display=display;
    this.displayReverse=displayReverse;
}
function find(elem){
    var currNode=this.head;
    while(currNode.elem!==elem&&currNode.next!==null){
        currNode=currNode.next;
    }
    return currNode;
}
function findPrevious(){
    var currNode=this.head;
    while(currNode.next!==null){
        currNode=currNode.next;
    }
    return currNode;
}
function insert(newElem,item){
    var currNode=this.find(item);
    var newNode=new Node(newElem);
    if(currNode.next!==null){
        currNode.next.previous=newNode;
        newNode.next=currNode.next;
    }
    newNode.previous=currNode;
    currNode.next=newNode;
}
function remove(elem){
    var currNode=this.find(elem);
    if(currNode.next!==null){
        currNode.next.previous=currNode.previous;
    }
    currNode.previous.next=currNode.next;
}
function display(){
    var currNode=this.head;
    while(currNode.next!==null){
        console.log(currNode.next.elem);
        currNode=currNode.next;
    }
}
function displayReverse(){
    var currNode=this.findPrevious();
    while(currNode.previous!==null){
        console.log(currNode.previous.elem);
        currNode=currNode.previous;
    }    
}

  • 循环链表
    循环链表与单向链表相比,强调最后一个节点的引用后继是head,所以初始化链表时头结点时后继是head本身

function Node(elem){
    this.elem=elem;
    this.next=null;
}
function LList(){
    this.head=new Node("head");
    this.head.next=this.head;
    this.find=find;
    this.insert=insert;
    this.findPrevious=findPrevious;
    this.remove=remove;
    this.display=display;
}
function find(elem){
    var currNode=this.head;
    while(currNode.next!==this.head&&currNode.elem!==elem){
        currNode=currNode.next;
    }
    return currNode;
}
function insert(newElem,item){
    var currNode=this.find(item);
    var newNode=new Node(newElem);
    if(currNode.next!==this.head){
        newNode.next=currNode.next;
        currNode.next=newNode;
    }else{
        currNode.next=newNode;
        newNode.next=this.head;
    }
}
function findPrevious(elem){
    var currNode=this.head;
    while(currNode.next.elem!==elem){
        currNode=currNode.next;
    }
    return currNode;
}
function remove(elem){
    var prevNode=this.findPrevious(elem);
    var currNode=this.find(elem);
    prevNode.next=currNode.next;
}
function display(){
    var currNode=this.head;
    while(currNode.next!==this.head){
        console.log(currNode.next.elem);
        currNode=currNode.next;
    }
}

优化一下就是文章开头的例子中用到的了

   (function(window) {
        function Node(value) {
            this.value = value;
            this.next = null;
        }

        function list() {
            this.head = new Node("head");
            this.head.next = this.head;
            this.length = 0;
        }
        list.prototype.find = function(elem) {
            if (elem === "head") {
                return this.head;
            }
            var curr = this.head.next;
            while (curr !== this.head) {
                if (curr.value === elem) {
                    return curr;
                } else {
                    curr = curr.next;
                }
            }
            return -1;
        };
        list.prototype.insert = function(newValue, currValue) {
            var newNode = new Node(newValue);
            var currNode = this.find(currValue);
            if (currNode === -1) {
                alert("未找到插入位置的元素");
            } else {
                newNode.next = currNode.next;
                currNode.next = newNode;
                this.length++;
            }
        };
        list.prototype.findPrevious = function(currValue) {
            if (this.head.next.value === currValue) {
                return this.head;
            }
            var curr = this.head.next;
            while (curr !== this.head) {
                if (curr.next.value === currValue) {
                    return curr;
                } else {
                    curr = curr.next;
                }
            }
            return -1;
        };
        list.prototype.remove = function(elem) {
            var curr = this.find(elem);
            if (curr === -1) {
                alert("找不到要删除的元素");
            } else {
                var pre = this.findPrevious(elem);
                if (pre === -1) {
                    alert("找不到要删除的元素");
                } else {
                    pre.next = curr.next;
                    this.length--;
                }
            }
        };
        list.prototype.display = function() {
            var curr = this.head;
            while (curr.next !== this.head) {
                console.log(curr.next.value);
                curr = curr.next;
            }
        };

        var LList = function() {
            list.call(LList);
        };
        LList.prototype = new list();
        window.LList = LList;
    })(window);

_ipo
179 声望15 粉丝

bug