栈(stack)是限定仅在表尾进行插入和删除操作的线性表。咱们把容许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈。栈又称为后进先出的线性表 因为栈具备后入先出的特点,所以任何不在栈顶的元素都无法访问。为了失去栈底的元素,必须先拿掉下面的元素。



对栈的两种次要操作是将一个元素压入栈和将一个元素弹出栈。入栈应用 push()办法,出栈应用 pop()办法,上面用代码实现栈这种数据结构

实现栈类

  1. dataStore代表数据集
  2. top代表栈顶坐标

    class Stack{  dataStore=[]  top=0  constructor(){  }}

    push():进栈

push(element){    this.dataStore[this.top++] = element  }

pop():出栈

pop(){    let element = this.dataStore[--this.top]    this.dataStore.length = this.top    return element  }

peek():返回栈顶

peek(){    return this.dataStore[this.top-1]  }

length():数据的数量

length() {    return this.top;  }

clear():清空栈

clear() {    this.top = 0;    this.dataStore.length=0  }

残缺代码

class Stack {    dataStore = []    top = 0    constructor() {    }    push(element) {        this.dataStore[this.top++] = element    }    pop() {        let element = this.dataStore[--this.top]        this.dataStore.length = this.top        return element    }    peek() {        return this.dataStore[this.top - 1]    }    length() {        return this.top;    }    clear() {        this.top = 0;        this.dataStore.length = 0    }}

队列

队列是一种列表,一种只能在队尾插入元素,在队首删除元素的列表。队列用于存储按顺序排列的数据,先进先出队列的两种次要操作是:向队列中插入新元素和删除队列中的元素。插入操作也叫做入队,删除操作也叫做出队。入队操作在队尾插入新元素,出队操作删除队头的元素。


上面用代码实现队列

实现 Queue 类

dataStore代表数据集

class Queue {    dataStore = []    constructor() {    }}

enqueue() 办法向队尾增加一个元素

enqueue(element) {        this.dataStore.push(element)    }

dequeue() 办法删除队首的元素

dequeue() {        return this.dataStore.shift()    }

能够应用如下办法读取队首和队尾的元素

front() {    return this.dataStore[0]}back() {    return this.dataStore[this.dataStore.length - 1]}

toString() 办法显示队列内的所有元素

toString() {        return String(this.dataStore)    }

判断队列是否为空

empty() {        return this.dataStore.length == 0    }

实现代码

class Queue {    dataStore = []    constructor() {    }    enqueue(element) {        this.dataStore.push(element)    }    dequeue() {        return this.dataStore.shift()    }    front() {        return this.dataStore[0]    }    back() {        return this.dataStore[this.dataStore.length - 1]    }    toString() {        return String(this.dataStore)    }    empty() {        return this.dataStore.length == 0    }}

链表

链表是由一组节点组成的汇合。每个节点都应用一个对象的援用指向它的后继。指向另一个节点的援用叫做链。标识出链表的起始节点却有点麻烦,因而在链表最后面有一个非凡节点,叫做头节点


设计的链表蕴含两个类。Node类用来示意节点,LinkedList类提供了插入节点、删除节点、显示列表元素的办法,以及其余一些辅助办法。

Node类
节点蕴含数据和指针,如下图所示

  1. element代表元素
  2. next为指针

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

    LinkedList类

链表创立默认给个头结点

class LinkedList {  constructor(){    this.head = new Node('head')  }}

find()查找一个节点

//从头遍历开始查找find(item){    let node = this.head    while(node&&node.element != item){      node = node.next    }    return node  }

findPrevious()查找指标前一个节点

findPrevious(item){    let node = this.head    while(node.next&&node.next.element != item){      node = node.next    }    return node.next?node:null  }

insert()插入新节点


插入节点是将新元素节点的指针指向指标元素指针指向的节点,再讲指标节点的指针指向新节点

