JavaScript数据结构(双向链表)

双向链表&单向链表

单向链表:只能从一端向另一端遍历

双向链表:既可以从头部向尾部开始遍历,也可以熊尾部向头部开始遍历。

一个head指针指向第一个节点,一个tail指针指向最后一个节点。

当没有节点时,head指针和tail指针都指向NULL。

在这里插入图片描述

双向链表常见的操作

  • append(element) 向链表尾部追加一个新元素。
  • insert(position, element) 向链表的指定位置插入一个新元素。
  • getElement(position) 获取指定位置的元素。
  • indexOf(element) 返回元素在链表中的索引。如果链表中没有该元素就返回 -1。
  • update(position, element) 修改指定位置上的元素。
  • removeAt(position) 从链表中的删除指定位置的元素。
  • remove(element) 从链表删除指定的元素。
  • isEmpty() 如果链表中不包含任何元素,返回 trun,如果链表长度大于 0 则返回 false
  • size() 返回链表包含的元素个数,与数组的 length 属性类似。
  • toString() 由于链表项使用了 Node 类,就需要重写继承自 JavaScript 对象默认的 toString 方法,让其只输出元素的值。
  • forwardString() 返回正向遍历节点字符串形式。
  • backwordString() 返回反向遍历的节点的字符串形式。
  • getHeadNode()获取第一个节点
  • getTailNode()获取最后一个节点

JavaScript代码双向链表的封装

class Node {
    constructor(data) {
        this.data = data;
        this.prev = null;
        this.next = null;
    }
}

class DoublyNodeList {
    constructor() {
        this.head = null;
        this.length = 0;
        this.tail = null;
    }
    append(element) {
        const node = new Node(element);
        if (this.length == 0) {
            this.head = node;
            this.tail = node;
        } else {
            node.prev = this.tail;
            node.prev.next = node;
            this.tail = node;
        }
        this.length += 1;
    }
    insert(position, element) {
        const node = new Node(element);
        // 越界判断
        if (position < 0 || position > this.length) {
            return false;
        }
        if (position == 0) {
            node.next = this.head;
            node.next.prev = node;
            this.head = node;
        } else if (position == this.length) {
            this.tail.next = node;
            node.prev = this.tail;
            this.tail = node;
        } else {
            //插入的时候判断position的位置离第一个节点近还是最后一个节点近
            //离第一个节点近从前往后开始遍历查找
            //离最后一个节点近从后往前开始遍历查找
            //同下方代码,未作抽离
            const flag = Math.ceil((this.length - 1) / 2);
            if (flag > position) {
                let current = this.head;
                let index = 0;
                while (index < position) {
                    index += 1;
                    current = current.next;
                }
                node.prev = current.prev;
                node.prev.next = node;
                node.next = current;
                current.prev = node;
            } else {
                let index = this.length - 1;
                let current = this.tail;
                while (index > position) {
                    index -= 1;
                    current = current.prev;
                }
                node.prev = current.prev;
                node.prev.next = node;
                node.next = current;
                current.prev = node;
            }

        }
        this.length += 1;
    }
    getData(position) {
        if (position < 0 | position >= this.length) {
            return -1;
        }
        const flag = Math.ceil((this.length - 1) / 2);
        if (flag > position) {
            let index = 0;
            let current = this.head;
            while (index < position) {
                index += 1;
                current = current.next;
            }
            return current.data;
        } else {
            let index = this.length - 1;
            let current = this.tail;
            while (index > position) {
                index -= 1;
                current = current.prev;
            }
            return current.data;
        }
    }
    indexOf(data) {
        let current = this.head;
        let index = 0;
        while (current) {
            if (current.data == data) {
                return index;
            }
            index += 1;
            current = current.next;
        }
        return -1;
    }
    update(position, data) {
        if (position < 0 || position >= this.length) {
            return false;
        }
        const flag = Math.ceil((this.length - 1) / 2);
        if (flag > position) {
            let index = 0;
            let current = this.head;
            while (index < position) {
                index += 1;
                current = current.next;

            }
            current.data = data;
            return current.data;

        } else {
            let index = this.length - 1;
            let current = this.tail;
            while (index > position) {
                index -= 1;
                current = current.prev;
            }
            current.data = data;
            return current.data;
        }
    }
    removeAt(position) {
        if (position < 0 || position >= this.length) {
            return -1;
        }
        let current = null;
        if (this.length == 1) {
            current = this.head;
            this.head = null;
            this.tail = null;
            this.length -= 1;
            return current.data;
        } else {
            if (position == 0) {
                current = this.head;
                this.head = this.head.next;
                this.head.prev = null;
                this.length -= 1;
                return current.data;
            } else if (position == this.length - 1) {
                current = this.tail;
                this.tail = this.tail.prev;
                this.tail.next = null;
                this.length -= 1;
                return current.data;
            } else {
                const flag = Math.ceil((this.length - 1) / 2);
                if (flag > position) {
                    let index = 0;
                    current = this.head;
                    while (index < position) {
                        index += 1;
                        current = current.next;
                    }
                } else {
                    let index = this.length - 1;
                    current = this.tail;
                    while (index > position) {
                        index -= 1;
                        current = current.prev;
                    }
                }
                current.next.prev = current.prev;
                current.prev.next = current.next;
                this.length -= 1;
                return current.data;
            }
        }
    }
    remove(element) {
        const index = this.indexOf(element);
        return this.removeAt(index);
    }
    isEmpty() {
        return this.length === 0;
    }
    size() {
        return this.length;
    }
    toString() {
        let current = this.head;
        let result = '';
        while (current) {
            result += current.data + ' ';
            current = current.next;
        }
        return result;
    }
    forwardString() {
        return this.toString()
    }
    backwordString() {
        let current = this.tail;
        let result = '';
        while (current) {
            result += current.data + ' ';
            current = current.prev;
        }
        return result;
    }
    getHeadNode() {
        return this.head;
    }
    getTailNode() {
        return this.tail;
    }
}


代码测试

const doublyNodeList = new DoublyNodeList();
doublyNodeList.append('111');
doublyNodeList.append('222');
doublyNodeList.append('333');
console.log(doublyNodeList.toString()); //111 222 333 
doublyNodeList.insert(0, '444');
doublyNodeList.insert(2, '555');
console.log(doublyNodeList.toString()); // 444 111 555 222 333
console.log(doublyNodeList.getData(1)); // 111

console.log(doublyNodeList.indexOf('444')); // 0

doublyNodeList.removeAt(0);
doublyNodeList.removeAt(1);
console.log(doublyNodeList.toString()); //111 222 333

doublyNodeList.update(0, '666');
console.log(doublyNodeList.toString()); // 666 222 333

console.log(doublyNodeList.forwardString()); // 666 222 333
console.log(doublyNodeList.backwordString()); // 333 222 666
console.log(doublyNodeList.getHeadNode().data); // 666
console.log(doublyNodeList.getTailNode().data); // 333

doublyNodeList.toString()); // 666 222 333

console.log(doublyNodeList.forwardString()); // 666 222 333
console.log(doublyNodeList.backwordString()); // 333 222 666
console.log(doublyNodeList.getHeadNode().data); // 666
console.log(doublyNodeList.getTailNode().data); // 333




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值