前言
使用没有指针的语言模拟实现数据结构,会碰到一些莫名奇妙的问题
单向循环链表
之前学习的链表都是单向且最后一个节点指向空节点,如果最后一个节点指向头节点,这样就形成了一个环,名字叫单向循环列表,简称循环列表
源码(JS模拟实现)
包含了头指针以及尾指针的实现
/**
* @desc 循环链表
*
* @author WadeYu
* @date 2015-08-15
* @copyright by WadeYu
*/
var Node = function(data){
this.data = data;
this.next = null;
};
var ListInit = function(ptr){
ptr.next = ptr;
};
var ListLength = function(ptr,bTail){
var len = 0;
var head = bTail ? ptr.next : ptr;
var curr = head.next;
while(curr != head){
len++;
curr = curr.next;
}
return len;
};
var ListClear = function(ptr){
ptr.next = ptr;
};
var ListInsert = function(ptr,i,node,bTail){
i = i - 1;
var len = ListLength(ptr,bTail);
if((i < 0) || (i > len)){
return false;
}
var pos = 0;
var curr = bTail ? ptr.next : ptr;
while(true){
if(pos == i){
break;
}
curr = curr.next;
pos++;
}
var tmp = curr.next;
curr.next = node;
node.next = tmp;
if(bTail && (pos == len)){
ptr = node;
}
return ptr; //JS变量赋值只在可见作用域范围才生效,因此这里需要返回
};
var ListDelete = function(ptr,i,bTail){
var len = ListLength(ptr,bTail);
if((i < 1)|| (i > len)){
return false;
}
var curr = bTail ? ptr.next : ptr;
var pos = 0;
while(true){
if(pos == (i-1)){
break;
}
curr = curr.next;
pos++;
}
var tmp = curr.next;
curr.next = tmp.next;
tmp = null;
if(bTail && (i == len)){
ptr = curr;
}
return ptr;
};
var GetElem = function(ptr,i,bTail){
if((i < 1) || (i > ListLength(ptr,bTail))){
return false;
}
var curr = bTail ? ptr.next : ptr;
var pos = 0;
while(true){
if(pos == i){
break;
}
curr = curr.next;
pos++;
}
return curr;
};
var Locate = function(ptr,node,bTail){
var pos = 0;
if(ListLength(ptr,bTail) < 1){
return -1;
}
var curr = bTail ? ptr.next.next : ptr.next;
var head = bTail ? ptr.next : ptr;
while( (curr != node) && (curr != head)){
pos++;
curr = curr.next;
}
if(curr == head){
return -1;
}
return pos;
};
var ListEmpty = function(ptr){
return ptr.next == ptr;
};
var print = function(ptr,bTail){
var head = bTail ? ptr.next : ptr;
var curr = bTail ? ptr.next.next : ptr.next;
var a = [];
while(curr != head){
a.push(curr.data);
curr = curr.next;
}
console.log(a.join(','));
};
var init = function(len,bTail){
var cl = new Node(0);
ListInit(cl);
for(var i = 1; i <= len; i++){
var tmp = ListInsert(cl,i,new Node(i),bTail);
cl = tmp ? tmp : cl;
}
return cl;
}
var ListTailMerge = function(ptr1,ptr2){
if(ListEmpty(ptr2)){
return false;
}
var tmp = ptr1.next;
ptr1.next = ptr2.next.next;
ptr2.next = tmp;
return ptr2;
};
应用---约瑟夫环
简介:一组数字,从左数到右,删除第N个数字,然后从新开始数,如此循环,直到剩下最后一个数字
分析:这个过程可以用循环链表模拟
var cl = init(50);
print(cl);
var num = 0;
var reject = 2;
var head = cl;
var curr = cl.next;
var tmp = {};
while(ListLength(cl) > 1){
if(curr != head){
num++;
}
if( num == reject ){
tmp = curr.next;
if(tmp != head){
num = 0;
curr.next = tmp.next;
}
}
curr = curr.next;
}
console.log("Last Number is : "+cl.next.data);
后记
1.因为JS是没有指针的弱类型语言,赋值操作只在可见作用范围内生效
2.JS模拟数据结构,最好通过OO的形式实现,OO可以共享数据,使用面向过程方式实现不方便