Fundamental Data Structures: Stacks and Queues in C
A stack operates on a Last-In, First-Out (LIFO) principle. It is a linear structure where insertion and deletino occur exclusively at one end, known as the top. The opposite end is the base. Adding an element is termed pushing, while removing one is popping.
Sequential Stack Implementation
Using a fixed-size array allows for efficient memory usage. The following example defines a structure containing a buffer and an index tracker.
#include <stdio.h>
#include <stdlib.h>
#define CAPACITY 10
typedef struct {
int buffer[CAPACITY];
int index;
} ArrayStack;
int show_options(void);
int push_element(ArrayStack *s, int value);
int pop_element(ArrayStack *s, int *value);
int main(void) {
int input_val, result;
ArrayStack *stack = (ArrayStack *)malloc(sizeof(ArrayStack));
if (!stack) return 1;
stack->index = 0;
while (1) {
switch (show_options()) {
case 1:
printf("Enter value to push: ");
scanf("%d", &input_val);
result = push_element(stack, input_val);
printf(result ? "Push successful.\n" : "Push failed: Stack full.\n");
break;
case 2:
result = pop_element(stack, &input_val);
if (result)
printf("Pop successful. Value: %d\n", input_val);
else
printf("Pop failed: Stack empty.\n");
break;
case 3:
printf("Exiting program.\n");
free(stack);
return 0;
default:
printf("Invalid selection.\n");
}
}
}
int show_options(void) {
int choice;
printf("\nSelect Operation:\n");
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Exit\n");
scanf("%d", &choice);
return (choice >= 1 && choice <= 3) ? choice : 0;
}
int push_element(ArrayStack *s, int value) {
if (s->index >= CAPACITY) return 0;
s->buffer[s->index++] = value;
return 1;
}
int pop_element(ArrayStack *s, int *value) {
if (s->index <= 0) return 0;
*value = s->buffer[--s->index];
return 1;
}
Linked Stack Implementation
Dynamic allocation removes size restrictions. Each node holds data and a reference to the subsequent node.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next_ptr;
} Node;
int show_options(void);
int push_node(Node **head, int value);
int pop_node(Node **head, int *value);
int main(void) {
int input_val, status;
Node *head = NULL;
while (1) {
switch (show_options()) {
case 1:
printf("Enter value to push: ");
scanf("%d", &input_val);
status = push_node(&head, input_val);
printf(status ? "Push successful.\n" : "Push failed.\n");
break;
case 2:
status = pop_node(&head, &input_val);
if (status)
printf("Pop successful. Value: %d\n", input_val);
else
printf("Pop failed: Stack empty.\n");
break;
case 3:
printf("Exiting program.\n");
while (pop_node(&head, &input_val));
return 0;
default:
printf("Invalid selection.\n");
}
}
}
int show_options(void) {
int choice;
printf("\nSelect Operation:\n");
printf("1. Push\n");
printf("2. Pop\n");
printf("3. Exit\n");
scanf("%d", &choice);
return (choice >= 1 && choice <= 3) ? choice : 0;
}
int push_node(Node **head, int value) {
Node *new_node = (Node *)malloc(sizeof(Node));
if (!new_node) return 0;
new_node->data = value;
new_node->next_ptr = *head;
*head = new_node;
return 1;
}
int pop_node(Node **head, int *value) {
if (*head == NULL) return 0;
Node *temp = *head;
*value = temp->data;
*head = temp->next_ptr;
free(temp);
return 1;
}
Queue Overview
A queue follows the First-In, First-Out (FIFO) pirnciple. Insertions occur at the rear, and deletions occur at the front. Like the stack, it is a restricted linear list, but the ends for operation are distinct.