99 lines
3.6 KiB
C
99 lines
3.6 KiB
C
#include <stdlib.h>
|
|
#include "stack.h"
|
|
|
|
// Pushes data as pointer onto the stack.
|
|
// Parameters:
|
|
// - stack: pointer to the current top of the stack (can be NULL if stack is empty)
|
|
// - data: void pointer to the data to be pushed onto the stack
|
|
// Returns: pointer to the new top of the stack (the newly created node)
|
|
// Note: The function allocates memory for a new StackNode, sets its data pointer
|
|
// and links it to the previous top, making it the new top of the stack.
|
|
StackNode *push(StackNode *stack, void *data)
|
|
{
|
|
// Allocate memory for a new StackNode
|
|
StackNode *newNode = (StackNode *)malloc(sizeof(StackNode));
|
|
|
|
// Check if memory allocation was successful
|
|
if (newNode == NULL)
|
|
{
|
|
return NULL; // Return NULL if allocation failed
|
|
}
|
|
|
|
// Store the data pointer in the new node
|
|
newNode->data = data;
|
|
|
|
// Link the new node to the previous top of the stack
|
|
// If stack was NULL (empty), newNode->next will be NULL
|
|
// If stack was not NULL, newNode->next points to the old top
|
|
newNode->next = stack;
|
|
|
|
// Return the new node, which is now the new top of the stack
|
|
return newNode;
|
|
}
|
|
|
|
// Deletes the top element of the stack (latest added element) and releases its memory.
|
|
// Parameters:
|
|
// - stack: pointer to the current top of the stack
|
|
// Returns: pointer to the new top of the stack (the second element, or NULL if stack becomes empty)
|
|
// Note: This function only frees the StackNode structure itself. The caller is responsible
|
|
// for freeing the data that the node was pointing to, if that data was dynamically allocated.
|
|
StackNode *pop(StackNode *stack)
|
|
{
|
|
// Check if the stack is empty
|
|
if (stack == NULL)
|
|
{
|
|
return NULL; // Cannot pop from an empty stack
|
|
}
|
|
|
|
// Save a pointer to the next node (which will become the new top)
|
|
StackNode *newTop = stack->next;
|
|
|
|
// Free the memory of the current top node
|
|
// NOTE: We do NOT free stack->data here because the caller may still need it
|
|
// or may be responsible for freeing it themselves
|
|
free(stack);
|
|
|
|
// Return the new top of the stack (or NULL if the stack is now empty)
|
|
return newTop;
|
|
}
|
|
|
|
// Returns the data of the top element without removing it from the stack.
|
|
// Parameters:
|
|
// - stack: pointer to the current top of the stack
|
|
// Returns: void pointer to the data of the top element, or NULL if stack is empty
|
|
// Note: This is a "peek" operation - it looks at the top without removing it.
|
|
void *top(StackNode *stack)
|
|
{
|
|
// Check if the stack is empty
|
|
if (stack == NULL)
|
|
{
|
|
return NULL; // Return NULL if stack is empty
|
|
}
|
|
|
|
// Return the data pointer stored in the top node
|
|
// The caller can then use this pointer to access the actual data
|
|
return stack->data;
|
|
}
|
|
|
|
// Clears the entire stack and releases all memory used by the StackNodes.
|
|
// Parameters:
|
|
// - stack: pointer to the current top of the stack
|
|
// Returns: void
|
|
// Note: This function only frees the StackNode structures. The caller is responsible
|
|
// for freeing any dynamically allocated data that the nodes were pointing to,
|
|
// unless that is done elsewhere in the program before calling clearStack.
|
|
void clearStack(StackNode *stack)
|
|
{
|
|
// Base case: if the stack is NULL (empty), we're done
|
|
if (stack == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Recursive case: first, recursively clear all the nodes below this one
|
|
// This processes the stack from top to bottom
|
|
clearStack(stack->next);
|
|
|
|
// After recursively clearing all deeper nodes, free the current node
|
|
free(stack);
|
|
} |