数据结构与算法-列表(List)

3,132 阅读5分钟

百度百科解释:
以表格为容器,装载着文字或图表的一种形式,叫列表。
<数据结构术语>数据结构中的列表一般指线性列表的简称
列表是一种数据项构成的有限序列,即按照一定的线性顺序,排列而成的数据项的集合,在这种数据结构上进行的基本操作包括对元素的的查找,插入,和删除

日常生活中人们使用的列表:行程安排列表、待办事项列表、榜单列表等。

javascript中没有原生定义的列表,但我们可以根据列表思想,创建列表类,抽象列表的数据类型,实现列表功能。

列表的抽象数据类型定义

定义 说明
listSize(属性) 列表的元素个数
pos(属性) 列表的当前位置
dataStore(属性) 空数组保存列表元素
append(方法) 在列表的末尾添加新元素
find(方法) 在列表中查找某一个元素
remove(方法) 从列表中删除元素
length(方法) 返回列表中有多少元素
toString(方法) 返回列表中的字符串形式
insert(方法) 在现有元素后插入新元素
clear(方法) 清空列表中的所有元素
contains(方法) 判断给定值是否在列表中
getElement(方法) 返回当前位置的元素
front(方法) 将列表的当前位置移动到第一个元素
end(方法) 将列表的当前位置移动到最后一个元素
prev(方法) 将当前位置后移一位
next(方法) 将当前位置前移一位
hasNext(方法) 判断后一位
hasPrev(方法) 判断前一位
currPos(方法) 返回列表的当前位置
moveTo(方法) 将当前位置移动到指定位置

实现列表类

function List() {
    this.listSize = 0
    this.pos = 0 // 当前位置
    this.dataStore = [] // 初始化一个空数组来保存列表元素
}
List.prototype = {
    constructor: List,
    append: function () {},
    find: function () {},
    remove: function () {},
    length: function () {},
    toString: function () {},
    insert: function () {},
    clear: function () {},
    contains: function () {},
    front: function () {},
    end: function () {},
    prev: function () {},
    next: function () {},
    currPos: function () {},
    moveTo: function () {},
    getElement: function () {},
    hasNext: function () {},
    hasPrev: function () {}
}

具体方法实现

append: function (element) {
    this.dataStore[this.listSize] = element
    this.listSize++
}
// 给列表的下一个位置增加一个新的元素,该位置正好等于listSize的值,添加好元素后,listSize加1
find: function (element) {
    for (var i = 0; i < this.dataStore.length; i++) {
        if (this.dataStore[i] === element) {
            retrun i
        }
    }
    return -1
}
// 在列表中查找某一元素,如果找到返回该位置,否则返回-1
remove: function (element) {
    var foundAt = thsi.find(element)
    if (foundAt > -1) {
        this.dataStore.splice(foundAt, 1)
        this.listSize--
        return true
    }
    return false
}
/* remove()方法是cList类中较难实现的一个方法,
   首先,需要在列表中找到该元素,
   然后删除,并且调整底层的数组对象以填补删除该元素后留下的空白。
   但是,在js中可以使用splice()方法来简化这一过程 */
length: function () {
    return this.listSize
}
// 返回列表元素个数
toString: function () {
    return this.dataStore
}
// 返回元素数组
insert: function (element, after) {
    var insertPos = this.find(after)
    if (insertPos > -1) {
        this.dataStore.splice(insertPos + 1, element)
        this.listSize++
        return true
    }
    return false
}
// 找到传入的after参数在列表中的位置,使用splice()将新元素插入该位置之后,然后长度+1并返回true
clear: function () {
    delete this.dataStore
    this.dataStore.length = 0
    this.listSize = this.pos = 0
}
// 置空
contains: function (element) {
    for (var i = 0; i < this.dataStore.length; i++) {
        if (this.dataStore[i] === element) {
            return true
        }
    }
    return false
}
// 循环判断给定值是否在列表中
// 使用迭代器访问列表
front: function () {
    this.pos = 0
}
end: function () {
    this.pos = this.listSize - 1
}
prev: function () {
    this.pos--
}
next: function () {
    if (this.pos < this.listSize) {
        this.pos++
    }
}
currPos: function () {
    return this.pos
}
moveTo: function (positon) {
    this.pos = position
}
getElement: function () {
    return this.dataStore[this.pos]
}
hasNext: function () {
    return this.pos < this.listSize
}
hasPrev: function () {
    return this.pos >= 0
}
// 使用迭代器,可以不必关心数据的内部存储方式,以实现对列表的遍历。
// 类似指针,在列表上随意移动(严格意义上不是指针)
// 迭代器遍历列表的例子
for (names.front(); names.hasNext(); names.next()) {
    console.log(names.getElement())
}
// 在for循环的一开始,将列表的当前位置设置为第一个元素,只要currPos的值小于列表的长度,就一直循环,每一次循环都调用next()将当前位置移动一位

列表的应用

function List() {
    this.listSize = 0
    this.pos = 0 // 当前位置
    this.dataStore = [] // 初始化一个空数组来保存列表元素
}
List.prototype = {
    constructor: List,
    append: function (element) {
        this.dataStore[this.listSize] = element
        this.listSize++
    },
    find: function (element) {
        for (var i = 0; i < this.dataStore.length; i++) {
            if (this.dataStore[i] === element) {
                return i
            }
        }
        return -1
    },
    remove: function (element) {
        var foundAt = thsi.find(element)
        if (foundAt > -1) {
            this.dataStore.splice(foundAt, 1)
            this.listSize--
            return true
        }
        return false
    },
    length: function () {
        return this.listSize
    },
    toString: function () {
        return this.dataStore
    },
    insert: function (element, after) {
        var insertPos = this.find(after)
        if (insertPos > -1) {
            this.dataStore.splice(insertPos + 1, element)
            this.listSize++
            return true
        }
        return false
    },
    clear: function () {
        delete this.dataStore
        this.dataStore.length = 0
        this.listSize = this.pos = 0
    },
    contains: function (element) {
        for (var i = 0; i < this.dataStore.length; i++) {
            if (this.dataStore[i] === element) {
                return true
            }
        }
        return false
    },
    front: function () {
        this.pos = 0
    },
    end: function () {
        this.pos = this.listSize - 1
    },
    prev: function () {
        this.pos--
    },
    next: function () {
        if (this.pos < this.listSize) {
            this.pos++
        }
    },
    currPos: function () {
        return this.pos
    },
    moveTo: function (positon) {
        this.pos = position
    },
    getElement: function () {
        return this.dataStore[this.pos]
    },
    hasNext: function () {
        return this.pos < this.listSize
    },
    hasPrev: function () {
        return this.pos >= 0
    }
}
var movies = ['电影1', '电影2', '电影3', '电影4', '电影5', '电影6', '电影7', '电影8', '电影9', '电影10']
var movieList = new List() // 根据前面写的List类new出列表对象
// 列表中添加对应内容
for (var i = 0; i < movies.length; i++) {
    movieList.append(movies[i])
}
// 显示列表内容
function displayList() {
    for (movieList.front(); movieList.hasNext(); movieList.next()) {
        console.log(movieList.getElement())
    }
}

displayList()

// 更多用法请举一反三。

列表类其实是对数组的封装,提供一套方法给外面方便使用。类似的我们也可以封装某些功能的类库,使用时就能方便的new出该类的对象,调用该类的方法。