数据结构与算法 JavaScript实现链表

链表存储有序的指向元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素有一个存储元素本身节点和一个 指向下一元素的引用组成。

1.创建一个链表

 首先初始化链表LinkedList类

function LinkedList(){
    var Node = function element(){
        this.element = element;
        this.next = null
    }

var length = 0;
var head = null;

this.append = function(element){};
this.insert = function(position,element){};
this.removeAt = function(positon){};
this.remove = function(element){};
this.indexOf = function(element){};
this.isEmpty = function(){};
this.size = function(){};
this.getHead = function(){};
this.toString = function(){};
this.print = function(){};
}

1.1 向链表尾部追加元素

有两种情况,一种链表为空,添加的是第一个元素,另一种是链表不为空,向其追加元素

this.append = function(element){
    var node = new Node(element),
        current;

    if (head===null) {
        head = node;
    }
    else{
        current = head;
        while(current.next){
            current = current.next;
        }
        current.next = node;
    }
    
    length++
};

1.2 从链表中移除元素

移除也有两种场景,第一种是移除第一个元素,第二种是移除第一个以外的任意元素; 实现两种移除方法:第一种是从特定位置移除一个元素,第二种是根据元素的值移除元素

首先实现从给定位置移除一个元素的方法

this.removeAt = function(positon){
    // 检查越界值
    if (positon>-1&&positon<length) {
        var current = head,
            previous,
            index=0;
        // 移除第一项
        if (positon===0) {
            head = current.next;
        }
        else{
            while(index++<positon){
                previous = current;
                current = current.next;
            }
            // 将previous与current的下一项链接起来,跳过current,从而删除current
            previous.next = current.next;
        }
        length--;
        // 返回被删除的元素
        return current.element
    }
    else{
        return null;
    }
};

1.3 在任意位置插入一个元素

以下是insert方法的实现买这个方法可以再任意位置插入一个元素

this.insert = function(position,element){
    // 检查越界值
    if (positon>-1&&positon<length) {
        var node = new Node(element),
            current = head,
            privious,
            index = 0;
        // 在第一个位置插入
        if (positon===0) {
            node.next = current;
            head = node;
        }
        else{
            while(index++<positon){
                previous = current;
                current = current.next;
            }
            node.next = current;
            previous.next = node;
        }
        length++;
        return true;
    }
    else{
        return false;
    }
};

1.4 其它方法的实现

1.toString方法

this.toString = function(){
    var current = head,
        string = '';
    while(current){
        string += ","+current.element;
        current = current.next;
    }
    return string.slice(1);
};

2.indexOf方法

this.indexOf = function(element){
    var current = head,
        index = 0;

    while(current){
        if(element===current.element){
            return index;
        }
        index++;
        current = current.next;
    }
    return -1;
};

实现了这个方法之后,就可以实现上文中提到的移除指定元素的方法remove

this.remove = function(element){
    var index = this.indexOf(element);
    return this.removeAt(index);
};

2.isEmpty,size,getHead方法

this.isEmpty = function(){
    return length = 0;
};
this.size = function(){
    return length;
};
this.getHead = function(){
    return head;
};

isEmpty方法判断链表是否为空,size方法返回链表的长度,getHead返回链表的一个节点

2.双向链表

双向链表中:一个链向下一个元素,另一个链向前一个元素

function DoubleLinkedList(){
    var Node = function(element){
        this.element = element;
        this.next = null;
        this.prev = null;
    };

    var length = 0;
    var head = null;
    var tail = null;
}

 双向链表提供了两种迭代链表的方法,从头到尾或者从尾到头。

2.1 在任意位置插入一个元素

this.insert = function(positon,element){
        // 检查越界值
        if (positon>-1&&positon<length) {
            var node = new Node(element),
                current = head,
                previous,
                index = 0;
            // 在第一个位置插入
            if (positon===0) {
                if (!head) {
                    head = node;
                    tail = node;
                }
                else{
                    node.next = current;
                    current.prev = node;
                    head = node;
                }
            }
            else if (positon === length) {
                current = tail;
                current.next = node;
                node.prev = current;
                tail = node;
            }
            else{
                while(index++<positon){
                    previous = current;
                    current = current.next;
                }
                node.next = current;
                previous.next = node;

                current.previous = node;
                node.prev = previous;
            } 

            length++;

            return true;
        }
        else{
            return false;
        }
    }

2.2 从任意位置移除元素

this.removeAt = function(){
        // 检查越界值
        if (positon>-1&&positon<length){
            var current = head,
                previous,
                index = 0;
            // 移除第一项
            if (positon === 0) {
                head = current.next;
                // 如果只有一项,更新tail
                if (length === 1) {
                    tail = null;
                }
                else{
                    head.prev = null;
                }
            }
            else if(positon === length-1){
                current = tail;
                tail = current.prev;
                tail.next = null;
            }
            else{
                while(index++<positon){
                    previous = current;
                    current = current.next;
                }

                // 将previous和current的下一项链接起来
                previous.next = current.next;
                current.next.prev = previous;
            }
            length--;

            return current.element;
        }
        else{
            return null;
        }
    }

3.循环链表

循环链表和链表唯一区别就是,最后一个元素指向下一个元素的指针不是引用null,而是指向第一个元素。

原文地址:https://www.cnblogs.com/Cathamerst/p/7217630.html