Stack Algorithm
The Stack Using Array Algorithm is an efficient data structure that implements the stack concept using an array as its underlying storage mechanism. The stack is a linear data structure that follows the Last-In-First-Out (LIFO) order, where the last element added to the stack is the first one to be removed. It consists of two main operations: pushing (adding) an element onto the stack and popping (removing) the element from the top of the stack. The array-based implementation of this algorithm allows for fast and easy access to the stack's top element, making it a popular choice for various applications such as parsing, expression evaluation, and function call management.
In the array-based stack implementation, an integer variable called "top" is used to keep track of the index of the topmost element in the stack. When a new element is pushed onto the stack, the "top" index is incremented, and the element is placed at that index in the array. Conversely, when an element is popped from the stack, the "top" index is decremented, effectively removing the element from the stack. One of the key considerations for this algorithm is the stack's capacity, which is determined by the size of the underlying array. When the stack becomes full, it may require resizing (either by doubling or shrinking) to accommodate additional elements or to conserve memory. This dynamic resizing can be implemented using a dynamic array or by allocating and deallocating memory as needed. Overall, the Stack Using Array Algorithm offers a simple and efficient method for implementing a stack data structure with constant time complexity for both push and pop operations, making it an attractive choice for a wide range of applications.
/*
* Copyright (c) 2017 Kotlin Algorithm Club
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.algorithmexamples.datastructures
import java.util.*
@Suppress("RedundantVisibilityModifier")
public class Stack<T> : Collection<T> {
private var head: Node<T>? = null
public override var size: Int = 0
private set
private class Node<T>(var value: T) {
var next: Node<T>? = null
}
public fun push(item: T) {
val new = Node(item)
new.next = head
head = new
size++
}
public fun peek(): T {
if (size == 0) throw NoSuchElementException()
return head!!.value
}
public fun poll(): T {
if (size == 0) throw NoSuchElementException()
val old = head!!
head = old.next
size--
return old.value
}
public override fun isEmpty(): Boolean {
return size == 0
}
public override fun contains(element: T): Boolean {
for (obj in this) {
if (obj == element) return true
}
return false
}
public override fun containsAll(elements: Collection<T>): Boolean {
for (element in elements) {
if (!contains(element)) return false
}
return true
}
public override fun iterator(): Iterator<T> {
return object : Iterator<T> {
var node = head
override fun hasNext(): Boolean {
return node != null
}
override fun next(): T {
if (!hasNext()) throw NoSuchElementException()
val current = node!!
node = current.next
return current.value
}
}
}
}