线性数据结构-栈

作者 : admin 本文共1315个字,预计阅读时间需要4分钟 发布时间: 2024-06-10 共1人阅读

在JavaScript中,栈(Stack)是一种遵循后进先出(Last In First Out, LIFO)原则的数据结构。这意味着最后进入栈的元素将会是第一个被移除的元素。栈通常被用于限制线性数据的访问顺序,使得数据的插入和删除操作只能在栈的一端进行。

栈的基本操作包括:

  • push:将一个元素放入栈顶。
  • pop:移除栈顶的元素,并返回被移除的元素。
  • peek 或 top:返回栈顶的元素,但不移除它。
  • isEmpty:检查栈是否为空。
  • size:返回栈中元素的数量。

数组实现栈:

  • 数组实现的栈在大多数情况下提供了更好的缓存性能,因为数组元素在内存中是连续存储的,这有助于利用现代处理器的缓存机制。
  • 数组的push和pop操作通常是高效的,时间复杂度为O(1)。
  • 但是,如果数组需要频繁地扩容(当数组满时),这将涉及到创建新数组并复制旧数组元素的操作,这个操作的时间复杂度为O(n)。不过,这种操作并不经常发生,因为数组扩容通常是成倍增长的,所以在多次push操作后才会触发。
class Stack {
    constructor() {
        this.items = []
    }
    push(value) {
        this.items.push(value)
    }
    pop() {
        return this.items.pop()
    }

    isEmpty(){
        return this.items.length === 0
    }

    peek() {
        if(this.isEmpty()){
            return undefined
        }
        return this.items[this.items.length - 1]
    }
    size() {
        return this.items.length
    }
}

链表实现栈

  • 链表实现的栈在动态内存分配方面更加灵活,因为链表节点可以分散在内存中,不需要连续的内存空间。
  • 链表的插入和删除操作(对应栈的push和pop)也是时间复杂度为O(1),但是因为这些操作需要处理指针,可能会有一些额外的开销。
  • 链表实现的栈不会遇到数组扩容的问题,因为链表可以根据需要动态地分配节点。
class Node {
    constructor(val) {
        this._value = val;
        this._next = null;
    }
}

class Stack {
    constructor() {
        this._top = null;
        this._size = 0;
    }

    isEmpty() {
        return this._size === 0;
    }

    push(value) {
        const node = new Node(value)
        if (this.isEmpty()) {
            this._top = node
        } 
        node.next = this._top
        this._top = node
        this._size++
    }

    pop() {
        if (this.isEmpty()) {
            return undefined;
        }  
        this._size--
        const removedNode = this._top
        this._top = this._top.next
        return removedNode._value
    }

    peek() {
        if (this.isEmpty()) {
          return undefined
        }
        return this._top.value;
    }

    getSize() {
        return this._size;
    }
}



本站无任何商业行为
个人在线分享 » 线性数据结构-栈
E-->