JavaScript 实现双向链表的操作

Posted YuLong~W

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript 实现双向链表的操作相关的知识,希望对你有一定的参考价值。

文章目录


参考之前所写文章: JavaScript 实现单向链表的操作

JavaScript实现双向链表 :使用ES6面向对象语法

双向链表: 每个结点都有一个指向其前一个结点的指针域(prev)和一个指向其下一个结点的指针域(next)

与单链表区别

单链表是单向的,有一个头结点,一个尾结点,要访问任何结点,都必须知道头结点,不能逆着进行

双向链表基于单链表。双链表添加了一个指针域,通过两个指针域,分别指向结点的前结点和后结点。可以通过双链表的任何结点,访问到它的前结点和后结点

在这里插入图片描述

链表的设计:
一个是 Node 类用来表示结点,另一个是 DoubleLinked 类提供插入结点、删除结点、遍历结点等一些操作

在链表中间的某个结点前插入:

给定p结点,要求在p结点前插入s结点
在这里插入图片描述

注意四步操作的顺序:

  • ① s.prev=p.prev
  • ② p.prev.next=s(也可写作s.prev.next=s 前提是先执行①,否则不可)
  • ③ s.next=p
  • ④ p.prev=s

注意: 以上四步顺序中,④一定要放在①后,因为一旦添加④,p结点的pre已经确定指向s结点,如果没有①,则p结点的前一个结点将会丢失,无法找到,而其余顺序随意排放

建议按照以上①②③④顺序进行排列,思路很清晰脑子不会乱

在链表中删除某个结点:

删除给定的p结点
在这里插入图片描述
顺序:

  • ① p.prev.next=p.next
  • ② p.next.prev=p.prev

注意: ① ②顺序无所谓,谁先谁后都可

双链表代码:

//定义一个节点类
class Node {
    constructor(data) {
        this.data = data
        this.next = null
        this.previous = null
    }
}

//双向链表类
class DoubleLinked {
    constructor() {
        this.size = 0
        this.head = new Node('head')
        this.currentNode = ''  //当前节点指针
    }

    //获取链表长度
    getLength() {
        return this.size
    }

    //判断链表是否为空
    isEmpty() {
        return this.size === 0
    }

    //显示当前节点
    showNode() {
        console.log(this.currentNode.data)
    }

    //遍历
    displayList() {
        let str = ''
        let currentNode = this.head //打印结果带head值
        // var currentNode=this.head.next  打印结果不带head值
        while (currentNode) {
            str += currentNode.data
            currentNode = currentNode.next
            if (currentNode) {
                str += '-->'
            }
        }
        console.log(str)
    }

    //倒序遍历链表
    lastDisplay() {
        let str = ''
        let currentNode = this.findLast()
        while (currentNode) {
            str += currentNode.data
            currentNode = currentNode.previous
            if (currentNode) {
                str += '-->'
            }
        }
        console.log(str)
    }

    //查找某一个元素
    findNode(data) {
        let currentNode = this.head
        while (currentNode && (currentNode.data != data)) {
            currentNode = currentNode.next
        }
        return currentNode
    }

    //头插法 在headh结点后添加结点(与insertNextNode()方法类似)
    headAppend(data) {
        let newNode = new Node(data)
        newNode.next = this.head.next
        this.head.next.previous = newNode
        newNode.previous = this.head
        this.head.next = newNode
        this.size++
    }
    //获取最后一个节点
    findLast() {
        let currentNode = this.head
        while (currentNode.next) {
            currentNode = currentNode.next
        }
        return currentNode
    }

    //尾插法 在尾部添加节点
    append(data) {
        let currentNode = this.findLast()
        let newNode = new Node(data)
        currentNode.next = newNode
        newNode.next = null
        newNode.previous = currentNode
        this.size++
    }

    //插入节点   表示将element值插入到data值之后
    insertNextNode(data, element) {
        let currentNode = this.findNode(data)
        //如果data不存在
        if (!currentNode) {
            return
        }
        let newNode = new Node(element)

        newNode.next = currentNode.next
        currentNode.next.previous = newNode
        // newNode.next.previous=newNode
        newNode.previous = currentNode
        currentNode.next = newNode
        this.size++
    }

    //插入节点   表示将element值插入到data值之前
    insertPreNode(data, element) {
        let currentNode = this.findNode(data)
        if (!currentNode) {
            return
        }
        let newNode = new Node(element)

        newNode.previous = currentNode.previous
        currentNode.previous.next = newNode
        // newNode.previous.next=newNode
        newNode.next = currentNode
        currentNode.previous = newNode
        this.size++
    }



    //删除一个节点
    deleteNode(data) {
        let currentNode = this.findNode(data)
        if (currentNode.next == null) //如果删除的节点是最后一个节点
        {
            currentNode.previous.next = null
        }
        else {
            currentNode.previous.next = currentNode.next
            currentNode.next.previous = currentNode.previous

        }
        this.size--
    }
}

代码检测:

//创建一个空链表
let doubleList = new DoubleLinked()
//判断是否为空
console.log(doubleList.isEmpty())
//尾插法依次插入数组序列
let arr = [1, 3, 5]
for (let i = 0; i < arr.length; i++) {
    doubleList.append(arr[i])
}
//遍历双向链表
doubleList.displayList()
//指定结点后插入新结点
doubleList.insertNextNode(3, 4)
//指定结点前插入结点
doubleList.insertPreNode(3, 2)
doubleList.displayList()
//删除指定结点
doubleList.deleteNode(5)
doubleList.displayList()
//前插法 在头元素后插入结点
doubleList.headAppend(20)
doubleList.headAppend(100)
doubleList.displayList()
//倒序遍历
doubleList.lastDisplay()

在这里插入图片描述

以上是关于JavaScript 实现双向链表的操作的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 实现链表的操作

链表的java实现(单向双向链表,单向链表的反转)

链表的java实现(单向双向链表,单向链表的反转)

双向链表的基础操作(C++实现)

双向链表的原理与实现

不会C和cpp也能学数据结构——JavaScript实现双向链表