js数据结构------双向链表

一 .认识双向链表

单向链表:

之前说了单向链表,单向链表在插入和删除数据的时候效率会比数组快很多,但是在进行查找操作时效率就比较低,因为单向链表只能从头遍历到尾或者从尾遍历到头,也就是链表相连的过程是单向的。比如说当前的节点要到下一个节点是很容易的,但是要到上一个节点,就必须从头开始再次遍历。

为了解决单向链表只能从头遍历到尾的问题,就引出了双向链表。

双向链表:

双向链表相连的过程是双向的, 一个节点既有向前连接的引用, 也有一个向后连接的引用.我们在查找上一个节点的时候就不用从头开始遍历,根据向前连接的引用就能查找到上一个节点。

但是双向链表有什么缺点呢?
每次在插入或删除某个节点时, 需要处理四个节点的引用, 而不是两个. 也就是相对于单向链表来说实现起来要困难一些, 而且必然占用内存空间更大一些.但是这些缺点和我们使用起来的方便程度相比, 是微不足道的.
双向链表图解:网上找的图侵删

双向链表的封装:

<script>
    function DoublyLinkedList() {
        //创建节点构造函数
        function Node(data) {
            this.prev = null;
            this.data = data;
            this.next = null;
        }
        //属性
        this.head = null;
        this.tail = null;
        this.length = 0;

        //1.向列表尾部添加一个新的项
        DoublyLinkedList.prototype.append = function (data) {
            let newNode = new Node(data);
            if (this.length === 0){
                this.head = newNode;
                this.tail = newNode;
            }else{
                newNode.prev = this.tail;
                this.tail.next = newNode;
                this.tail = newNode;
            }
            this.length += 1;
        };
        //2.向列表特定位置插入一个新的项
        DoublyLinkedList.prototype.insert = function (position,data) {
            //越界判断
            if(position<0 || position>this.length) return false;
            //创建新的节点
            let newNode = new Node(data);
            if(this.length === 0){
                 this.head = newNode ;
                 this.tail = newNode ;
            }else{
                //当插入的是第一个节点时的情况
                if(position === 0){
                    this.head.prev = newNode;
                    newNode.next = this.head;
                    this.head = newNode;
                }else if(position === this.length){  //插入最后一个节点的情况
                    newNode.prev = this.tail;
                    this.tail.next = newNode;
                    this.tail = newNode;
                }else{  //其他情况
                    let current = this.head;
                    let index = 0;
                    while (index < position){
                        current = current.next;
                        index ++;
                    }
                    newNode.prev = current.prev;
                    newNode.next = current;                    				 	
                    current.prev.next = newNode;
                    current.prev = newNode;    //一直都在最后一步更新新的节点
                }
            }
            this.length += 1;
            return true;
        };
        //3.获取对应位置的元素
        DoublyLinkedList.prototype.get = function (position) {
            if(position<0 || position>=this.length) return false;  //这里的取值position不能等于length因为在length处没有数据

            //为了节省效率,可以采取以下方法
            // this.length / 2 < position   :采用从前往后遍历
            // this.length / 2 > position   :采用从后往前遍历
           if(this.length / 2 < position){
               let index = 0;
               let current = this.head;
               while (index < position){
                   current = current.next;
                   index ++;
               }
               return current.data;
           }else{
               let index = this.length - 1;
               let current = this.tail;
               while (index > position){
                   current = current.prev;
                   index --;
               }
               return current.data;
           }
        };
        //4.返回元素在列表中的索引,如果没有该元素则返回-1
        DoublyLinkedList.prototype.indexof = function (data) {
            let index = 0;
            let current = this.head;
            while (current){
                if (current.data === data){
                    return index;
                }else{
                    current = current.next;
                    index += 1;
                }
            }
            return -1;
        };
        //5.修改某个位置的元素
        DoublyLinkedList.prototype.updata = function (position,newData) {
            if(position < 0 || position >= this.length) return false;
            let index = 0;
            let current = this.head;
            while (index ++ < position){
                current = current.next;
            }
            current.data = newData;
            return true;
        };
        //6.从列表指定位置移除一项,根据位置
        DoublyLinkedList.prototype.removeAt = function (position) {
            if (position < 0 || position >= this.length) return null;
            let current = this.head;
            //只有一个节点的情况
            if (this.length === 1){
                this.head = null;
                this.tail = null;
            } else{
                if(position === 0){
                    this.head.next.prev = null;
                    this.head = this.head.next;
                }else if(position === this.length - 1){
                    let current = this.tail;
                    this.tail.prev.next = null;
                    this.tail = this.tail.prev;
                }else{
                    let index = 0;
                    while(index ++ < position){
                        current = current.next;
                    }
                    current.prev.next = current.next;
                    current.next.prev = current.prev;
                }
            }
            this.length -= 1;
            return current.data; //返回被删除节点的数据

        };
        //7.从列表中移除一项,根据数据
        DoublyLinkedList.prototype.remove = function (data) {
            this.removeAt(this.indexof(data));
        };
        //8.判断链表是否为空
        DoublyLinkedList.prototype.isEmpty = function () {
            return this.length === 0;
        };
        //9.返回链表的长度
        DoublyLinkedList.prototype.size = function () {
            return this.length;
        };
        //10.tostring()方法
        DoublyLinkedList.prototype.tostring= function () {
          return this.backwordString;

        };
        //11.返回正向遍历的节点字符串形式,将链表里面的数据从后往前遍历并返回字符串形式
        DoublyLinkedList.prototype.forwardString = function () {
            let resultString = '';
            let current = this.tail;
            while (current){
                resultString += current.data + ' ';
                current = current.prev;
            }
            return resultString;
        };
         //12.返回反向遍历的节点字符串形式,将链表里面的数据从前往后遍历并返回字符串形式
        DoublyLinkedList.prototype.backwordString = function () {
            let resultString = '';
            let current = this.head;
            while (current){
                resultString += current.data + ' ';
                current = current.next;
            }
            return resultString;
        };

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值