How do I convert my depth-first traversal code using recursion to the one using stack? - recursion

My data structures and stack operations are defined like this.
typedef struct AdjListNode{
int dest;
struct AdjListNode* next;
int visited;
}AdjListNode;
typedef struct AdjList{
struct AdjListNode* head;
}AdjList;
typedef struct Graph{
int V;
struct AdjList* array;
}Graph;
typedef struct Stack{
int top;
char items[MAX];
}Stack;
void Push(struct Stack *s,float val){
if(s->top == MAX-1){
printf("Error: Stack overflow.");
exit(1);
}else{
s->items[++(s->top)]=val;
}
}
float Pop(struct Stack *s){
if(s->top == -1){
printf("Error: Stack underflow");
exit(1);
}else{
return(s->items[(s->top)--]);
}
}
int isFull(struct Stack* s){
return s->top == MAX-1;
}
int isEmpty(struct Stack* s){
return s->top == -1;
}
And this function checks if there is a path from p to q
void FindPath_DepthFirstSearch(Graph* graph, int p, int q) {
AdjListNode* node = graph->array[p].head;
node->visited = 1;
// printf("%d\n", p);
if(p == q){
printf("Path found!\n");
exit(1);
}
while(node){
if (!graph->array[node->dest].head->visited)
FindPath_DepthFirstSearch(graph, node->dest, q);
node = node->next;
}
printf("Path not found!\n");
exit(1);
}
I'm fairly new to learning data strctures. The code works perfectly when I use recursion but I got stuck for a long time when I tried to implement this using stack. Can anyone help me with this? Thanks!

The basic idea when converting from a recursive definition to a loop-based one is that you store the data that you normally store in local variables on a stack (LIFO) container. Instead of recursing, you push additional elements on the stack. The code then looks like this:
function algorithm(args):
stack = new FIFO
# push initial state (e.g. root node for DFS)
stack.push(args)
# process all elements
while stack.has_elements():
# retrieve topmost element from stack
e = stack.pop()
# do something with the current element
e.frobnicate()
# push additional elements onto the stack
if e.condition1():
stack.push(e.derived1())
if e.condition2():
stack.push(e.derived2())

Related

when to use to double pointers and pointers