insert(element,item){    let node = this.find(item)    if(node){      let newNode = new Node(element)      newNode.next =  node.next      node.next = newNode    }  }

remove()删除一个节点


删除节点是将指标节点的上一个节点指向指标节点的下一个节点

remove(item){    let node = this.findPrevious(item)    if(node){      node.next = node.next.next    }  }

display()打印链表

display(){    let node = this.head    while(node){      console.log(node.element)      node = node.next    }  }

残缺代码

class Node {    constructor(element) {        this.element = element        this.next = null    }}class LinkedList {    constructor() {        this.head = new Node('head')    }    find(item) {        let node = this.head        while (node && node.element != item) {            node = node.next        }        return node    }    findPrevious(item) {        let node = this.head        while (node.next && node.next.element != item) {            node = node.next        }        return node.next ? node : null    }    insert(element, item) {        let node = this.find(item)        if (node) {            let newNode = new Node(element)            newNode.next = node.next            node.next = newNode        }    }    remove(item) {        let node = this.findPrevious(item)        if (node) {            node.next = node.next.next        }    }    display() {        let node = this.head        while (node) {            console.log(node.element)            node = node.next        }    }}

双向链表

只管从链表的头节点遍历到尾节点很简略,但反过来,从后向前遍历则没那么简略。通过给Node对象减少一个属性,该属性存储指向前驱节点的链接,这样就容易多了。此时向链表插入一个节点须要更多的工作,咱们须要指出该节点正确的前驱和后继。然而在从链表中删除节点时,效率进步了,不须要再查找待删除节点的前驱节点了

Node类

双向链表的节点比单向链表的节点多了一个前驱指针previous

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

实现双向链表

class DoubleLink{  constructor(){    this.head = new Node('head')  }}

查找一个元素

find(item){    let node = this.head    while(node&&node.element != item){      node = node.next    }    return node  }

查找前一个元素

findPrevious(item){    let node = this.head    while(node.next&&node.next.element != item){      node = node.next    }    return node.next?node:null  }

查找最初一个元素

findLast(){    let node = this.head    while(node.next){      node = node.next    }    return node  }

插入一个元素


插入节点,除了和单向链表一样的操作外,后一个节点的前驱指针得指向要插入的节点,插入的节点的前驱指针须要指向前一个节点

insert(element,item){    let node = this.find(item)    if(node){      let newNode = new Node(element)      newNode.previous = node      if( node.next){        node.next.previous = newNode      }      newNode.next =  node.next      node.next = newNode    }  }

删除一个元素

remove(item){    let node = this.findPrevious(item)    if(node){      if(node.next.next){        node.next.next.previous = node      }      node.next = node.next.next    }  }

打印元素

display(){    let node = this.head    while(node){      console.log(node.element)      node = node.next    }  }

逆向打印链表

dispReverse(){    let node = this.findLast()    while(node){      console.log(node.element)      node = node.previous    }  }

残缺代码

class Node {    constructor(element) {        this.element = element        this.next = null        this.previous = null    }}class DoubleLink {    constructor() {        this.head = new Node('head')    }    find(item) {        let node = this.head        while (node && node.element != item) {            node = node.next        }        return node    }    findPrevious(item) {        let node = this.head        while (node.next && node.next.element != item) {            node = node.next        }        return node.next ? node : null    }    findLast() {        let node = this.head        while (node.next) {            node = node.next        }        return node    }    insert(element, item) {        let node = this.find(item)        if (node) {            let newNode = new Node(element)            newNode.previous = node            if (node.next) {                node.next.previous = newNode            }            newNode.next = node.next            node.next = newNode        }    }    remove(item) {        let node = this.findPrevious(item)        if (node) {            if (node.next.next) {                node.next.next.previous = node            }            node.next = node.next.next        }    }    display() {        let node = this.head        while (node) {            console.log(node.element)            node = node.next        }    }    dispReverse() {        let node = this.findLast()        while (node) {            console.log(node.element)            node = node.previous        }    }}