数据结构那些事(二)

上篇数据结构那些事(一)已经介绍了数组,列表和栈。这篇咱们将介绍队列,链表,字典。数组

队列也是一种列表,遵循先进先出的规则。

队列的两种主要操做是:向队列中插入新元素和删除队列中的元素。入队操做在队尾插入新元素,出队在队头删除元素。 接下来,咱们来设计一个队列Queue类:bash

function Queue(){
    this.dataStore = [];//存储
    this.enqueue = enqueue;//入队
    this.dequeue = dequeue;//出队
    this.front = front;//队首
    this.back = back;//队尾
    this.toString = toString;//显示队列元素
    this.empty = empty;//清除
}
复制代码

实现上面的操做方法:cookie

function enqueue(e){
    this.dataStore.push(e);
}
function dequeue(e){
    this.dataStore.shift(e)
}
function front(){
    return this.dataStore[0]
}
function back(){
    return this.dataStore[this.dataStore.length - 1]
}
function toString(){
    let retStr = "";
    for (let i = 0; i<this.dataStore.length; ++i){
        retStr += this.dataStore[i] + "\n";
    }
    return retStr;
}
function empty(){
    if(this.dataStore.length === 0){
        return true;
    }else{
        return false;
    }
}
复制代码

上面咱们实现了一个基础的队列。但现实生活中,可能会出现相似军人优先,重病患优先这样的场景,那样咱们上面的队列就没法知足了。这时,咱们须要一个优先队列。 从优先队列中删除元素时,须要考虑优先权的限制。咱们来定义一下存储在队列中的元素:数据结构

function Person(name, code){
    this.name = name;
    this.code = code; //表示优先级,越小优先级越高
}
复制代码

如今,须要从新定义dequeue()方法。post

function dequeue(){
    let p = this.dataStore[0].code;
    for(let i =1 ; i < this.dataStore.length; ++i){
        if(this.dataStore[i].code < p){
            p = i
        }
    }
    return this.dataStore.splice(p, 1);
}
复制代码

链表:有时候咱们使用数组效率比较低的时候就能够考虑使用链表。固然,若是你的场景须要随机访问,数组仍然比链表更合适。

链表元素依靠相互之间的关系进行引用。遍历链表,就是跟着链表,从链表的首元素一直走到尾元素,链表的尾元素通常指向null。ui

下图演示了在eggs后插入cookies操做this

下图演示了删除操做

从上面的几张图,咱们能直观的感觉到,链表作这些插入和删除操做比数组要便捷的多。由于数组执行插入删除操做时还须要对应的改变数组中其余元素的索引。而链表只须要改变对应节点的指向便可完成操做,二者不可同日而语。

明白了链表的好处,接下来咱们来设计实现一个链表:

咱们设计的链表包含两个类。Node类用来表示节点,LinkedList类提供插入,删除,显示元素等方法。spa

function Node(e){
    this.element = e;
    this.next = null;
}
function LList(){
    this.head = new Node("head");
    this.find = find; //遍历链表,查找给定数据
    this.findPrev = findPrev; //遍历链表,查找给定数据前面一个节点
    this.insert = insert; //插入一个节点
    this.remove = remove; //删除
    this.display = display; //显示
}
复制代码

实现上面的方法:设计

function find(e){
    let currNode = this.head;
    while(currNode.element !== e){
        currNode = currNode.next;
    }
    return currNode;
}

function insert(newEl, e){
    let newNode = new Node(newEl);
    let current = this.find(e);
    newNode.next = current.next;
    current.next = newNode;
}

function display(){
    let currNode = this.head;
    while(currNode.next !== null){
        console.log(currNode.next.element);
        corrNode = currNode.next;
    }
}

function findPrev(e){
    let currNode = this.head;
    while(currNode.next !== null && currNode.next.element !== e){
        currNode = currNode.next;
    }
    return currNode;
}

function remove(e){
    let prev = this.findPrev(e);
    if(prev.next !== null){
        prev.next = prev.next.next;
    }
}
复制代码

上面定义的基础链表存在一个问题:很难从后向前遍历

这时,咱们能够考虑实现一个双向链表:code

按照上图的理解:咱们先要给Node类增长一个先前链接的属性

function Node(element) {
    this.element = element;
    this.next = null;
    this.previous = null;
}
复制代码

咱们还要修改对应的insert方法,由于他如今须要创建两个链接

function insert(newElement, item) {
    var newNode = new Node(newElement);
    var current = this.find(item);
    newNode.next = current.next;
    newNode.previous = current;
    current.next = newNode;
}
复制代码

双向链表的remove()方法比单向链表的效率更高,由于不须要查找前驱节点了。

function remove(item) {
    var currNode = this.find(item);
    if (!(currNode.next == null)) {
        currNode.previous.next = currNode.next;
        currNode.next.previous = currNode.previous;
        currNode.next = null;
        currNode.previous = null;
    }
}
复制代码

还有一种链表是循环链表:和单向链表相似,惟一的区别是,在建立循环列表时,让其头结点的next属性指向它自己。

建立循环列表,咱们只须要改变一下LList类便可:

function LList() {
    this.head = new Node("head");
    this.head.next = this.head; //让头结点的next指向它本身
    this.find = find;
    this.insert = insert;
    this.display = display;
    this.findPrevious = findPrevious;
    this.remove = remove;
}
复制代码

字典:字典是一种以键值对形式存储数据的数据结构。

JavaScript中的Object类就是以字典形式设计的。因此字典的实现就像对象同样,感受实在没什么值得写的,这里给一个demo。

function Dictionary(){
    this.dataStore = new Array();
}

function add(key, value){
    this.dataStore[key] = value;
}

function find(key){
    return this.dataStore[key];
}

function remove(key){
    delete this.dataStore[key]
}

function show(){
    for( let key in Object.keys(this.dataStore)){
        console.log(key + this.dataStore[key])
    }
}
复制代码
相关文章
相关标签/搜索