mirror of
https://github.com/TheAlgorithms/C
synced 2024-11-22 13:31:21 +03:00
251 lines
6.4 KiB
C
251 lines
6.4 KiB
C
|
/**
|
||
|
* @file
|
||
|
*
|
||
|
* @brief
|
||
|
* Dynamic [Stack](https://en.wikipedia.org/wiki/Stack_(abstract_data_type)),
|
||
|
* just like Dynamic Array, is a stack data structure whose the length or
|
||
|
* capacity (maximum number of elements that can be stored) increases or
|
||
|
* decreases in real time based on the operations (like insertion or deletion)
|
||
|
* performed on it.
|
||
|
*
|
||
|
* In this implementation, functions such as PUSH, POP, PEEK, show_capacity,
|
||
|
* isempty, and stack_size are coded to implement dynamic stack.
|
||
|
*
|
||
|
* @author [SahilK-027](https://github.com/SahilK-027)
|
||
|
*
|
||
|
*/
|
||
|
#include <assert.h> /// to verify assumptions made by the program and print a diagnostic message if this assumption is false.
|
||
|
#include <inttypes.h> /// to provide a set of integer types with universally consistent definitions that are operating system-independent
|
||
|
#include <stdio.h> /// for IO operations
|
||
|
#include <stdlib.h> /// for including functions involving memory allocation such as `malloc`
|
||
|
/**
|
||
|
* @brief DArrayStack Structure of stack.
|
||
|
*/
|
||
|
typedef struct DArrayStack
|
||
|
{
|
||
|
int capacity, top; ///< to store capacity and top of the stack
|
||
|
int *arrPtr; ///< array pointer
|
||
|
} DArrayStack;
|
||
|
|
||
|
/**
|
||
|
* @brief Create a Stack object
|
||
|
*
|
||
|
* @param cap Capacity of stack
|
||
|
* @return DArrayStack* Newly created stack object pointer
|
||
|
*/
|
||
|
DArrayStack *create_stack(int cap)
|
||
|
{
|
||
|
DArrayStack *ptr;
|
||
|
ptr = (DArrayStack *)malloc(sizeof(DArrayStack));
|
||
|
ptr->capacity = cap;
|
||
|
ptr->top = -1;
|
||
|
ptr->arrPtr = (int *)malloc(sizeof(int) * cap);
|
||
|
printf("\nStack of capacity %d is successfully created.\n", ptr->capacity);
|
||
|
return (ptr);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief As this is stack implementation using dynamic array this function will
|
||
|
* expand the size of the stack by twice as soon as the stack is full.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @param cap Capacity of stack
|
||
|
* @return DArrayStack*: Modified stack
|
||
|
*/
|
||
|
DArrayStack *double_array(DArrayStack *ptr, int cap)
|
||
|
{
|
||
|
int newCap = 2 * cap;
|
||
|
int *temp;
|
||
|
temp = (int *)malloc(sizeof(int) * newCap);
|
||
|
for (int i = 0; i < (ptr->top) + 1; i++)
|
||
|
{
|
||
|
temp[i] = ptr->arrPtr[i];
|
||
|
}
|
||
|
free(ptr->arrPtr);
|
||
|
ptr->arrPtr = temp;
|
||
|
ptr->capacity = newCap;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief As this is stack implementation using dynamic array this function will
|
||
|
* shrink the size of stack by twice as soon as the stack's capacity and size
|
||
|
* has significant difference.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @param cap Capacity of stack
|
||
|
* @return DArrayStack*: Modified stack
|
||
|
*/
|
||
|
DArrayStack *shrink_array(DArrayStack *ptr, int cap)
|
||
|
{
|
||
|
int newCap = cap / 2;
|
||
|
int *temp;
|
||
|
temp = (int *)malloc(sizeof(int) * newCap);
|
||
|
for (int i = 0; i < (ptr->top) + 1; i++)
|
||
|
{
|
||
|
temp[i] = ptr->arrPtr[i];
|
||
|
}
|
||
|
free(ptr->arrPtr);
|
||
|
ptr->arrPtr = temp;
|
||
|
ptr->capacity = newCap;
|
||
|
return ptr;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief The push function pushes the element onto the stack.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @param data Value to be pushed onto stack
|
||
|
* @return int Position of top pointer
|
||
|
*/
|
||
|
int push(DArrayStack *ptr, int data)
|
||
|
{
|
||
|
if (ptr->top == (ptr->capacity) - 1)
|
||
|
{
|
||
|
ptr = double_array(ptr, ptr->capacity);
|
||
|
ptr->top++;
|
||
|
ptr->arrPtr[ptr->top] = data;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
ptr->top++;
|
||
|
ptr->arrPtr[ptr->top] = data;
|
||
|
}
|
||
|
printf("Successfully pushed : %d\n", data);
|
||
|
return ptr->top;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief The pop function to pop an element from the stack.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @return int Popped value
|
||
|
*/
|
||
|
int pop(DArrayStack *ptr)
|
||
|
{
|
||
|
if (ptr->top == -1)
|
||
|
{
|
||
|
printf("Stack is empty UNDERFLOW \n");
|
||
|
return -1;
|
||
|
}
|
||
|
int ele = ptr->arrPtr[ptr->top];
|
||
|
ptr->arrPtr[ptr->top] = 0;
|
||
|
ptr->top = (ptr->top - 1);
|
||
|
if ((ptr->capacity) % 2 == 0)
|
||
|
{
|
||
|
if (ptr->top <= (ptr->capacity / 2) - 1)
|
||
|
{
|
||
|
ptr = shrink_array(ptr, ptr->capacity);
|
||
|
}
|
||
|
}
|
||
|
printf("Successfully popped: %d\n", ele);
|
||
|
return ele;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief To retrieve or fetch the first element of the Stack or the element
|
||
|
* present at the top of the Stack.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @return int Top of the stack
|
||
|
*/
|
||
|
int peek(DArrayStack *ptr)
|
||
|
{
|
||
|
if (ptr->top == -1)
|
||
|
{
|
||
|
printf("Stack is empty UNDERFLOW \n");
|
||
|
return -1;
|
||
|
}
|
||
|
return ptr->arrPtr[ptr->top];
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief To display the current capacity of the stack.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @return int Current capacity of the stack
|
||
|
*/
|
||
|
int show_capacity(DArrayStack *ptr) { return ptr->capacity; }
|
||
|
|
||
|
/**
|
||
|
* @brief The function is used to check whether the stack is empty or not and
|
||
|
* return true or false accordingly.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @return int returns 1 -> true OR returns 0 -> false
|
||
|
*/
|
||
|
int isempty(DArrayStack *ptr)
|
||
|
{
|
||
|
if (ptr->top == -1)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Used to get the size of the Stack or the number of elements present in
|
||
|
* the Stack.
|
||
|
*
|
||
|
* @param ptr Stack pointer
|
||
|
* @return int size of stack
|
||
|
*/
|
||
|
int stack_size(DArrayStack *ptr) { return ptr->top + 1; }
|
||
|
|
||
|
/**
|
||
|
* @brief Self-test implementations
|
||
|
* @returns void
|
||
|
*/
|
||
|
static void test()
|
||
|
{
|
||
|
DArrayStack *NewStack;
|
||
|
int capacity = 1;
|
||
|
NewStack = create_stack(capacity);
|
||
|
uint64_t arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
|
||
|
|
||
|
printf("\nTesting Empty stack: ");
|
||
|
assert(stack_size(NewStack) == 0);
|
||
|
assert(isempty(NewStack) == 1);
|
||
|
printf("Size of an empty stack is %d\n", stack_size(NewStack));
|
||
|
|
||
|
printf("\nTesting PUSH operation:\n");
|
||
|
for (int i = 0; i < 12; ++i)
|
||
|
{
|
||
|
int topVal = push(NewStack, arr[i]);
|
||
|
printf("Size: %d, Capacity: %d\n\n", stack_size(NewStack),
|
||
|
show_capacity(NewStack));
|
||
|
assert(topVal == i);
|
||
|
assert(peek(NewStack) == arr[i]);
|
||
|
assert(stack_size(NewStack) == i + 1);
|
||
|
assert(isempty(NewStack) == 0);
|
||
|
}
|
||
|
|
||
|
printf("\nTesting POP operation:\n");
|
||
|
for (int i = 11; i > -1; --i)
|
||
|
{
|
||
|
peek(NewStack);
|
||
|
assert(peek(NewStack) == arr[i]);
|
||
|
int ele = pop(NewStack);
|
||
|
assert(ele == arr[i]);
|
||
|
assert(stack_size(NewStack) == i);
|
||
|
}
|
||
|
|
||
|
printf("\nTesting Empty stack size: ");
|
||
|
assert(stack_size(NewStack) == 0);
|
||
|
assert(isempty(NewStack) == 1);
|
||
|
printf("Size of an empty stack is %d\n", stack_size(NewStack));
|
||
|
|
||
|
printf("\nTesting POP operation on empty stack: ");
|
||
|
assert(pop(NewStack) == -1);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @brief Main function
|
||
|
* @returns 0 on exit
|
||
|
*/
|
||
|
int main()
|
||
|
{
|
||
|
test(); // run self-test implementations
|
||
|
return 0;
|
||
|
}
|