JS数据结构之列表

140 阅读2分钟
原文链接: zhuanlan.zhihu.com
列表
/*
 * 列表是一组有序的序列。
 * 列表的抽象数据类型(ADT): 描述列表具有什么特征, 动作。
 * 使用迭代器访问列表而不是数组索引: 当你删除或者插入元素, 你需要去更新索引。而迭代器方式不需要。
 *
 * pos属性: 当前元素所在位置
 * length属性: 返回列表中元素个数
 * append(): 列表尾部添加元素
 * insert(): 列表某个元素后插入元素
 * remove(): 在列表中删除元素
 * clear(): 清空列表所有元素
 * toString(): 查看列表所有元素
 * getElement(): 获取当前元素
 * currPos(): 获取当前元素位置
 * next(): 从当前元素移到下一个元素
 * prev(): 从当前元素移到上一个元素
 * front(): 将列表的当前位置移到第一个
 * end(): 将列表的当前位置移到最后
 * moveTo(n): 直接移到具体某个位置
 * contains(ele): 判断值是否在列表中
 * getListSize(): 获取列表元素长度
*/

class List {

    constructor () {
        this.dataStore = []
        this.length = 0
        this.pos = 0
    }

    /*
     * @desc: 私有方法, 搜索目标元素在列表的索引
    */
    _find (target) {
        for (let i = 0; i < this.dataStore.length; i++) {
            if (this.dataStore[i] === target) {
                return i
            }
        }
        return -1
    }

    append (element) {
        // 同时更新了length
        this.dataStore[this.length++] = element
    }

    insert (element, afterEle) {
        const insertIndex = this._find(afterEle)
        if (insertIndex > -1) {
            this.dataStore.splice(insertIndex + 1, 0, element)
            ++this.length
            return true
        }
        return false
    }

    remove (element) {
        const eleIndex = this._find(element)
        if (eleIndex > -1) {
            this.dataStore.splice(eleIndex, 1)
            --this.length
            return true
        }
        return false
    }

    clear () {
        delete this.dataStore
        this.dataStore = []
        this.length = this.pos = 0
    }

    toString () {
        return this.dataStore
    }

    getElement () {
        return this.pos <= this.length - 1 ? this.dataStore[this.pos] : this.dataStore[this.length - 1]
    }

    currPos () {
        return this.pos
    }

    next () {
        if (this.pos <= this.length - 1) {
            ++this.pos
        }
    }

    prev () {
        if (this.pos > 0) {
            --this.pos
        }
    }

    front () {
        this.pos = 0
    }

    end () {
        this.pos = this.length - 1
    }

    moveTo (pos) {
        this.pos = pos
    }

    contains (element) {
        const index = this._find(element)
        return index > -1 ? true : false
    }

    getListSize () {
        return this.length
    }

}

module.exports = List


demo实践

需求: 使用列表存储数据。

// demo.txt
(1) The Shawshank Redemption(《肖申克的救赎》)
(2) The Godfather(《教父》)
(3) The Godfather: Part II(《教父 2》)
(4) Pulp Fiction(《低俗小说》)
(5) The Good, the Bad and the Ugly(《黄金三镖客》)
(6) 12 Angry Men(《十二怒汉》)
(7) Schindler’s List(《辛德勒名单》)
(8) The Dark Knight(《黑暗骑士》)
(9) The Lord of the Rings: The Return of the King(《指环王:王者归来》)
(10) Fight Club(《搏击俱乐部》)
(11) Star Wars: Episode V - The Empire Strikes Back(《星球大战 5:帝国反击战》)
(12) One Flew Over the Cuckoo’s Nest(《飞越疯人院》)
(13) The Lord of the Rings: The Fellowship of the Ring(《指环王:护戒使者》)
(14) Inception(《盗梦空间》)
(15) Goodfellas(《好家伙》)
(16) Star Wars(《星球大战》)
(17) Seven Samurai(《七武士》)
(18) The Matrix(《黑客帝国》)
(19) Forrest Gump(《阿甘正传》)
(20) City of God(《上帝之城》)


// readFile.js

const fs = require('fs')
const List = require('./List.js')

function readFile (path) {
    return new Promise((resolve, reject) => {
        fs.readFile(path, (err, data) => {
            if (err) {
                reject(err)
            }
            resolve(data.toString().split('\n').filter(item => item !== ''))
        })
    })
}



async function createList () {
    const dataOfArray = await readFile('./demo.text')
    const list = new List()
    if (Array.isArray(dataOfArray) && dataOfArray.length > 0) {
        for (let i = 0; i < dataOfArray.length; i++) {
            list.append(dataOfArray[i])
        }
    }
    return list
}

createList().then(res => {
    list = res
    // 判断是否含有某个电影
    console.log(list.contains('(20) City of God(《上帝之城》)')) // true
    // 遍历
    while (list.currPos() < list.getListSize()) {
        console.log(list.getElement())
        list.next()
    }
}).catch(err => {
    console.log(err)
})