JavaScript链表的实现

链表

链表概念

链表:数据的一种存储结构,一个链表包含若干个结点,每个结点至少包含一个数据域和一个指针域,指针域指向下一个结点。
结点:数据元素的存储映像,由存放数据元素的数据域和存放后继结点地址的指针域组成。
特点:用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意味着,这些数据元素可以存在内存未被占用的任意位置。

头结点、头指针、首元结点的区别
区别

  • 头结点: 在单链表第一个元素结点之前设置的一个结点, 数据域可以不存任何信息,指针域指向单链表第一个元素的结点。头结点不是链表的必要元素
  • 头指针: 指向单链表的第一个结点的指针, 如果单链表有头结点,则头指针指向头结点,如果单链表没有头结点,则头指针指向第一个首元结点。头指针不能为空,头指针是链表的必要元素。
  • 首元结点:单链表中第一个有数据元素的结点。如果单链表有头结点,则首元结点为头结点的下一个结点,如果单链表没有头结点,则首元结点就是单链表的第一个结点

链表的基础操作

  • 获取链表长度
  • 判断链表是否为空
  • 遍历链表
  • 查找元素
  • 添加元素
  • 删除元素

单链表的实现

//定义节点类
class Node
{
    constructor(data)
    {
        this.data = data    //节点的数据域(数据成员)
        this.next = null    //节点的指针域(指针成员)
    }
}

//定义单向链表类
class SingleLinked
{
    constructor()
    {
        this.size = 0  //记录链表中的节点个数
        this.head = new Node('head')   //是链表的头指针,记录链表的起始地址
        this.currentNode = ''   //用来记录当前节点
    }

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

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

    //遍历链表:不重复访问链表中的每个节点
    displayList()
    {
        var list = ''
        var currentNode = this.head  //指向链表的头指针
        while(currentNode)  //若当前节点不为空 
        {
            list += currentNode.data
            currentNode = currentNode.next  //让指针指向当前节点的下一个节点
            if(currentNode)
            {
                list += '->'
            }
        }
        console.log(list)
    }

    //获取链表的最后一个节点
    findLast()
    {
        var currNode = this.head
        while(currNode.next)
        {
            currNode = currNode.next
        }
        return currNode
    }

    //在单链表的尾部添加元素
    appendNode(element)
    {
        var currNode = this.findLast()   //找到链表的最后一个节点
        var newNode = new Node(element)  //创建一个新的节点
        currNode.next = newNode
        newNode.next = null
        this.size++    //链表长度+1
    }

    //删除一个节点
    delete(element)
    {
        var currNode = this.head
        while(currNode.next.data!=element)
        {
            currNode = currNode.next
        }
        currNode.next = currNode.next.next
        this.size--
    }
}
  • 注意:在单链表中间插入元素时注意连接结点的顺序

双向链表的实现

//定义一个节点类
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.currentCode = ''  //当前节点指针
    }

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

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

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

    //遍历
    displayList()
    {
        var str = ''
        var currentNode = this.head
        while(currentNode)
        {
            str += currentNode.data
            currentNode = currentNode.next
            if(currentNode) 
            {
                str += '-->'
            }
        }
        return str
    }

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

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

    //在data后插入节点
    insertNode(data,element)
    {
        var currentNode = this.findNode(data)
        //如果data不存在
        if(!currentNode)
        {
            return
        }
        var newNode = new Node(element)
        newNode.previous = currentNode
        newNode.next = currentNode.next
        currentNode.next.previous = newNode
        currentNode.next = newNode
        this.size++
    }

    //获取最后一个节点
    findLast()
    {
        var currentNode = this.head
        while(currentNode.next)
        {
            currentNode = currentNode.next
        }
        return currentNode
    }

    //尾部添加节点
    appendNode(data)
    {
        var currentNode = this.findLast()
        var newNode = new Node(data)
        currentNode.next = newNode
        newNode.next = null
        newNode.previous = currentNode
        this.size++
    }

    //删除一个节点
    deleteNode(data)
    {
        var 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--
    }
}
  • 注意:单链表插入操作时连接结点的顺序
  • 先连接新结点的前驱和后继,再连接后结点的前驱,最后连接前结点的后继
newNode.previous = currentNode
newNode.next = currentNode.next
currentNode.next.previous = newNode
currentNode.next = newNode
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 17
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值