Linked List Stack in C - c

I am looking at the following paragraph in the book "Programming Interviews Exposed" in reference to the implementation of a linked list stack in C:
typedef struct Element {
struct Element *next;
void *data;
} Element;
void push( Element *stack, void *data );
void *pop( Element *stack );
Now consider what will happen in these routines in terms of proper
functionality and error handling. Both operations change the first
element of the list. The calling routine’s stack pointer must be
modified to reflect this change, but any change you make to the
pointer that is passed to these functions won’t be propagated back to
the calling routine. You can solve this problem by having both
routines take a pointer to a pointer to the stack. This way, you can
change the calling routine’s pointer so that it continues to point at
the first element of the list. Implementing this change results in the
following:
void push( Element **stack, void *data );
void *pop( Element **stack);
Could someone explain, in different words, why we need to use a double pointer here? I'm a bit unsure about the explanation provided.

It is similar to the famous swap() function in C.
Case 1:
void swapFails(int x, int y) {
int temp = x;
x = y;
y = temp;
}
Case 2:
void swapOk(int *x, int *y) {
int temp = *x;
*x = *y;
*y = temp;
}
and we invoke swap like this:
int x = 10;
int y = 20;
Case 1:
swapFails(x, y);
Case 2:
swapOk(&x, &y);
Remember, we wanted to CHANGE the values of x and y. For CHANGING values of a datatype, we need pointers. Take this to the next level for pointers. For CHANGING values of a pointer, we would need double pointers.
For Stack using linked list:
If you push values 10, 20 and 30, they are stored like this:
top --- bottom
30 -> 20 -> 10
So you see every time you push or pop values from the stack, which is a linked list, the top or the first node of the linked list changes. Hence you need double pointers.

The first version sends a copy of the pointer, if it's changed inside the function then the local copy would only be changed, when the function returns to the caller the caller still has a pointer to the old address.
Element *stack =...
push (stack)
void push( Element *stack, void *data ) {
stack = ... // this changes the local pointer allocated on the function's stack
}
//call returns
stack //still points to old memory
The second version, however, passes a pointer to the stack pointer, so when that is changed, it changes the stack pointer in the calling function.

In C everything is passed by value, let's say that I have this function:
void foo(void* ptr)
{
ptr=NULL;
}
If you call this method in the main, the pointer that you pass will not be NULL (unless it wat already NULL).Because a copy of the pointer is made before passing it to the function.So if you want to modify it's value, you have to pass a double pointer:
void foo(void** ptr)
{
*ptr=NULL;
}
The same is valid for the stack, of which you want to modify the value.

With the single-pointer signature you can imagine using the code as follows
Element *myStack = NULL ;
.... bla bla bla ....
push(myStack, something);
Then in the push call you're telling the stack implementation where the old head element of the stack was, but there's no way for the implementation of push to tell you where the new head is. It cannot change your myStack variable, because parameter passing in C is always by value -- i.e., the push function get told what the value of myStack happens to be, but get no chance to change the caller's variable.
In order for things to work, you need to tell the push primitive the address of your local variable that it needs to change:
....
push(&myStack, something);
and since myStack itself has type Element *, a pointer to the myStack variable has type Element **.

Related

Insertion into a Linked list using double pointer in C

