传说在公元1 世纪的犹太战争中,犹太历史学家弗拉维奥·约瑟夫斯和他的40 个同胞被罗马士兵包围。犹太士兵决定宁可自杀也不做俘虏,于是商量出了一个自杀方案。他们围成一个圈,从一个人开始,数到第三个人时将第三个人杀死,然后再数,直到杀光所有人。约瑟夫和另外一个人决定不参加这个疯狂的游戏,他们快速地计算出了两个位置,站在那里得以幸存。写一段程序将n个人围成一圈,并且第m个人会被杀掉,计算一圈人中哪两个人最后会存活。使用循环链表解决该问题。
这个问题就是典型的循环链表的应用,实现了循环链表后还有个问题就是找到特定元素之后的移动问题。
如下是具体链表的实现过程:
function Node(ele) { this.ele = ele; this.next = null; } function LList() { this.head = new Node("head"); this.head.next = this.head; this.currentNode = this.head; } LList.prototype.find =function (item) { var currNode = this.head; while(currNode.ele != item) { currNode = currNode.next; } return currNode; }; LList.prototype.insert = function (newEle,item) { var newNode = new Node(newEle); var current = this.find(item); newNode.next = current.next; current.next = newNode; }; LList.prototype.display = function() { var currNode = this.head; while(!(currNode.next == null) && !(currNode.next.ele == "head")) {//这点有区别当前节点的后继不为空或者当前节点的后继元素不为头节点 console.log(currNode.next.ele); currNode = currNode.next; } }; LList.prototype.findPrevious = function (item) { var currNode = this.head; while(!(currNode.next == null) && (currNode.next.ele != item )) {//当前节点的后继不为空或者后继节点不为所要查找的元素时 currNode = currNode.next;//修改后继链 } return currNode;//找到时返回 }; LList.prototype.remove = function(item) { var prevNode = this.findPrevious(item);//找到删除元素的前一个元素 if(!(prevNode.next == null)) {//待删除元素不为空 prevNode.next = prevNode.next.next;//待删除元素的前驱的后继修改为待删除元素的后继的后继 } }; //当前链表中有多少个元素 LList.prototype.count = function(){ var node = this.head; var i = 0; while (!(node.next.ele == "head")){ node = node.next; i++; } return i; }; //向前移动n个节点 LList.prototype.advance = function(n){ while (n>0){ if(this.currentNode.next.ele == "head"){ this.currentNode = this.currentNode.next.next; }else{ this.currentNode = this.currentNode.next; } n--; } };
下面是测试部分:(有点小兴奋哦~~)
var per = new LList(); per.insert("1","head"); per.insert("2","1"); per.insert("3","2"); per.insert("4","3"); per.insert("5","4"); per.insert("6","5"); per.insert("7","6"); per.insert("8","7"); per.insert("9","8"); per.insert("10","9"); var num = 3; while(per.count() >2 ) {//个数大于2,从三开始进行移动 per.advance(num); per.remove(per.currentNode.ele); per.display(); }
输出结果:
第一次:1 2 4 5 6 7 8 9 10
第二次:1 2 4 5 7 8 9 10
第三次:1 2 4 5 7 8 10
第四次:1 4 5 7 8 10
第五次:1 4 5 8 10
第六次:4 5 8 10
第七次:4 5 10
第八次:4 10