A stack is a linear data structure that restricts insertions and deletions to a single endpoint—referred to as the top—while the opposite fixed end is the bottom. When no elements are present, its an empty stack, and its fundamental behavior follows Last-In-First-Out (LIFO) semantics.
Static Stack Using Contiguous Memory
This implementation leverages a dynamically allocated array with an integer index tracking the top position.
Structure Definition
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int ElementType;
typedef struct {
ElementType *buffer;
int capacity;
int current_size;
} ArrayStack;
Initialization
ArrayStack* create_array_stack(int max_elements) {
if (max_elements <= 0) return NULL;
ArrayStack* s = malloc(sizeof(ArrayStack));
if (!s) return NULL;
s->buffer = malloc(max_elements * sizeof(ElementType));
if (!s->buffer) {
free(s);
return NULL;
}
s->capacity = max_elements;
s->current_size = 0;
return s;
}
Push Operation
int push(ArrayStack* s, ElementType value) {
if (!s || s->current_size >= s->capacity) return -1;
s->buffer[s->current_size++] = value;
return 0;
}
Pop Operation
int pop(ArrayStack* s, ElementType* out_value) {
if (!s || s->current_size == 0) return -1;
*out_value = s->buffer[--s->current_size];
return 0;
}
Peek and Utility Functions
int peek(const ArrayStack* s, ElementType* out_value) {
if (!s || s->current_size == 0) return -1;
*out_value = s->buffer[s->current_size - 1];
return 0;
}
int is_empty(const ArrayStack* s) {
return s ? (s->current_size == 0) : -1;
}
int is_full(const ArrayStack* s) {
return s ? (s->current_size == s->capacity) : -1;
}
void clear_stack(ArrayStack* s) {
if (s) s->current_size = 0;
}
void destroy_array_stack(ArrayStack* s) {
if (s) {
free(s->buffer);
free(s);
}
}
Dynamic Stack Using Singly Linked Nodes
In this version, each node holds one element and a pointer to the next; the head of the list serves as the stack top.
Node and Stack Definitions
struct StackNode {
ElementType val;
struct StackNode* next;
};
typedef struct {
struct StackNode* head;
} LinkedStack;
Initialization
LinkedStack* create_linked_stack(void) {
LinkedStack* s = malloc(sizeof(LinkedStack));
if (!s) return NULL;
s->head = NULL;
return s;
}
Push Operation
int push_linked(LinkedStack* s, ElementType value) {
if (!s) return -1;
struct StackNode* new_node = malloc(sizeof(struct StackNode));
if (!new_node) return -1;
new_node->val = value;
new_node->next = s->head;
s->head = new_node;
return 0;
}
Pop Operation
int pop_linked(LinkedStack* s, ElementType* out_value) {
if (!s || !s->head) return -1;
struct StackNode* temp = s->head;
*out_value = temp->val;
s->head = temp->next;
free(temp);
return 0;
}
Peek and Utility Functions
int peek_linked(const LinkedStack* s, ElementType* out_value) {
if (!s || !s->head) return -1;
*out_value = s->head->val;
return 0;
}
int is_empty_linked(const LinkedStack* s) {
return s ? (s->head == NULL) : -1;
}
void destroy_linked_stack(LinkedStack* s) {
if (!s) return;
struct StackNode* current = s->head;
while (current != NULL) {
struct StackNode* next = current->next;
free(current);
current = next;
}
free(s);
}
Example Usage
int main() {
// Test array-based stack
ArrayStack* arr_stack = create_array_stack(5);
if (arr_stack) {
push(arr_stack, 10);
push(arr_stack, 20);
push(arr_stack, 30);
ElementType val;
while (pop(arr_stack, &val) == 0) {
printf("Popped: %d\n", val);
}
destroy_array_stack(arr_stack);
}
// Test linked stack
LinkedStack* link_stack = create_linked_stack();
if (link_stack) {
push_linked(link_stack, 100);
push_linked(link_stack, 200);
while (pop_linked(link_stack, &val) == 0) {
printf("Popped: %d\n", val);
}
destroy_linked_stack(link_stack);
}
return 0;
}