void insert(list **l, int x)
{
list *p;
p = malloc(sizeof(list));
p->item = x;
p->next = *l;
*l=p;
}
Why did we use double pointer? Could we have done the same thing using single pointer? I saw this example in the book "The Algorithm Design Manual" page 69 2nd Edition.
List is basically node, just for refernce.
Could we have done the same thing using single pointer?
You could have done that using a single pointer with a minor update.
Return the pointer that was allocated and make sure that the function call is changed appropriately.
list* insert(list *l, int x)
{
// list = *p
// What was that? That is not valid code.
list* p = malloc(sizeof(list));
p->item = x;
p->next = l;
return p;
}
and use it as
list* l = NULL;
l = insert(l, 10);
Parameters in C are passed by value. So in order to make some changes to a variable in a function, we have to tell that function the address of the variable. This enables it to change the value of the variable indirectly by writing data to the corresponding memory.
As a result, to modify an int, you have to pass an int *. In your case, to modify a list *(the type of p->next), you have to pass a list **.
using double pointer is justified here because in the function you insert node in the header of list, so the variable l will be changed with the new header *l=p;
*l->|node1|->|node2| //initial value
p->|nodeP| //after p = malloc(sizeof(list)); p->item = x;
p->|nodeP|->|node1|->|node2| //p->next = *l;
*l->|nodeP|->|node1|->|node2| //after *l=p
in this case function is called like this:
list *head;
insert(&head, 4);
For your question:
Could we have done the same thing using single pointer?
Yes, the function will look like this:
list *insert(list *l, int x)
{
list *p;
p = malloc(sizeof(list));
p->item = x;
p->next = l;
return p;
}
you can call function in this case like this:
list *head;
head = insert(head, 4);
Basically u might be calling the insert function using insert(&head,x);
Previously head would have stored the address of your first node in the
linked list and u give the address of the head node to l and to access the
address of a u need to dereference it once and to change its value u need to
dereference it twice.
and obviously u can do it without double pointers just giving the value of
head to l insert(head,x)....and in the function declaring insert(int *l,int
x)
suppose
address of a(first node)=123
value of head=123
address of head =456
l(storing address of head)=456
In order to get the address of the first node dereference once
*l=123
in order to change value or to go to the next node you dereference it twice
for visual satisfaction have a look at the diagram image i tried to figure
out for your better understanding.
----------
[Here's an diagram which will give you a clear idea abt how the double pointer
is working here][1]
[1]: http://i.stack.imgur.com/HQOaa.jpg
You need to use double pointer in this example because you would like to also change the starting node of your list. So basically when you're inserting a new element, you also want to make the node that contains it the first one of your list. If you pass only a single pointer(list *l) and you assign to it the newly created node (p), the changes (and by changes I mean the fact that it will be the first node of the list) would only be available inside your function, and would not be propagated outside it.
To make it more clear, if you're taking in a simple pointer (list *l) you're basically copying the address stored by the list* variable that's sitting outside your function, in the newly created pointer (the l parameter). So the l variable inside your function is a different pointer (a different location in memory compared to the pointer variable outside your function) containing the same address as the pointer outside the function. So that's why assigning the newly created element to this l single-pointer would only make the the newly inserted element the first only local (function scope).
Compared to the alternative method when you're taking in a double pointer (so list **l), what really happens is that by passing the outer pointer variable to the function, you're actually passing the address of the outside pointer, not to be confused with the address that the pointer is containing. (take care since you will have to call the function something like this: insert(&l, 2)). This way you will still have the address contained by the outer pointer by dereferencing it and using it as rvalue (p->next = *l) and at the same time you have the address of the outside variable, so when you're making *l = p (notice *l is used as lvalue here), you're actually dereferencing the double pointer and in consequence you will obtain the the address of the real variable (the outside one), assigning to it the newly created node. In other words you're actually setting the newly created node as the starting node but this time also outside the function.
Really hope this is not extremely confusing.

Usage of Pointer to Pointers

I was trying to write a pop function which pops a node from a linked list by using a pointer to the head pointer of the linked list
My code was:
struct stack{
char name;
int info;
struct stack *next;
};
typedef struct stack s;
The first POP Function which i wrote was (this is my first time using pointer to pointer)
1) s *pop(s **ps){
s **temp1;
*temp1=NULL;
*temp1=*ps;
*ps=(*ps)->next;
return *temp1;
}
rather this worked
2) s *pop(s **ps){
s *temp2=NULL;
temp2=*ps;
*ps=(*ps)->next;
return temp2;
}
I am getting a segmentation fault for 1,whats going wrong?,Is there a better way to do this?
I used the pointer to pointer method cos i have read pointers are passed by value so even if i change something in pop using temp variable the local change wont affect the actual one
To simplify the issue, let's illustrate using integers and pointers to integers instead of pointers and pointers to pointers:
First fragment:
int pop(int *ps){
int *temp1;
*temp1=0;
*temp1=*ps;
*ps=*ps + 1;
return *temp1;
}
Second fragment:
int pop(int *ps){
int temp1;
temp1=0;
temp1=*ps;
*ps=*ps + 1;
return temp1;
}
In your first code fragment, you are dereferencing an uninitialised pointer. When you try to access *temp1, you will receive an access violation because temp1 is uninitialised and probably points to NULL or some other invalid pointer. In the second fragment, we are not dereferencing it, only assigning to the memory location the compiler assigned to temp1.
The reason ps is a pointer to a pointer (or a pointer to an integer in our illustration) is because we want to change its value outside the function. Whoever calls the pop function will tell us at what location pop should write the new value. We do not have direct access to that variable so the caller needs to pass a pointer to it. Within the pop function, however, we don't need to use pointers to pointers because our local variable is accessible.
In this here:
s **temp1;
*temp1=NULL;
temp1 points nowhere since it is not initialized, but you write NULL to where it points.

