1+ package com .thealgorithms .datastructures .stacks ;
2+
3+ /**
4+ * A generic stack implementation using a singly linked list.
5+ * This implementation provides O(1) time complexity for push, pop, and peek operations.
6+ *
7+ * @param <T> the type of elements held in this stack
8+ * @author Your Name
9+ */
10+ public class StackUsingLinkedList <T > {
11+
12+ /**
13+ * Inner class representing a node in the linked list.
14+ */
15+ private static class Node <T > {
16+ T data ;
17+ Node <T > next ;
18+
19+ /**
20+ * Constructs a new node with the given data.
21+ *
22+ * @param data the data to store in this node
23+ */
24+ Node (T data ) {
25+ this .data = data ;
26+ this .next = null ;
27+ }
28+ }
29+
30+ private Node <T > top ;
31+ private int size ;
32+
33+ /**
34+ * Constructs an empty stack.
35+ */
36+ public StackUsingLinkedList () {
37+ this .top = null ;
38+ this .size = 0 ;
39+ }
40+
41+ /**
42+ * Pushes an element onto the top of this stack.
43+ * Time Complexity: O(1)
44+ *
45+ * @param data the element to be pushed onto this stack
46+ */
47+ public void push (T data ) {
48+ Node <T > newNode = new Node <>(data );
49+ newNode .next = top ;
50+ top = newNode ;
51+ size ++;
52+ }
53+
54+ /**
55+ * Removes and returns the element at the top of this stack.
56+ * Time Complexity: O(1)
57+ *
58+ * @return the element at the top of this stack
59+ * @throws IllegalStateException if this stack is empty
60+ */
61+ public T pop () {
62+ if (isEmpty ()) {
63+ throw new IllegalStateException ("Stack is empty. Cannot pop element." );
64+ }
65+ T data = top .data ;
66+ top = top .next ;
67+ size --;
68+ return data ;
69+ }
70+
71+ /**
72+ * Returns the element at the top of this stack without removing it.
73+ * Time Complexity: O(1)
74+ *
75+ * @return the element at the top of this stack
76+ * @throws IllegalStateException if this stack is empty
77+ */
78+ public T peek () {
79+ if (isEmpty ()) {
80+ throw new IllegalStateException ("Stack is empty. Cannot peek element." );
81+ }
82+ return top .data ;
83+ }
84+
85+ /**
86+ * Checks if this stack is empty.
87+ * Time Complexity: O(1)
88+ *
89+ * @return {@code true} if this stack contains no elements, {@code false} otherwise
90+ */
91+ public boolean isEmpty () {
92+ return top == null ;
93+ }
94+
95+ /**
96+ * Returns the number of elements in this stack.
97+ * Time Complexity: O(1)
98+ *
99+ * @return the number of elements in this stack
100+ */
101+ public int size () {
102+ return size ;
103+ }
104+
105+ /**
106+ * Removes all elements from this stack.
107+ * Time Complexity: O(1)
108+ */
109+ public void clear () {
110+ top = null ;
111+ size = 0 ;
112+ }
113+
114+ /**
115+ * Returns a string representation of this stack.
116+ * The string representation consists of a list of the stack's elements
117+ * from top to bottom, enclosed in square brackets ("[]").
118+ *
119+ * @return a string representation of this stack
120+ */
121+ @ Override
122+ public String toString () {
123+ if (isEmpty ()) {
124+ return "[]" ;
125+ }
126+
127+ StringBuilder sb = new StringBuilder ("[" );
128+ Node <T > current = top ;
129+ while (current != null ) {
130+ sb .append (current .data );
131+ if (current .next != null ) {
132+ sb .append (", " );
133+ }
134+ current = current .next ;
135+ }
136+ sb .append ("]" );
137+ return sb .toString ();
138+ }
139+
140+ /**
141+ * Demonstration of the StackUsingLinkedList implementation.
142+ *
143+ * @param args command line arguments (not used)
144+ */
145+ public static void main (String [] args ) {
146+ // Example 1: Stack of Integers
147+ System .out .println ("=== Integer Stack Demo ===" );
148+ StackUsingLinkedList <Integer > intStack = new StackUsingLinkedList <>();
149+
150+ // Push elements
151+ intStack .push (10 );
152+ intStack .push (20 );
153+ intStack .push (30 );
154+ intStack .push (40 );
155+ System .out .println ("Stack after pushing 10, 20, 30, 40: " + intStack );
156+ System .out .println ("Size: " + intStack .size ());
157+
158+ // Peek
159+ System .out .println ("Top element (peek): " + intStack .peek ());
160+
161+ // Pop elements
162+ System .out .println ("Popped: " + intStack .pop ());
163+ System .out .println ("Popped: " + intStack .pop ());
164+ System .out .println ("Stack after popping twice: " + intStack );
165+ System .out .println ("Size: " + intStack .size ());
166+
167+ // Check if empty
168+ System .out .println ("Is stack empty? " + intStack .isEmpty ());
169+
170+ // Pop remaining elements
171+ intStack .pop ();
172+ intStack .pop ();
173+ System .out .println ("Is stack empty after popping all? " + intStack .isEmpty ());
174+
175+ // Example 2: Stack of Strings
176+ System .out .println ("\n === String Stack Demo ===" );
177+ StackUsingLinkedList <String > stringStack = new StackUsingLinkedList <>();
178+
179+ stringStack .push ("Hello" );
180+ stringStack .push ("World" );
181+ stringStack .push ("Java" );
182+ System .out .println ("Stack: " + stringStack );
183+ System .out .println ("Top: " + stringStack .peek ());
184+ System .out .println ("Popped: " + stringStack .pop ());
185+ System .out .println ("Stack after pop: " + stringStack );
186+
187+ // Example 3: Exception handling
188+ System .out .println ("\n === Exception Handling Demo ===" );
189+ StackUsingLinkedList <Integer > emptyStack = new StackUsingLinkedList <>();
190+ try {
191+ emptyStack .pop ();
192+ } catch (IllegalStateException e ) {
193+ System .out .println ("Caught exception: " + e .getMessage ());
194+ }
195+
196+ try {
197+ emptyStack .peek ();
198+ } catch (IllegalStateException e ) {
199+ System .out .println ("Caught exception: " + e .getMessage ());
200+ }
201+
202+ // Example 4: Clear operation
203+ System .out .println ("\n === Clear Operation Demo ===" );
204+ StackUsingLinkedList <Integer > stack = new StackUsingLinkedList <>();
205+ stack .push (1 );
206+ stack .push (2 );
207+ stack .push (3 );
208+ System .out .println ("Stack before clear: " + stack );
209+ stack .clear ();
210+ System .out .println ("Stack after clear: " + stack );
211+ System .out .println ("Is empty? " + stack .isEmpty ());
212+ }
213+ }
0 commit comments