JavaScript数据结构——链表(2)

144 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第17天,点击查看活动详情

前言

上期我们实现介绍了何为链表,并创建了一个链表类。本篇文章我们就继续完善我们的链表类。首先先来回顾一下,链表中所包含的方法。

链表中的方法

  • push(data) 向链表尾部添加一个新元素
  • pushAnyWhere(data,index) 向链表的特定位置添加一个新元素
  • getData(index) 返回链表特定位置的元素。不存在返回undefined
  • remove(data) 从链表中移除一个元素
  • indexOf(data) 返回数据在链表中的索引,不存在返回-1
  • removeAnyWhere(index) 从链表特定位置移除一个元素
  • isNull() 链表是否为空
  • size() 链表中的元素个数

编码实现

push

push(data){
    // 创建节点
    const node = new Node(data)
    if(this.head === null){
        this.head = node
    }else{
        // 定义一个指针,来帮助我们指向最后一个节点
        let current = this.head
        while(current.next){
            current = current.next
        }
        // 尾部添加
        current.next = node
    }
    // 数量+1
    this.count++
}

pushAnyWhere

pushAnyWhere(data,index){
    // 两种情况,头节点插入,身体或尾部插入
    if(index >= 0 && index <= this.count){
        // 不能过界。
        const node = new Node(data)
        if(index === 0){
            // 第一种情况——头插入
            const current = this.head
            node.next = current
            this.head = node
        }else{
            // 第二种情况
            // 获取前一个节点
            const prev = this.getData(index - 1)
            // 获取当前index位置的节点
            const current = prev.next
            node.next = current
            prev.next = node
        }
        this.count++
    }else{
        console.log(`index输入不合法,请输入0-${this.count}之间的值`)
    }
}

getData()

getData(index){
    if(index >= 0 && index <= this.count){
        let current = this.head
        for(let i = 0;i < index && current !== null;i++){
            current = current.next
        }
        return current
    }
    return undefined
}

remove()

remove(data){
    return this.removeAnyWhere(this.indexOf(data))
}

removeAnyWhere()

removeAnyWhere(index){
    // 两种情况,第一项,非第一项
    if(index >= 0 && index < this.count){
        let current = this.head
        if(index === 0){
            this.head = current.next
        }else{
            const prev = this.getData(index - 1)
            current = prev.next
            prev.next = current.next
        }
        this.count--
        return current.data
    }
    return undefined
}

indexOf()

indexOf(data){
    let current = this.head
    for(let i = 0;i < this.count && current !== null;i++){
        if(this.isEqual(data,current.data)){
            return i
        }
        current = current.next
    }
    return -1
}

isNull()

isNull(){
    return this.count === 0
}

size()

size(){
    return this.count
}

为了方便观察链表,我们重写一下toString方法

toString()

toString(){
    if(this.head === null) {
        return ''
    }
    let resultData = `${this.head.data}`
    let current = this.head.next
    for(let i = 1;i < this.count && current !== null;i++){
        resultData = `${resultData},${current.data}`
        current = current.next
    }
    return resultData
}

完整代码如下:

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

class LinkedList {
    constructor(){
        // 链表大小
        this.count = 0
        // 头节点
        this.head = null
        // 比较函数
        this.isEqual = function(a,b){
            return a === b
        }
    }
    push(data){
        // 创建节点
        const node = new Node(data)
        if(this.head === null){
            this.head = node
        }else{
            // 定义一个指针,来帮助我们指向最后一个节点
            let current = this.head
            while(current.next){
                current = current.next
            }
            // 尾部添加
            current.next = node
        }
        // 数量+1
        this.count++
    }
    pushAnyWhere(data,index){
        // 两种情况,头节点插入,身体或尾部插入
        if(index >= 0 && index <= this.count){
            // 不能过界。
            const node = new Node(data)
            if(index === 0){
                // 第一种情况——头插入
                const current = this.head
                node.next = current
                this.head = node
            }else{
                // 第二种情况
                // 获取前一个节点
                const prev = this.getData(index - 1)
                // 获取当前index位置的节点
                const current = prev.next
                node.next = current
                prev.next = node
            }
            this.count++
        }else{
            console.log(`index输入不合法,请输入0-${this.count}之间的值`)
        }
    }
    getData(index){
        if(index >= 0 && index <= this.count){
            let current = this.head
            for(let i = 0;i < index && current !== null;i++){
                current = current.next
            }
            return current
        }
        return undefined
    }
    remove(data){
        return this.removeAnyWhere(this.indexOf(data))
    }
    removeAnyWhere(index){
        // 两种情况,第一项,非第一项
        if(index >= 0 && index < this.count){
            let current = this.head
            if(index === 0){
                this.head = current.next
            }else{
                const prev = this.getData(index - 1)
                current = prev.next
                prev.next = current.next
            }
            this.count--
            return current.data
        }
        return undefined
    }
    indexOf(data){
        let current = this.head
        for(let i = 0;i < this.count && current !== null;i++){
            if(this.isEqual(data,current.data)){
                return i
            }
            current = current.next
        }
        return -1
    }
    isNull(){
        return this.count === 0
    }
    size(){
        return this.count
    }
    toString(){
        if(this.head === null) {
            return ''
        }
        let resultData = `${this.head.data}`
        let current = this.head.next
        for(let i = 1;i < this.count && current !== null;i++){
            resultData = `${resultData},${current.data}`
            current = current.next
        }
        return resultData
    }
}
const linkedList = new LinkedList()

console.log(linkedList.isNull());// true
linkedList.push(0)
linkedList.push(1)
linkedList.push(2)
linkedList.pushAnyWhere(3,3)
linkedList.pushAnyWhere(6,0)
linkedList.pushAnyWhere(4,4)
linkedList.pushAnyWhere(5,2)
console.log(linkedList.toString());// 6,0,5,1,2,4,3
console.log(linkedList.getData(3));// Node节点
linkedList.remove(5)
linkedList.removeAnyWhere(4)
console.log(linkedList.toString());// 6,0,1,2,3
console.log(linkedList.isNull());// false
console.log(linkedList.size());// 5
console.log(linkedList.indexOf(3));// 4
console.log(linkedList.indexOf(5));// -1

总结

本次我们实现了链表类上面的常用方法。但是这只是一个基本的链表结构,还有双向链表,循环链表,有序链表等特殊链表,万变不离其宗,只要基础链表学会了,特殊链表只是在此基础上做了一些属于自己的修改,下次我们实现双向链表。