原生js手写java链表集合

 

链表集合是java中的多种集合之一,从名字就能听的出,这种集合它的底层实现使用了链表。

链表是一种数据结构,它的排列方式很像一根链条,链表是由很多节点组成的,每个节点包含三个属性,previous,Value,next

previous存储着上一个节点,next指向下一个节点,value存储着当前节点的数据,链表就是使用这样的方式将每个节点连接在一

起,像链条一样,环环相扣

使用链表的好处在于,它的插入和修改的效率很高,这个和数组不同,拿数组来说

[1,3,4,6,8,9,2]
例如我们想在下标1的位置插入一个元素,那么就需要将后面元素的都整体向后移动一位

 但如果使用链表的话,就不需要这么麻烦,在java中,我们向链表的某个位置插入一个元素时,它底层实现是这样的

例如我想在第3个节点后面插入一个新节点,那么它只需要将第3个节点的next属性指向新节点,在将第4个节点的previous属性也指向新节点,然后将新节点的previous属性指向节点3,在将新节点的next属性指向节点4,这样就将新节点放到节点3和节点四之间了。也就是将节点3的下一个节点的位置指向新节点,在将节点4的上一个节点的位置指向新节点,然后将新节点的previous和next属性分别指向节点3和节点4。

那么删除也是一样的,例如想删除节点3,那么只需要让节点2的next不在指向节点3,节点4的previous也不在指向节点3,那么这样就把节点3删除了。

链表的增删改的效率很高,但是查询的效率很低,从它结构就能看的出,它需要访问每个节点的next属性才能到下一个节点中去,所以查询很慢

好了,链表节点的介绍就到这里,下面贴出js实现的链表集合源码

/**
 * 链表中的每个节点
 * @param {*} element 本节点的数据
 * @param {*} previous 上一个节点
 * @param {*} next 下一个节点
 */
function Node(element){
    this.previous = null;
    this.element = element;
    this.next = null;
}
Node.prototype.getElement=function(){
    return this.element;
}
/**
 * 链表 构造函数
 * @param {*} first 头部节点
 * @param {*} last 尾部节点
 * @param {*} size 链表集合的长度
 */
function LinkedList(){
    this.first = null;
    this.last = null;
    this.size = 0;
}

//[a,b,c]
/**
 * [a,b,c,d,e,f,g]
 * 往链表中添加元素
 * @param element 插入的元素
 */
LinkedList.prototype.add = function(element){
    this.size++;
    let node = new Node(element);
    if(this.first==null){
        this.first = node;
        this.last = node;
    }else{
        this.last.next = node;
        node.previous = this.last;
        this.last = node;
    }
}

LinkedList.prototype.insert = function(element,index){
    let currentNode = this.get(index);
    let node  = new Node(element);
    if(index==0){
        currentNode.previous = node;
        node.next = currentNode;
        this.first = node;
    }else if(index==this.size-1){
        currentNode.next = node;
        node.previous = currentNode;
        this.last = node;
    }else{
        currentNode.previous.next  = node;
        node.next = currentNode;
        node.previous = currentNode.previous;
        currentNode.previous = node;
    }
    this.size++;
}

/**
 * 打印链表中的元素
 */
LinkedList.prototype.toString = function(){
    let str = "["+this.first.element;
    let nextNode = this.first.next;
    for(let i=0;i<this.size;i++){
        if(nextNode==null){
            break;
        }
        str+=","+nextNode.element;
        nextNode = nextNode.next;
    }
    str+="]"
    console.log(str);
}

/**
 * 返回链表的长度
 */
LinkedList.prototype.getSize = function(){
    return this.size;
}

/**
 * 返回指定下标的元素
 * @param index 下标
 */
LinkedList.prototype.get = function(index){
    if(!this.checkIndex(index)){
        return "下标错误"; 
    }
    if(index==0){
        return this.first;
    }
    let nextNode = this.first.next;
    for(let i=1;i<this.size;i++){
        if(nextNode==null){
            break;
        }
        if(i==index){
            return nextNode;
        }
        nextNode = nextNode.next;
    }
}

/**
 * 删除链表中的某个元素,删除成功返回true
 * 删除失败返回false
 */
LinkedList.prototype.remove = function(index){
    if(!this.checkIndex(index)){
        return false;
    }
    let nodes = this.get(index);
    if(index==0){
        nodes.next.previous = null;
        this.first = nodes.next;
    }else if(index==this.size-1){
        nodes.previous.next = null;
        this.last = nodes.previous;
    }else{
        let prevNodes = nodes.previous;
        nodes.previous.next  =nodes.next;
        nodes.next.previous = prevNodes;
    }
    this.size--;
    return true;
}

/**
 * 为空则返回true 否则返回false
 */
LinkedList.prototype.isEmpty = function(){
    return this.size>0 ? false : true;
}

/**
 * 检测下标是否合法
 */
LinkedList.prototype.checkIndex = function(index){
    if(index<0||index>=this.size){
        return false;
    }else{
        return true;
    }
}

 现在可以将js文件引入,试试效果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>LinkedList</title>
</head>
<body>
    <script type="text/javascript" src="./LinkedList.js"></script>
    <script type="text/javascript">
        /**
         * 插入添加删除元素效率高
         * 但是读取元素效率低 
         */

        let linkedlist = new LinkedList();
        //往链表里添加数据
        linkedlist.add("a");
        linkedlist.add("b");
        linkedlist.add("c");
        linkedlist.add("d");
        linkedlist.add("e");
        linkedlist.add("f");
        linkedlist.add("g");
        //打印链表集合
        linkedlist.toString();

        //输出链表长度
        console.log("返回集合长度",linkedlist.getSize());

        //根据下标返回指定位置的节点
        console.log("获取下标6的元素",linkedlist.get(linkedlist.getSize()-1).getElement());

        //判断集合是否为空
        console.log("集合是否为空",linkedlist.isEmpty());

        //删除集合中指定下标的元素
        console.log("删除下标6",linkedlist.remove(6));
        linkedlist.toString()

        //在指定下标位置插入元素
        linkedlist.insert("A",0);
        console.log("在集合开头插入元素A");
        linkedlist.toString();

        linkedlist.insert("B",linkedlist.getSize()-1);
        console.log("在集合末尾插入元素B");
        linkedlist.toString();

        linkedlist.insert("G",4);
        console.log("在集合下标为4的位置插入元素G");
        linkedlist.toString();

        //利用for循环打印链表集合中的每个元素
        for(let i=0;i<linkedlist.getSize();i++){
            console.log(linkedlist.get(i));
        }
    </script>
</body>
</html>

看看效果

没有问题

当然这里是用js的方式实现的,用java去手写一个链表用的方式也大同小异。

当然了,这只是写着玩而已,js自带的数组就够我们用的了,写个链表只是想深入理解一下链表的底层实现原理

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值