前言
使用没有指针的语言模拟实现数据结构,会碰到一些莫名奇妙的问题
单向循环链表
之前学习的链表都是单向且最后一个节点指向空节点,如果最后一个节点指向头节点,这样就形成了一个环,名字叫单向循环列表,简称循环列表
源码(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可以共享数据,使用面向过程方式实现不方便