JavaScript 数据结构-双向链表

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style></style>
</head>

<body>

    <script>
        // 封装双向链表类
        function DoublyLinkedList() {
            // 内部类:用来创建链表节点
            function Node(data) {
                this.data = data
                this.prev = null //上指针 指向上一个节点
                this.next = null //下指针 指向下一个节点
            }

            // 定义属性
            this.length = 0
            this.head = null //头结点
            this.tail = null //尾结点

            // 定义相关方法
            // 1.在尾部追加数据
            DoublyLinkedList.prototype.append = function (data) {
                // 1.创建新的节点
                var newNode = new Node(data)

                // 2.判断是否为空链表
                if (this.head == null) {
                    this.head = newNode
                    this.tail = newNode
                } else {
                    this.tail.next = newNode
                    newNode.prev = this.tail
                    this.tail = newNode
                }

                // 3.length+1
                this.length += 1
            }

            // 2.转为字符串的方法 方便我们调试alert输出 否则会显示undefined
            // 2.1从前往后转为字符串
            DoublyLinkedList.prototype.forwardString = function () {
                var current = this.head
                var forwardStr = ""

                while (current) {
                    forwardStr += "," + current.data
                    current = current.next
                }

                return forwardStr.slice(1)
            }

            // 2.2反向遍历的方法 从后往前
            DoublyLinkedList.prototype.reverseString = function () {
                var current = this.tail
                var reverseStr = ""

                while (current) {
                    reverseStr += "," + current.data
                    current = current.prev
                }

                return reverseStr.slice(1)
            }

            // 2.3实现toString方法
            DoublyLinkedList.prototype.toString = function () {
                return this.forwardString()
            }

            // 3.根据索引插入元素的方法
            DoublyLinkedList.prototype.insert = function (position, data) {
                // 1.判断是否越界
                if (position < 0 || position > this.length) {
                    return false
                }

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

                // 3.判断原来的链表是否为空链表
                if (this.length == 0) {
                    this.head = newNode //头指针指向新的节点
                    this.tail = newNode //尾指针指向新的节点
                } else {
                    if (position == 0) { //3.1判断插入位置是否为第一个
                        this.head.prev = newNode //原来头节点的上一个节点为新节点
                        newNode.next = this.head //新节点的下一个节点为原来的头结点
                        this.head = newNode      //头结点为新的节点
                    } else if (position == this.length) { //3.2判断插入位置是否为最后一个
                        newNode.prev = this.tail  //新节点的上节点为之前的尾结点
                        this.tail.next = newNode  //之前尾结点的下节点为新节点
                        this.tail = newNode       //新节点成为尾结点
                    } else {                      //3.3插入位置在中间
                        var current = this.head
                        var index = 0

                        while (index++ < position) {
                            current = current.next
                        }
                        //当循环终止时就找到了目标节点位置(position索引处的节点)
                        newNode.next = current       //新节点的下节点为目标节点
                        newNode.prev = current.prev  //新节点的上节点为目标节点的上节点
                        current.prev.next = newNode  //目标节点的上节点的下节点为新节点
                        current.prev = newNode       //目标节点的上节点为新节点
                    }
                }
                // 4.长度+1
                this.length += 1
            }

            // 4.根据索引获取元素的方法
            DoublyLinkedList.prototype.get = function (position) {
                // 1.判断是否越界
                if (position < 0 || position >= this.length) {
                    return null
                }
                if (this.length / 2 >= position) { //2.从前往后查找
                    var current = this.head
                    var index = 0
                    while (index++ < position) {
                        current = current.next
                    }
                    // 循环结束时已找到目标索引
                    return current.data
                } else {                      //3.从后往前查找
                    var current = this.tail
                    var index = this.length - 1
                    while (index-- > position) {
                        current = current.prev
                    }
                    // 循环结束时已找到目标索引
                    return current.data
                }
            }

            // 5.根据元素返回索引的方法
            DoublyLinkedList.prototype.indexOf = function (data) {
                // 1.定义变量
                var current = this.head
                var index = 0

                // 2.循环查找和data相同的节点
                while (current) {
                    if (current.data == data) {
                        return index
                    }
                    current = current.next
                    index += 1
                }
                return -1 //循环结束说明没有找到和data相同的节点 返回-1
            }

            // 6.根据索引修改元素的方法
            DoublyLinkedList.prototype.update = function (position, newData) {
                // 1.判断是否越界
                if (position < 0 || position >= this.length) return false

                if (this.length / 2 >= position) { //2.从前往后查找
                    var current = this.head
                    var index = 0
                    while (index++ < position) {
                        current = current.next
                    }
                    // 循环结束时已找到目标索引
                    current.data = newData
                } else {                            //3.从后往前查找
                    var current = this.tail
                    var index = this.length - 1
                    while (index-- > position) {
                        current = current.prev
                    }
                    // 循环结束时已找到目标索引
                    current.data = newData
                }
            }

            // 7.根据索引删除元素的方法
            DoublyLinkedList.prototype.removeAt = function (position) {
                // 1.判断是否越界
                if (position < 0 || position >= this.length) return null

                // 2.判断是否只有一个节点
                var current = this.head
                if (this.length == 1) {
                    this.head = null
                    this.tail = null
                } else {
                    if (position == 0) { //判断是否删除第一个节点
                        this.head.next.prev = null //头结点的下节点的上节点为null(删除第一个节点)
                        this.head = this.head.next //头结点为原来头结点的下节点
                    } else if (position == this.length - 1) { //最后节点
                        current = this.tail
                        this.tail.prev.next = null //删除最后节点
                        this.tail = this.tail.prev //尾结点为原来尾结点的上节点
                    } else { //中间删除
                        var index = 0
                        while (index++ < position) {
                            current = current.next
                        }
                        // 循环结束找到目标元素
                        current.prev.next = current.next  //目标节点的上节点 的下节点 为目标节点的下节点
                        current.next.prev = current.prev  //目标节点的下节点 的上节点 为目标节点的上节点
                    }
                }
                // 3.长度-1
                this.length -= 1
                return current.data
            }

            // 8.根据元素删除元素的方法
            DoublyLinkedList.prototype.remove = function (data) {
                // 1.根据data获取索引值
                var index = this.indexOf(data)

                // 2.根据index删除对应的节点
                return this.removeAt(index)
            }

            // 9.判断链表是否为空
            DoublyLinkedList.prototype.isEmpty = function () {
                return this.length == 0
            }

            // 10获取链表长度
            DoublyLinkedList.prototype.size=function (){
                return this.length
            }

            // 11.获取链表的第一个元素
            DoublyLinkedList.prototype.getHead=function (){
                return this.head.data
            }

            // 12.获取链表的最后一个元素
            DoublyLinkedList.prototype.getTail=function(){
                return this.tail.data
            }
        }

        // 方法测试
        var list = new DoublyLinkedList()

        // 1.测试末尾追加方法
        list.append(10)
        list.append(20)
        list.append(30)
        alert(list)

        // 2.测试转字符串的方法
        // alert(list.forwardString())
        // alert(list.reverseString())

        // 3.测试根据索引插入元素的方法
        // list.insert(0, 00)
        // list.insert(1, 11)
        // list.insert(2, 22)
        // alert(list)

        // 4.测试获取目标索引的元素
        // alert(list.get(0))
        // alert(list.get(4))

        // 5.测试根据元素获取索引的方法
        // alert(list.indexOf(10))
        // alert(list.indexOf(30))

        // 6.测试根据索引修改元素的方法
        // list.update(0,'000')
        // list.update(1,'111')
        // list.update(2,'222')
        // alert(list)

        // 7.测试根据索引删除元素的方法
        // list.removeAt(0)
        // list.removeAt(0)
        // alert(list)

        // 8.测试根据元素删除元素的方法
        // list.remove('10')
        // list.remove('20')
        // alert(list)

        // 9.测试链表是否为空的方法
        // alert(list.isEmpty())

        // 10.测试获取链表长度的方法
        // alert(list.size())

        // 11.测试获取链表第一个元素的方法
        // alert(list.getHead())

        // 12.测试获取链表最后一个元素的方法
        // alert(list.getTail())

    </script>
</body>

</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值