Using a function call to implement a stack

I'm a little unclear on this part of C, since it's a bit unlike other languages I've used, but this may just be a dumb question. I'm trying to implement a stack. I have the node struct, it has the information I want to pass:
struct position{
int square[2];
int counter;
struct position *prev;
};
so in main, I declare and initialize the bottom node of the stack, set *prev to NULL, then declare the rest. My question is, what happens when I try to pass it to function pop? I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes? Or should I return the position and set that equal to a new position object in main? What if I decide to create several of these nodes in a function? Will they remain once the function closes?
Edit: mah reminded me of my followup question which is, if they don't exist outside of the function, should I use malloc to create the space in the memory for them?
The lifetime of your objects depend on where they're created; if you declare for example a structure within a block of code (where a block is everything inside { and its matching }), that structure is no longer valid once execution leaves the block. Pointers to that structure are only valid as long as the structure is valid.
For what you're describing, you want to dynamically allocate your structures, using either malloc() or a similar function. Dynamically allocated data will remain valid (assuming you do not overwrite it) until you free() the memory, or until your program terminates. Pointers to these areas of memory will remain valid for that same period of time.
Consider:
static struct position *topOfStack = NULL;
void push(struct position *node)
{
node->prev = topOfStack;
topOfStack = node;
}
struct position *pop()
{
struct position *popped = topOfStack;
if (topOfStack) topOfStack = topOfStack->pref;
return popped;
}
To use this, you can:
f() {
struct position *node = malloc(sizeof(*node));
/* ... fill in node details ... */
push(node);
}
Notice that I allocated the node dynamically. Had I just declared a struct position node;, I could legally call push(&node); but once my function left scope, the stack would have an invalid item in it (which would likely cause havoc).
what happens when I try to pass it to function pop?
it depends on your pop() function prototype. If the pop's function prototype should be:
struct position* pop(struct position* stack);
I can create a position object that points to this one and return that, but will it be pushed off the stack when the function closes?
your question is quite unclear, and it looks like a big misunderstanding of instance scoping in C. Basically, you have two ways to allocate variables, either on the stack or on the heap. The scoping you're talking about is stack instances scope.
What if I decide to create several of these nodes in a function? Will they remain once the function closes?
basically, if you use the stack, they will live as long as the scope they're declared in. In C, scope is defined by { and }. for example:
int main() {
struct position pos1;
struct position pos2;
struct position pos3;
pos3.prev = pos2;
pos2.prev = pos1;
pos1.prev = NULL;
pop(&pos3);
}
there you declare 3 variables, and associate them, and the pop function just resets the .prev link. But for a stack that kind of architecture is not really useful, because it is quite limited.
There you definitely need to push your instances in the heap, thus using malloc() and free():
// push() pseudocode:
// take stack, iterate over each prev until prev is NULL
// allocate prev with malloc() the same way as for "stack" in main()
// insert values in prev
void push(struct position* stack, int* value);
// pop() pseudocode:
// take stack, iterate over each prev until prev->prev is NULL,
// then keep prev->prev in a temporary variable
// set prev to NULL
// return temporary variable (former prev->prev)
struct position* pop(struct position* stack);
int main() {
int value[2];
struct position* stack = malloc(sizeof(struct position));
// value is what you want to push to the stack
value[0] = 42;
value[1] = 42;
push(stack, value);
value[0] = 2;
value[1] = 20;
push(stack, value);
struct position* pos;
pos = pop(stack);
// do something with pos->value
free(pos);
}
there you create a pointer to a node for which you allocate some memory in the heap. the push() function is allocating some new memory, assigning .prev for that new space to stack's address and populating that memory with the value. pop() should get to the value before the last one, reset its pointer to that value, and return that value.
Of course, I'm just giving concepts and ideas here, I'm leaving you get to the real implementation. One advice though, instead of using square that contains an array, use two separate values in your struct, that will make it simpler for a first implementation.

