数据结构-JS实现栈、队列、链表

1,481 阅读3分钟

栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶。咖啡厅内的一摞盘子是现实世界中常见的栈的例子。只能从最上面取盘子,盘子洗净后,也只能摞在这一摞盘子的最上面。栈被称为一种后入先出(LIFO, last-in-first-out)的数据结构。

栈
对栈的基本操作:

  • 入栈(push)
  • 出栈(pop)
  • 查看栈顶元素(peek)
  • 获取栈的长度(length)
  • 清空栈(clear)
  • 判断栈是否空(isEmpty)

栈的应用场景:

  • 递归函数的使用。

下面代码实现的栈的构造函数,已经对构造函数的测试验证。

class Stack{
    constructor(){
        this.data = [];
    }
	
    push(el){
        this.data.push(el);
    }
    pop(){
        return this.data.pop();
    }
    peek(){
        return this.data[this.data.length-1];
    }
    length(){
        return this.data.length;
    }
    clear(){
        this.data.length = 0;
    }
    isEmpty(){
        return this.data.length == 0 ? true : false
    }
}

let s = new Stack();
s.push("张三");
s.push("李四");
s.push("王五");
console.log(s.length());        //3
console.log(s.pop());           //"王五"
console.log(s.length());        //2
console.log(s.peek());          //"李四"
console.log(s.length());        //2
s.clear();  
console.log(s.length());        //0
console.log(s.isEmpty());       //true

队列

队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素。队列用于存储按顺序排列的数据,先进先出,这点和栈不一样,在栈中,最后入栈的元素反而被优先处理。可以将队列想象成在银行前排队的人群,排在最前面的人第一个办理业务,新来的人只能在后面排队,直到轮到他们为止。 队列是一种先进先出(First-In-First-Out, FIFO)的数据结构。

队列
对队列的基本操作:

  • 入队(push)
  • 出队(pop)
  • 查看对头元素(peek)
  • 获取队列的长度(length)
  • 清空队列(clear)
  • 判断队列是否空(isEmpty)

下面代码实现的队列的构造函数,已经对构造函数的测试验证。

class Queue{
    constructor(){
        this.data = [];
    }
	
    push(el){
        this.data.push(el);
    }
    pop(){
        return this.data.shift();
    }
    peek(){
        return this.data[0];
    }
    length(){
        return this.data.length;
    }
    clear(){
        this.data.length = 0;
    }
    isEmpty(){
        return this.data.length == 0 ? true : false
    }
}

let q = new Queue();
q.push("张三");
q.push("李四");
q.push("王五");
console.log(q.length());        //3
console.log(q.pop());           //"张三"
console.log(q.length());        //2
console.log(q.peek());          //"李四"
console.log(q.length());        //2
q.clear();  
console.log(q.length());        //0
console.log(q.isEmpty());       //true

链表

链表是由一组节点组成的集合。每个节点都使用一个对象的引用指向它的后继。指向另一个节点的引用叫做链。在链表最最前面有一个特殊的节点,叫做头节点,链表的尾元素指向一个null节点。遍历链表,就是跟着链接,从链表的首元素一直走到尾元素(不包含链表的头节点,头节点通常只是用来作为链表的接入点)。

链表
对链表的基本操作:

  • 向链表插入元素(insert)
  • 从链表中删除元素(remove)
  • 输出链表(toString)

下面代码实现的队列的构造函数,已经对构造函数的测试验证。

class Node{
    constructor(el){
        this.el = el;
        this.next = null;
    }
}
class linkedList{
    constructor(){
        this.head = new Node("head");
    }
    //查找链表中指定元素
    find(item){
        let currNode = this.head;
        while(currNode != null && currNode.el != item){
            currNode = currNode.next;
        }
        return currNode;
    }
    //查找指定元素的前驱节点
    findPrevious(item){ 
        let currNode = this.head;
        while(currNode.next != null && currNode.next.el != item){
            currNode = currNode.next;
        }
        return currNode;
    }
    
    insert(newEl,item){
        let newNode = new Node(newEl);
        let current = this.find(item);
        //元素不存在,返回false
        if( current == null ) return false;
        newNode.next = current.next;
        current.next = newNode;
        return true;
    }
    remove(item){
        let prevNode = this.findPrevious(item);
        //元素不存在,返回false
        if(prevNode.next == null) return false;
        prevNode.next = prevNode.next.next;
        return true;
    }
    toString(){
        let currNode = this.head;
        let str = ''
        while(currNode.next != null){
            str = str + currNode.next.el + ' -> ';
            currNode = currNode.next;
        }
        return str.slice(0,str.length-4);
    }
}

let link = new linkedList();
link.insert("张三","head");
link.insert("李四","张三");
link.insert("王五","李四");
link.insert("赵六","王五");
console.log(link.toString());       //张三 -> 李四 -> 王五 -> 赵六
link.remove("王五");
console.log(link.toString());       //张三 -> 李四 -> 赵六