数据结构学习系列之线性表(四)

前言

使用没有指针的语言模拟实现数据结构,会碰到一些莫名奇妙的问题

单向循环链表

之前学习的链表都是单向且最后一个节点指向空节点,如果最后一个节点指向头节点,这样就形成了一个环,名字叫单向循环列表,简称循环列表

源码(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可以共享数据,使用面向过程方式实现不方便

作者:WadeYu
出处:http://www.cnblogs.com/wadeyu/
本文版权归本人和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/wadeyu/p/4734878.html