Why do we use double pointers while passing a Structure argument in C?

I was writing some C-code to implement basic Stack data structure operations like push,pop,etc.
I'm using the Linked List implementation of the stack.
In this implementation, every time I push a value into the stuck, I create a new node, and set it as the head node of my Linked List. So this involves changing the references of the head node.
void push(stack **t, int ele)
{
stack *new, *temp;
temp=*t;
new=(stack *)malloc(sizeof(stack));
if(new==NULL)
{
printf("\n stack overflow");
return;
}
new=(stack *)malloc(sizeof(stack));
new->val=ele;
new->next=*t;
*t=new;
}
If I were to write a similar code using single pointers, then it would be like this
void push(stack *t, int ele)
{
stack *new, *temp;
temp=t;
new=(stack *)malloc(sizeof(stack));
if(new==NULL)
{
printf("\n stack overflow");
return;
}
new=(stack *)malloc(sizeof(stack));
new->val=ele;
new->next=t;
t=new;
}
In the function, the head node(**t) appears on the RHS of assignment in all steps but this
*t=new;
Basically the first code assigns 'new' to the pointer of **t, that is *t, and the second code assigns 'new' to the pointer of *t, that is t.
Both seem to be requiring only the single pointer to the head node to be assigned as 'new', yet only the first code works, and second doesn't actually modify the head node value.
What is the explanation for this to happen? Why doesn't the second code work in a similar way to the first?
Because everything in C is passed by value. So, if you need to assign a new value to an argument to a function, you must add a level of indirection. if you don't you simply receive a local copy, so any value assigned to that copy will be visible only within the function itself.
On a side note, don't cast the return value of malloc in C. It is unnecessary, clutters you code, and can hide an error for compilers which allow default int.
On.. another side note, instead of writing something like:
new_stack = malloc(sizeof(stack));
Use this instead:
new_stack = malloc(sizeof(*new_stack));
Now you don't have a problem if the type of new_stack ever changes.
In case of single pointer say
int addInBeginning(int *s)
{
... // add a node in the beginning of the linked list
}
int main()
{
int *t;
... // make t point to a linked list say t ---> 1 -> 2 -> 3
f(t);
}
Initially, s and t point to the same list. But when we add a node in the beginning, s points to the new node while t still points to the node it was earlier pointing to. When push returns, the new node is inaccessible from t.
0 -> 1 -> 2 -> 3
^ ^
| |
s t
In case of double pointer, s will point to t which in turn points to the list. So all pointer manipulations happen on the original pointer t.
s ----> t ----> 0 -> 1 -> 2 -> 3

double pointer question in C (single pointer for next, but double pointer for prev)

In the code of table.h for mysql. There are the following code
typedef struct st_table_share
{
...
struct st_table_share * next, /* Link to unused shares */
**prev;
in the text book, we usally have
sometype *next, *prev;
but here it use **prev instead of *prev. What the reason to use double pointer for prev?
It's not pointing to the previous structure, as next is, it's pointing to the pointer that's pointing to this structure.
The benefit of doing this is that it can point to either the 'next' member of the preceding structure, or it can point to the actual head pointer itself - in the case where this is the first item in the list. This means that removing the item involves "*prev = next" in both cases - there's no special case for updating the head pointer.
The downside is that you can't (easily) use it to traverse the structure backwards; so it's really designed to optimize the case where you only care about traversing forwards, but want to easily remove an arbitrary node.
it is not a "double pointer" as you mention. rather it is referred to as "de-referencing".
int x = 10;
int* prev = &x;
*prev is the address of variable x.
now lets say you need to pass the address of the pointer variable prev to another function named foo which accepts an address of a pointer as its parameter (pointer to a pointer).
void function foo(int** ptr)
{
prinft("%p", ptr); //this would print the address of prev
printf("%p", *ptr); //this would print the value (the address of x) contained inside address contained inside ptr.
printf("%d", **ptr); //this would print the value (the value of x, 10) contained at the address(address of x) contained inside address (address of prev) contained inside ptr
}

Resources