Understanding Static and Dynamic Stack Implementations in C
- Static Stack
1.1 Definition
A static stack is a fixed-capacity stack data structure where the size is determined at creation time and cannot be modified during runtime. This implementation relies on a pre-allocated array to hold elements, and since memory is reserved during compilation, there's a potential risk of stack overflow when attempting to push elements beyond the defined capacity.
1.2 Characteristics
The stack capacity remains constant throughout its lifetime An array serves as the underlying storage mechanism, with a top pointer tracking the current position Overflow conditions can occur when attempting to push onto a full stack
1.3 Implementation Example
#include <stdio.h>
#define MAX_ELEMENTS 10
typedef struct {
int elements[MAX_ELEMENTS];
int currentTop;
} FixedStack;
void initStack(FixedStack *stack) {
stack->currentTop = -1;
}
void pushElement(FixedStack *stack, int value) {
if (stack->currentTop < MAX_ELEMENTS - 1) {
stack->elements[++stack->currentTop] = value;
printf("Pushed: %d\n", value);
} else {
printf("Stack overflow!\n");
}
}
int popElement(FixedStack *stack) {
if (stack->currentTop >= 0) {
int extracted = stack->elements[stack->currentTop--];
printf("Popped: %d\n", extracted);
return extracted;
}
printf("Stack underflow!\n");
return -1;
}
void printStack(FixedStack *stack) {
if (stack->currentTop == -1) {
printf("Stack is empty\n");
} else {
printf("Stack contents: ");
for (int i = 0; i <= stack->currentTop; i++) {
printf("%d ", stack->elements[i]);
}
printf("\n");
}
}
int main() {
FixedStack myStack;
initStack(&myStack);
pushElement(&myStack, 10);
pushElement(&myStack, 20);
pushElement(&myStack, 30);
printStack(&myStack);
int result = popElement(&myStack);
printf("Returned value: %d\n", result);
printStack(&myStack);
return 0;
}
Output:
Pushed: 10
Pushed: 20
Pushed: 30
Stack contents: 10 20 30
Popped: 30
Returned value: 30
Stack contents: 10 20
- Dynamic Stack (Linked Stack)
2.1 Definition
A dynamic stack utilizes heap memory allocation, allowing its size to grow or shrink based on operational demands. This approach employs dynamic memory management through pointers, providing flexibility that static stacks cannot offer.
2.2 Characteristics
Memory allocation occurs at runtime with complete programmer control The capacity can adapt dynamically to accommodate more or fewer elements No fixed size limitations reduce the risk of overflow
2.3 Implementation Example
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int *buffer;
int topIndex;
int maxSize;
} FlexibleStack;
void createStack(FlexibleStack *stack, int size) {
stack->buffer = (int *)malloc(sizeof(int) * size);
stack->topIndex = -1;
stack->maxSize = size;
}
void pushValue(FlexibleStack *stack, int value) {
if (stack->topIndex < stack->maxSize - 1) {
stack->buffer[++stack->topIndex] = value;
printf("Pushed: %d\n", value);
} else {
printf("Stack at capacity!\n");
}
}
int popValue(FlexibleStack *stack) {
if (stack->topIndex >= 0) {
int extracted = stack->buffer[stack->topIndex--];
printf("Popped: %d\n", extracted);
return extracted;
}
printf("Stack is empty!\n");
return -1;
}
void showStack(FlexibleStack *stack) {
if (stack->topIndex == -1) {
printf("Stack is empty\n");
} else {
printf("Stack contents: ");
for (int i = 0; i <= stack->topIndex; i++) {
printf("%d ", stack->buffer[i]);
}
printf("\n");
}
}
int main() {
FlexibleStack dynStack;
createStack(&dynStack, 5);
pushValue(&dynStack, 100);
pushValue(&dynStack, 200);
pushValue(&dynStack, 300);
showStack(&dynStack);
popValue(&dynStack);
showStack(&dynStack);
free(dynStack.buffer);
return 0;
}
Output:
Pushed: 100
Pushed: 200
Pushed: 300
Stack contents: 100 200 300
Popped: 300
Stack contents: 100 200