MODULE_2_DSC
MODULE_2_DSC
The program allocates memory for the data and address is passed to the stack ADT.
The head node and the data nodes are encapsulated in the ADT. The calling function can only see the
pointer to the stack.
The stack head structure also contains a pointer to top and count of number of entries currently in
stack.
Recursion in C programming involves a function calling itself to solve a smaller part of the problem
until a base condition is met. This process uses the system stack in several key ways:
• Function Calls and the Stack: Each time a recursive function is called, a new instance of that
function is placed on the stack. This instance contains the function’s local variables and the
return address.
• Working with the Stack Frame:
Creating a Stack Frame: A stack frame is created when a function is called. This frame
stores the function’s local variables and the return address.
Stack Frame for Each Recursive Call: Each recursive call creates its own stack frame
on top of the previous one. This is essential for the function to remember its state
and variables for each call.
Base Case: This is a condition in the recursive function that does not make a
recursive call. Reaching the base case is crucial to stop the recursion.
Unwinding the Stack: Once the base case is reached, the function starts returning,
and its stack frames are popped off the stack. This unwinding continues until the
original call is reached and the stack is empty.
• Memory Considerations:
Stack Overflow: If the recursive calls are too deep or the base case is not properly
defined, it can lead to a stack overflow, where the stack space allocated for the
program is exhausted.
Optimization: Tail recursion, where the recursive call is the last operation in the
function, can be optimized by compilers to reuse stack frames, thus saving memory.
typedef struct {
int *array;
int top;
int capacity;
} Stack;
Stack* create_stack() {
Stack* stack = (Stack*)malloc(sizeof(Stack));
stack->array = (int*)malloc(INIT* sizeof(int));
stack->top = -1; // Empty stack
stack->capacity = INIT;
return stack;
}
void resize(Stack* stack) {
stack->capacity *= 2;
stack->array = (int*)realloc(stack->array, stack->capacity * sizeof(int));
}
void push(Stack* stack, int value) {
if (stack->top == stack->capacity - 1) {
resize(stack); // Resize the array if it's full
}
stack->array[++stack->top] = value;
}
int pop(Stack* stack) {
if (stack->top == -1) {
printf("Stack underflow!\n");
exit(EXIT_FAILURE);
}
return stack->array[stack->top--];
}
int is_empty(Stack* stack) {
return stack->top == -1;
}
int peek(Stack* stack) {
if (stack->top == -1) {
printf("Stack is empty!\n");
exit(EXIT_FAILURE);
}
return stack->array[stack->top];
}
void free_stack(Stack* stack) {
free(stack->array);
free(stack);
}
int main() {
Stack* stack = create_stack();
push(stack, 10);
push(stack, 20);
push(stack, 30);
printf("Top element: %d\n", peek(stack));
printf("Popped element: %d\n", pop(stack));
printf("Popped element: %d\n", pop(stack));
printf("Is stack empty? %s\n", is_empty(stack) ? "Yes" : "No");
printf("Popping the last element:\n");
pop(stack);
printf("Is stack empty? %s\n", is_empty(stack) ? "Yes" : "No");
free_stack(stack);
return 0;
}
Output:
Top element: 30
Popped element: 30
Popped element: 20
Is stack empty? No
Popping the last element:
Is stack empty? Yes