js实现简单双向链表封装

function DoublyLinkedList() {
            this.head = null;
            this.tail = null;
            this.length = 0;


            function Node(data) {
                this.previous = null;
                this.next = null;
                this.data = data;
            }

            DoublyLinkedList.prototype.append = function (data) {
                //创建新的节点
                var newNode = new Node(data);
                //判断是否为插入链表的第一个节点
                if (this.length === 0) {
                    this.head = newNode;
                    this.tail = newNode;
                } else {
                    //如果插入的元素不是链表的第一个节点
                    newNode.previous = this.tail;
                    this.tail.next = newNode;
                    this.tail = newNode;
                }
                this.length += 1;
            }

            DoublyLinkedList.prototype.forwardString = function () {
                var current = this.tail;
                var resultStr = '';
                while (current) {
                    resultStr += current.data + ' ';
                    current = current.previous;
                }
                return resultStr;
            }

            DoublyLinkedList.prototype.backwardString = function () {
                var current = this.head;
                var resultStr = '';
                while (current) {
                    resultStr += current.data + ' ';
                    current = current.next;
                }
                return resultStr;
            }

            DoublyLinkedList.prototype.toString = function () {
                return this.backwardString();
            }

            DoublyLinkedList.prototype.insert = function (position, data) {
                //判断越界
                if (position < 0 || position > this.length) return false;

                //创建新的节点
                var newNode = new Node(data);

                //如果当前链表是空链表
                if (this.length === 0) {
                    this.head = newNode;
                    this.tail = newNode;
                    //下面的情况都是插入时链表不为空
                } else if (position === 0) {
                    //如果插入的位置是索引为0,也就是第一个位置
                    newNode.next = this.head;
                    this.head.previous = newNode;
                    this.head = newNode;
                } else if (position === this.length) {
                    //如果插入的位置是索引为this.length,也就是最后一个位置
                    newNode.previous = this.tail;
                    this.tail.next = newNode;
                    this.tail = newNode;
                } else {
                    //如果插入的位置是索引为中间位置
                    var current = this.head;
                    var previous = null;
                    var count = 0;
                    while (count < position) {
                        //这样就通过循环找到了要插入的地方对应的元素current和它前一个元素previous
                        previous = current;
                        current = current.next;
                        count += 1;
                    }
                    newNode.previous = previous;
                    newNode.next = current;
                    current.previous = newNode;
                    previous.next = newNode
                }

                this.length += 1;
            }

            DoublyLinkedList.prototype.get = function (position) {
                //越界判断
                if (position < 0 || position >= this.length) return null;


                //我们把整个链表分为2段,前半段和后半段,根据position的值和length/2的值的大小关系
                //决定遍历的方向,这样提高性能
                //如果position属于后半段,我们就从后往前遍历
                //如果position属于前半段,我们就从前往后遍历

                var middle = Math.floor(this.length/2);


                //1.position属于前半段
                if (position < middle) {
                    //箭头指向的是遍历的方向从前往后
                    console.log('---->');
                    var index = 0;
                    var current = this.head;
                    while (index < position) {
                        current = current.next;
                        index += 1;
                    }
                } else {
                    //2.position属于后半段
                    //箭头指向的是遍历的方向从后往前
                    console.log('<----');
                    var index = this.length;
                    var current = this.tail;
                    while(index-1>position){
                        current = current.previous;
                        index -= 1;
                    }
                }

                return current.data;
            }

            DoublyLinkedList.prototype.indexOf = function(data){
                var index = 0;
                var current = this.head;
                while(current){
                   if(current.data == data){
                       return index;
                   }
                   current = current.next;
                   index += 1;
                }
                return -1;
            }

            DoublyLinkedList.prototype.update = function(position,data){
                //判断越界
                if(position<0 || position>=this.length) return false;
                
                //获取链表的中间值
                var middle = Math.floor(this.length/2);
                var current = null;
                //1.position属于前半段
                if(position<middle){
                    //从前往后遍历
                    var count = 0;
                    current = this.head;
                    while(count<position){
                        current = current.next;
                        count +=1;
                    }
                } else {
                    //2.position属于后半段
                    var count = this.length;
                    current = this.tail;
                    while(count>position+1){
                        count -=1;
                        current = current.previous;
                    }
                }

                //更新data
                current.data = data;

                return true;
            }

            DoublyLinkedList.prototype.removeAt = function(position) {
                if(position<0 || position>=this.length) return false;
                
                //如果链表里面只有一个元素
                if(this.length === 1){
                    this.head = null;
                    this.tail = null;
                } else {
                    //链表里有多个元素,删除索引为0的元素
                    if(position === 0){
                        this.head.next.previous = null;
                        this.head = this.head.next;
                    } else if(position === this.length-1){
                        //链表里有多个元素,删除最后一个元素
                        this.tail = this.tail.previous
                        this.tail.next = null;
                    } else {
                        //链表里有多个元素,删除中间一个元素
                        var current = this.head;
                        var previous = null;
                        var count = 0;
                        //通过循环找到要删除的元素的索引current和它前一个元素previous
                        while(count<position){
                            previous = current;
                            current = current.next;
                            count += 1;
                        }
                        current.next.previous = previous;
                        previous.next = current.next;
                        current.next = null;
                        current.previous = null;
                    }
                }

                this.length -=1;

                return true;
            }

            DoublyLinkedList.prototype.remove = function(data){
                var index = this.indexOf(data);
                this.removeAt(index);
            }
        }
        //Test测试代码
        var dllist = new DoublyLinkedList();
        dllist.append('rabbit');
        dllist.append('dog');
        dllist.append('kitten');
        dllist.append('fish');
        dllist.append('birdy');
        dllist.append('president-trump');

        console.log(dllist);

        console.log(dllist.forwardString());
        console.log(dllist.backwardString());

        dllist.insert(0, 'xxxx');
        console.log(dllist);
        console.log(dllist.backwardString());

        dllist.insert(7,'item1');
        dllist.insert(7,'item2');
        dllist.insert(7,'item3');
        dllist.insert(7,'item4');
        dllist.insert(7,'item5');
        dllist.insert(7,'item6');
        dllist.insert(7,'item7');
        console.log(dllist);
        console.log(dllist.backwardString());

        console.log(dllist.get(8));

        console.log(dllist.indexOf('president-trump'));
        console.log(dllist.indexOf('rabbit'));
        console.log(dllist.indexOf('item1'));
        console.log(dllist.indexOf('not-exist'));

        console.log(dllist.update(6,'asshole'));
        console.log(dllist);
        console.log(dllist.backwardString());

        // 11-->item3   change item3 to hehe
        console.log(dllist.update(11,'hehe'));
        console.log(dllist);
        console.log(dllist.backwardString());

        dllist.removeAt(0);
        console.log(dllist);
        console.log(dllist.backwardString());
        dllist.removeAt(12);
        console.log(dllist);
        console.log(dllist.backwardString());
        dllist.removeAt(11);
        console.log(dllist);
        console.log(dllist.backwardString());
        dllist.removeAt(5);
        console.log(dllist);
        console.log(dllist.backwardString());

Output:
在这里插入图片描述
下面是我画的一些便于理解的示例图
在这里插入图片描述
在这里插入图片描述
insert()方法的示例图
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值