// A C program to demonstrate linked list based implementation of queue
#include <stdio.h>
#include <stdlib.h>
struct QNode {
int key;
struct QNode* next;
};
struct Queue {
struct QNode *front, *rear;
};
struct QNode* newNode(int k)
{
struct QNode* temp = (struct QNode*)malloc(sizeof(struct QNode));
temp->key = k;
temp->next = NULL;
return temp;
}
struct Queue* createQueue()
{
struct Queue* q = (struct Queue*)malloc(sizeof(struct Queue));
q->front = q->rear = NULL;
return q;
}
void enQueue(struct Queue* q, int k)
{
struct QNode* temp = newNode(k);
if (q->rear == NULL) {
q->front = q->rear = temp;
return;
}
q->rear->next = temp;
q->rear = temp;
}
void deQueue(struct Queue* q)
{
if (q->front == NULL)
return;
struct QNode* temp = q->front;
q->front = q->front->next;
if (q->front == NULL)
q->rear = NULL;
free(temp);
}
int main()
{
struct Queue* q = createQueue();
enQueue(q, 10);
enQueue(q, 20);
deQueue(q);
deQueue(q);
enQueue(q, 30);
enQueue(q, 40);
enQueue(q, 50);
deQueue(q);
printf("Queue Front : %d \n", q->front->key);
printf("Queue Rear : %d", q->rear->key);
return 0;
}
The above code is from geeksforgeeks website.
in function calls they used pointer to struct,
in function definition they passed pointer to struct.
how it works, I thought we need to use double pointers , otherwise > it is pass by value instead of pass by reference.
the above code works fine, but i have doubt about it.
In main there is a variable q declared which is a pointer to a struct. The variable q is used as the function argument which means the function receives a pointer to the struct. The function can dereference the pointer and modify the struct. The variable q is technically passed by value because its value is a pointer and that's what the function receives. But you have to remember that q points to a struct that could be modified by the function.
Because this situation causes some confusion some people have tried to introduce new terminology like "pass by sharing" or "object sharing" to distinguish it from passing primitive values like an `int' by value.
If you had passed a pointer to a pointer then the function could have modified the variable q declared in main and changed it so it points to a completely different struct. That would be (technically) pass by reference because you are passing a reference to the variable.

why my my function is using call by value method?

I don't know why in last line it is printing data of first element instead of last element. I want explanation.
// A simple C program for traversal of a linked list
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// This function prints contents of linked list starting from
// the given node
void printList(struct Node* n)
{
while (n != NULL) {
printf(" %d ", n->data);
n = n->next;
}
}
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(head);
printf("%d",head->data);
return 0;
}
As the function is accepting pointers so it should be call by reference.
And in last loop of function when n pointer is equal to NULL.
But in last line of this code is printing data of first list of my linked list.
Actually what you are doing is not being done in the actual linked list, it not pass by reference
void printList(struct Node* n)
{
/* some code here */
}
void main()
{
/* all your code here */
printList(head);
}
so if you want to change the head in the actual linked list you will have to pass the address of the pointer head to the function
something like this
int append_list(node **head, int data)
{
while((*head)->next!=NULL)
{
(*head) = (*head)->next;
}
}
int main()
{
struct node *head = NULL;
/* add nodes */
print_list(&head);
}
so here is the modification in your code:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node* next;
};
// This function prints contents of linked list starting from
// the given node
void printList(struct Node** n)
{
while ((*n)->next != NULL) {
printf(" %d ", (*n)->data);
(*n) = (*n)->next;
}
}
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; // assign data in first node
head->next = second; // Link first node with second
second->data = 2; // assign data to second node
second->next = third;
third->data = 3; // assign data to third node
third->next = NULL;
printList(&head);
printf("%d",head->data);
return 0;
}
here the output will be
1 2 3
since you have used (*head) for the traversal you no longer have the access to your list and hence will get segmentation fault if you try to access
(*head)->next
But I would not suggest to do this since now you will not be able to deallocate the memory
There is no pass-by-reference in C, everything is pass-by-value. People use pointers to emulate pass-by-reference, and this works because you can use the passed-in pointer to get at the same underlying data item.
In other words, even though the passed-in pointer is a pass-by-value copy within the function, the fact that it has the same value as the original means that both point to the same thing.
However, if the thing you're trying to change is a pointer already, you need a pointer to a pointer to do this emulation.
I could give you the code to do this but, believe me, it's not want you want. It would mean that the list printing code would be destructive to the list itself, since the head would now point to NULL.
Here is some code instead which shows how to do something similar, one that uses this double-pointer method to change the pointer outside of the function:
#include <stdio.h>
#include <stdlib.h>
void allocateSomeMem(void **pPtr, size_t sz) {
*pPtr = malloc(sz);
}
int main(void) {
void *x = NULL;
printf("%p\n", x);
allocateSomeMem(&x, 42);
printf("%p\n", x);
}
You can see by the output that the pointer is being changed:
(nil)
0x55f9ce5f96b0
Now, obviously, you wouldn't do this for the simple example shown, it would be far easier just to return the new pointer and have it assigned to x. But this is just illustrative of the method to use.

Queue implementation throws incompatible pointer type error

I think I'm missing general concepts on structs and pointers. Hence, below code is producing 2 warnings/errors and I don't understand why.
Why is "queue->head = temp" producing following warning:
warning: assignment from incompatible pointer type [enabled by default]
Why is "queue->tail->next = temp" producing following error:
error: dereferencing pointer to incomplete type.
Note: The line "Node *temp = newNode(data)" does not throw any error/warnings so it's successful.
typedef struct {
int data;
struct Node *next;
} Node;
typedef struct {
struct Node *head;
struct Node *tail;
} Queue;
void enQueue(Queue *queue, int data)
{
// Create a new node
Node *temp = newNode(data);
// If queue is empty, then new node is both head and tail
if (queue->tail == NULL)
{
queue->head = temp;
queue->tail = temp;
return;
}
// Add the new node at the end of queue and change tail
queue->tail->next = temp;
queue->tail = temp;
}
How did you get this code to compile?
Your Node structure contains a pointer to another Node. In the way you declared your structure, the compiler does not know Node while parsing your structure definition. Hence, you must write:
1 typedef struct Node{
2 int data;
3 struct Node *next;
4 } Node;
In this way, the compiler knows how to handle your structure when parsing it. In line 3 it already knows that Nodeis structure. Since some of your code is missing, I created a minimal example that implements a super simple queue:
#include <stdlib.h>
#include <stdio.h>
#define MAX 5
typedef struct Node{
int data;
struct Node *next;
} Node;
typedef struct {
struct Node *head;
struct Node *tail;
} Queue;
Node* newNode(const int nodeData){
Node* tmp = malloc(sizeof(*tmp));
if (NULL == tmp){
printf("Could not allocate Node ... exiting");
exit(EXIT_FAILURE);
}
tmp->data = nodeData;
tmp->next = NULL;
return tmp;
}
void enQueue(Queue *queue, int data)
{
// Create a new node
Node *temp = newNode(data);
// If queue is empty, then new node is both head and tail
if (queue->tail == NULL)
{
printf("Queue is empty\n");
queue->head = temp;
queue->tail = temp;
return;
}
// Add the new node at the end of queue and change tail
queue->tail->next = temp;
queue->tail = temp;
}
void printQueue(Queue* q){
Node* tmp = q->head;
while (tmp != NULL){
printf("Value: %d\n", tmp->data);
tmp = tmp->next;
}
}
int main(void){
Queue q;
q.head = q.tail = NULL;
int i;
for (i = 0; i < MAX; ++i){
printf("%d is entered into the queue\n", i);
enQueue(&q, i);
}
printQueue(&q);
}

recursion in the memory in finding the height of a binary search tree

I am having a trouble understanding the recursion that is happening in the
memory of the code below. How does the stack behave during this operation?
typedef struct node
{
struct node *left;
int data;
struct node *right;
}node;
int findheight(node *root)
{
if(root==NULL)
return 0;
int left,right;
left=findheight(root->left);
right=findheight(root->right);
if(left<right)
return right+1;
else
return left+1;
}

Pointers to stack

I am sorry that I cannot support my question with some code (I didnt understand how to structure it so it would be accepted here), but I try anyway.
If I understand correctly, a struct that references a struct of same type would need to do this with contained pointer for reference. Can this pointer reference to allocated space on the stack (instead of the heap) without creating segmentation fault? -
how should this be declared?
Yes, you can use pointers to variables on the stack, but only when the method that provides that stack frame has not returned. For example this will work:
typedef struct
{
int a;
float b;
} s;
void printStruct(const s *s)
{
printf("a=%d, b=%f\n", s->a, s->b);
}
void test()
{
s s;
s.a = 12;
s.b = 34.5f;
printStruct(&s);
}
This will cause an error however, as the stack frame would have disappeared:
s *bad()
{
s s;
s.a = 12;
s.b = 34.5f;
return &s;
}
EDIT: Well I say it will cause an error, but while calling that code with:
int main()
{
test();
s *s = bad();
printStruct(s);
return 0;
}
I get a warning during compilation:
s.c:27:5: warning: function returns address of local variable [enabled by default]
and the program appears to work fine:
$ ./s
a=12, b=34.500000
a=12, b=34.500000
But it is, in fact, broken.
You didn't say what language you are working in, so assuming C for now from the wording of your question... the following code is perfectly valid:
typedef struct str_t_tag {
int foo;
int bar;
struct str_t_tag *pNext;
} str_t;
str_t str1;
str_t str2;
str1.pNext = &str2;
In this example both str1 and str2 are on the stack, but this would also work if either or both were on the heap. The only thing you need to be careful of is that stack variables will be zapped when they go out of scope, so if you had dynamically allocated str1 and passed it back out of a function, you would not want str1->pNext to point to something that was on the stack within that function.
In other words, DON'T DO THIS:
typedef struct str_t_tag {
int foo;
int bar;
struct str_t_tag *pNext;
} str_t;
str_t *func(void)
{
str_t *pStr1 = malloc(sizeof(*pStr1));
str_t str2;
pStr1->pNext = &str2;
return pStr1; /* NO!! pStr1->pNext will point to invalid memory after this */
}
Not sure if this is specifically a C/C++ question, but I'll give C/C++ code as example in anyway.
The only way you can declare it: (with minor variations)
typedef struct abc
{
struct abc *other;
} abc;
other can point to an object on the stack as follows:
abc a, b; // stack objects
b.other = &a;
This is not a question about scope, so I'll skip commenting on possible issues with doing the above.
If, however, you want to assign it to a dynamically created object, there's no way this object can be on the stack.
abc b;
b.other = malloc(sizeof(abc)); // on the heap

Resources