链表(单向双向)

 //链表是一个此案型结构,同时也是一个天然的递归结构。链表结构可以充分利用计算机内存空间,

        //实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了节点的指针域,

        //空间开销比较大

        //链表是一个线性结构,也是一个天然的递归结构,可以充分利用计算机内存空间,实现灵活的

        //内存动态管理,但是失去了数组可以随机读取的优点,同时增加了节点的指针域,空间开销较大

        //单向链表

        class Node {

            constructor(v, next) {

                this.value = v

                this.next = next

            }

        }

        class LinkList {

            constructor() {

                //链表长度

                this.size = 0

                //虚拟头部

                this.dummyNode = new Node(null, null)

            }

            find(header, index, currentIndex) {

                if (index === currentIndex) {

                    return header

                }

                return this.find(header.next, index, currentIndex + 1)

            }

            addNode(v, index) {

                this.checkIndex(index)

                //当往链表末尾插入时,prev.next为空,其他情况时,因为要插入节点,所以

                //插入的节点的next应该是prev.next,然后设置prev.next 为插入的节点

                let prev = this.find(this.dummyNode, index, 0)

                prev.next = new Node(v, prev.next)

                this.size++

                return prev.next

            }

            insertNode(v, index) {

                return this.addNode(v, index)

            }

            addToFirst(v) {

                return this.addNode(v, 0)

            }

            addToLast(v) {

                return this.addNode(v, this.size)

            }

            removeNode(index, isLast) {

                this.checkIndex(index)

                index = isLast ? index - 1 : index

                let prev = this.find(this.dummyNode, index, 0)

                let node = prev.next

                prev.next = node.next

                node.next = null

                this.size--

                return node

            }

            removeFirstNode() {

                return this.removeNode(0)

            }

            removeLastNode() {

                return this.removeNode(this.size, true)

            }

            checkIndex(index) {

                if (index < 0 || index > this.size) {

                    throw Error('index Error')

                }

            }

            getNode(index) {

                this.checkIndex(index)

                if (this.isEmpty()) return

                return

            }

            isEmpty() {

                return this.size === 0

            }

            getSize() {

                return this.size

            }

        }

        var list = new LinkList()

        list.addToFirst(100)

        console.log(list)

        //双向链表

        // 双向链表的节点类(继承单向链表的节点类)

        class DoublyNode extends Node {

            constructor(element) {

                super(element);

                this.prev = null;

            }

        }

        // 双向链表类继承单向链表类

        class DoublyLinkedList extends LinkedList {

            constructor() {

                super();

                this.tail = null;

            }

        }

        // append(element) 往双向链表尾部追加一个新的元素

        // 重写 append()

        function append(element) {

           

            // 1、创建双向链表节点

            const newNode = new DoublyNode(element);

            // 2、追加元素

            if (this.head === null) {

                this.head = newNode;

                this.tail = newNode;

            } else {

                // !!跟单向链表不同,不用通过循环找到最后一个节点

                // 巧妙之处

                this.tail.next = newNode;

                newNode.prev = this.tail;

                this.tail = newNode;

            }

            this.length++;

        }

        // insert(position, data) 插入元素

        // 重写 insert()

        function insert(position, element) {

            // 1、position 越界判断

            if (position < 0 || position > this.length) return false;

            // 2、创建新的双向链表节点

            const newNode = new DoublyNode(element);

            // 3、判断多种插入情况

            if (position === 0) { // 在第 0 个位置插入

                if (this.head === null) {

                    this.head = newNode;

                    this.tail = newNode;

                } else {

                    //== 巧妙之处:相处腾出 this.head 空间,留个 newNode 来赋值 ==//

                    newNode.next = this.head;

                    this.head.perv = newNode;

                    this.head = newNode;

                }

            } else if (position === this.length) { // 在最后一个位置插入

                this.tail.next = newNode;

                newNode.prev = this.tail;

                this.tail = newNode;

            } else { // 在 0 ~ this.length 位置中间插入

                let targetIndex = 0;

                let currentNode = this.head;

                let previousNode = null;

                // 找到要插入位置的节点

                while (targetIndex++ < position) {

                    previousNode = currentNode;

                    currentNode = currentNode.next;

                }

                // 交换节点信息

                previousNode.next = newNode;

                newNode.prev = previousNode;

                newNode.next = currentNode;

                currentNode.prev = newNode;

            }

            this.length++;

            return true;

        }

        // removeAt() 删除指定位置的节点

        // 重写 removeAt()

        function removeAt(position) {

            // 1、position 越界判断

            if (position < 0 || position > this.length - 1) return null;

            // 2、根据不同情况删除元素

            let currentNode = this.head;

            if (position === 0) { // 删除第一个节点的情况

                if (this.length === 1) { // 链表内只有一个节点的情况

                    this.head = null;

                    this.tail = null;

                } else { // 链表内有多个节点的情况

                    this.head = this.head.next;

                    this.head.prev = null;

                }

            } else if (position === this.length - 1) { // 删除最后一个节点的情况

                currentNode = this.tail;

                this.tail.prev.next = null;

                this.tail = this.tail.prev;

            } else { // 删除 0 ~ this.length - 1 里面节点的情况

                let targetIndex = 0;

                let previousNode = null;

                while (targetIndex++ < position) {

                    previousNode = currentNode;

                    currentNode = currentNode.next;

                }

                previousNode.next = currentNode.next;

                currentNode.next.perv = previousNode;

            }

            this.length--;

            return currentNode.data;

        }

        // update(position, data) 修改指定位置的节点

        // 重写 update()

        function update(position, data) {

            // 1、删除 position 位置的节点

            const result = this.removeAt(position);

            // 2、在 position 位置插入元素

            this.insert(position, data);

            return result;

        }

        forwardToString()

        // forwardToString() 链表数据从前往后以字符串形式返回

        function forwardToString() {

            let currentNode = this.head;

            let result = '';

            // 遍历所有的节点,拼接为字符串,直到节点为 null

            while (currentNode) {

                result += currentNode.data + '--';

                currentNode = currentNode.next;

            }

            return result;

        }

        // backwardString() 链表数据从后往前以字符串形式返回

        function backwardString() {

            let currentNode = this.tail;

            let result = '';

            // 遍历所有的节点,拼接为字符串,直到节点为 null

            while (currentNode) {

                result += currentNode.data + '--';

                currentNode = currentNode.prev;

            }

            return result;

        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值