連結串列--約瑟夫環
阿新 • • 發佈:2018-12-26
/*
* 雙向連結串列:在連結串列的基礎上進行改進
* 特徵:首尾相連,即最後一個節點指向第一個節點
* 另外:新增一個length屬性
*
* */
/*
* 定義一個node節點
* element 節點名稱
* next 指向下個節點的指標
* */
function Node(element){
this.element = element;
this.next = null;
}
/*
* 建立節點
* */
function LList(){
this.head = new Node('head');
// 自己指向自己,形成一個環
this.head.next = this.head;
this.length = 0;
}
/*
* 根據節點名稱item查詢節點
* item 要查詢的節點的名稱
*
* 實現過程:
* 先找到首個節點(不為空),然後比較這個節點和名稱和要查詢的節點名稱是否一致
* 如果不一致,就將這個首個節點的下一個節點(不能為空)賦值給它,
* 直到找到為止
* */
LList.prototype.find = function (item) {
// 找到第一個節點,也就是當前的節點
let curNode = this.head;
// 如果當前節點不為空 && 名稱與查詢節點名稱不相同
// 那麼指向下一個節點,並且迭代
while( curNode !== null && curNode.element !== item ) {
curNode = curNode.next;
}
// 返回找到的節點
return curNode;
}
/*
* 在已有節點item後面新增一個新節點newElement
* newElement 新節點的名稱
* item 要插入到節點後的節點名稱
*
* 實現過程:
* 1.建立新節點newElement
* 2.找到item的節點
* 3.將item.next 賦值給新節點 newElement.next
* 即 newElement.next = item.next
* 4.item.next 指向新節點 newElement
* 即 item.next = newElement
* */
LList.prototype.insertAfter = function (newElement, item) {
// 1.建立新節點newElement
newElement = new Node(newElement);
// 2.找到item的節點
item = this.find(item);
// 3.將item.next 賦值給新節點 newElement.next
newElement.next = item.next;
// 4.item.next 指向新節點 newElement
item.next = newElement;
this.length++;
}
/*
* 找到當前節點的前一個節點
* item 當前節點的名稱
*
* 實現過程:
* 1.找到首個節點(不為空)
* 2.這個節點的下一個節點的名稱和要查詢的節點相同,就返回
* 否則,繼續迭代
*
* */
LList.prototype.findPrevious = function (item) {
let curNode = this.head;
while(curNode !== null && curNode.next.element !== item) {
curNode = curNode.next;
}
return curNode;
}
/*
* 刪除連結串列中的某個節點
* item : 要刪除的節點的名稱
* 實現過程:
* 1.找到要刪除節點的前一個節點
* 2.將前一個節點的下一個節點指向當前節點的下一個節點
* */
LList.prototype.remove = function (item) {
// 1.找到要刪除節點的前一個節點
let previousNode = this.findPrevious(item);
previousNode.next = this.find(item).next;
this.length--;
}
/*
* 打印出整個連結串列中的所有節點
*
*
* */
LList.prototype.display = function () {
let result = [];
if(this.length === 0) return [this.head.element];
let curNode = this.head;
while( curNode !== null && curNode.next.element !== 'head'){
result.push( curNode.element );
curNode = curNode.next;
}
result.push(curNode.element);
return result;
}
killGame(41, 3);
/*
* 殺人遊戲
* num 一共多少人
* step 每隔多少人殺人
*
* 實現過程
* 1,形成41人的約瑟夫環
* 2,每個3三人,刪除一個
* 3,最後剩下的兩位就是倖存者
* */
function killGame(num, step) {
let iNow = 0;
// 1,形成41人的約瑟夫環
let obj = new LList();
obj.insertAfter(1, 'head');
for ( let i = 1; i < num; i++ ) {
obj.insertAfter(i + 1, i);
}
// 當前的節點
let curNode = 'head';
kill();
// 2,每個3三人,刪除一個
function kill(){
if(obj.length < step) return;
iNow++;
// 尋找下一個節點
curNode = obj.find(curNode).next.element;
// 如果下一個節點是head,也就是說開始新的一輪殺人比賽
if(curNode === 'head'){
curNode = obj.find(curNode).next.element;
}
if(iNow === step){
let removeNode = curNode;
// 殺掉當前這個為三的人,然後執行之前的一個,再開始迭代
curNode = obj.findPrevious(curNode).element;
obj.remove(removeNode);
iNow = 0;
}
arguments.callee();
}
let luckyPerson = obj.display();
console.log('倖存的人是:' + luckyPerson[1] + ',' + luckyPerson[2]);
}