My question is simple and answers too rare. I know how to add or remove a node but how do you copy one previous node's data to the following node? Basically with an array the easiest way to shift it is to copy to the last element the previous element and move up the array like so:
for (i = number_of_elements ; i > 0; i--)
tab[i] = tab[i-1];
Otherwise you would copy each element to the next and have the same data for each element which we don't want.
Then I can assign to tab[0] a new value.
But how to do that with a linked list? I know how to add a node to the beginning of the list:
struct node *node (struct node *head, int data)
{
struct node *new_node = malloc(sizeof(struct node));
new_node->data = data;
new_node->next = head;
// new_node->prev = ??
return new_node;
}
which I assign to my list pointer so that it adds to the left. But I can't go up a linked list. Since the pointer next leads to the next node. Do I have to add a prev pointer to each node? But to what should it point? Thank you for helping in any way or for your rebuke because I just can't think properly.
edit: My idea then is to do simply as follows:
for (current = head; current!= NULL; current=current -> next) ;
and from there:
for( ; current!= head; current = current -> prev)
current ->data = current -> prev -> data;
return head;
Something like this?
void Shift(node* Head) {
type PrevData = Head->Data;
Head = Head->Next;
while (Head) {
type Temp = Head->Data;
Head->Data = PrevData;
PrevData = Temp;
Head = Head->Next;
}
}
Related
we've given a task to reverse a singly linked list and for some reason i struggling with it
its reversing as it should ,but the head that should be the tail just disappears and i can't figure why, even after debugging
'''
void Reverse(struct node *head) {
struct node *last = NULL;
struct node *current = NULL;
struct node *temp = NULL;
current = head;
while (current->next != NULL) { //getting ptr to last item of the list
current = current->next;
last = current;
};
current = head; //resseting the current ptr back to the head of the list
while (current->next->next != NULL) { //getting the current ptr to one before the tail item
current = current->next;
};
temp = last;
while (last != head) {
if (current->next == last) {
last->next = current;
last = current;
current = head;
if (last == head) {
head->next = NULL;;
head->data = temp->data;
head->next = temp->next;
break;
};
};
};
};
'''
I can't completely follow the logic in your code. You find the last and the second last element, and I will assume that head is some dummy element that you always have (because otherwise, not checking if it is NULL is a problem). After that, I am not sure what happens. You "flip" the last two links if you are looking at the head you update it? (You don't need to set head->next to NULL before you update it two lines later; that doesn't do anything).
Did you want to move current from the head and down to the one before last somewhere in the loop? I think that would work, but you would get a quadratic time algorithm.
If we assume that head is a dummy, so it doesn't have any elements to worry about, and we just want its next pointer to point to the reversed links, you should be able to do something like this:
void reverse(struct node *head)
{
struct node *next = head->next;
head->next = 0;
while (next) {
struct node *next_next = next->next;
next->next = head->next;
head->next = next;
next = next_next;
}
}
In the while-loop you can think of the code as pushing next to the front of the list pointed to by head->next and popping it off the current list (by setting next to next_next. When you reach the end of the list, head->next points to all the links, in reversed order. (I haven't tested the code, but I belive it should work).
If head is not a dummy node, you have to handle the special case that it is NULL, and you have to move its value. It makes things trickier if you have to do the latter, especially if you want to use the list generically, where the user is allowed to allocate links, and you might not know what data is in them (beyond that they have a link embedded in them). I would go for having a dummy link if you can, it makes everything simpler, not just reversal.
Of course, with doubly-linked lists it gets simpler still:
#define swap_p(x,y) \
do { struct node *tmp = x; x = y; y = tmp; } while(0)
void reverse(node *dummy)
{
struct link *p = dummy;
do {
swap_p(p->prev, p->next);
p = p->prev;
} while (p != dummy);
}
but that might not be what you want.
Don't know if that helps, but I hope it does a little at least.
I'm following the tutorial over here to build a linked list. I can't get the "Adding an item to the beginning of the list (pushing to the list)" part to work.
My code:
node_t* prepend(node_t **head, int val) {
//create new node pointer
node_t *new_node = (node_t*) malloc(sizeof(node_t));
new_node->val = val;
new_node->next = *head; //set its next to existing head (pointer of pointer)
//update existing head to point to new node
*head = new_node;
return *head;
}
int my_first_ll() {
//define a local variable called head that will point to the first node
node_t *head = NULL;
head = (node_t*) malloc(sizeof(node_t));
//check for null pointer
if (head == NULL) {
return 1;
}
//note how because head is a pointer we're using -> rather than dot notation to access attributes
head->val = 1;
head->next = (node_t*) malloc(sizeof(node_t));
head->next->val = 2;
head->next->next = NULL; //last item should point to a NULL
head = prepend(head, 0);
print_list(head);
}
It prints:
Currently at node 0
Instead of
Currently at node 0
Currently at node 1
Currently at node 2
So it seems when I insert the new head I fail to link to the previous one - but I just can't figure out how.
I found a solution: instead of passing **head to prepend like they do in the tutorial, passing *head solves it. Thus the final code:
node_t* prepend(node_t *head, int val) {
//create new node pointer
node_t *new_node = (node_t*) malloc(sizeof(node_t));
new_node->val = val;
new_node->next = head; //set its next to existing head (pointer of pointer)
//update existing head to point to new node
head = new_node;
return head;
}
Could someone explain why one works and the other doesn't? And why did they use two stars in the tutorial? And if two stars is actually correct, then why is it failing for me?
You can pass **head to the function, so you basically pass a pointer to a pointer:
void prepend(node_t **head, int data){
node_t *new = malloc(sizeof(node_t));
//set data
new->data = data;
//set the next pointer of new to current head
new->next = *head;
//now set the newly created node to be the new head
*head = new;
}
But the you'd have to call the function like this:
int main()
{
node_t *head = NULL;
prepend(&head, 3);
prepend(&head, 6);
printlist(head);
deltelist(&head);
return 0;
}
And theres no reason to return the *head in your function because you basically change the head node you created in main.
So if I now print my list, it prints
6
3
And never forget to delete the list after you used it.
Hope this helped you :)
I need to implement a function that reverses a linked list but i don't know how to return a newly formed linked list as a result.
typedef struct node_t* Node;
struct node_t {
int n;
Node next;
};
// create a new node with value n
Node nodeCreate(int n)
{
Node node = malloc(sizeof(*node));
if (node == NULL) return NULL;
node->n = n;
node->next = NULL;
return node;
}
// reversing the linked list
Node reverseList(Node list)
{
if (list == NULL) return NULL;
Node current, prev, next;
current = rev_head;
prev = NULL;
while( current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
list = prev;
return list;
}
This is the code I have written so far.
How do I insert this reverse linked list into a different new linked list within the function reverseList it self?
You are juggling around your nodes on the original list, and modifying then in place - which means you have only one list, and modify its nodes.
If that is what you want, your code might work (as soon as you fix things like the rev_head variable that appears from nowhere) - and the new head of the list, which is on your prev variable: which means your code should just work.
(It is important that the typedef don't hide the pointer though, I'd suggest changing that.)
What you seem not to have understood quite well is that for this kind o structure, any node works as the head of a list - there is no "list" type, just "node" types - and if you happen to pick any node in the middle of a list, that will just represent a partial list, starting from that node as well. So when you change your previous "last" node to point to its previous "antecessor" as its "next", that is it: that node is now the head.
(The exception to this "node == list" equality is while the reversing algorithm is running - at that point you have nodes that point in one direction and nodes that point in another, and the extra "next" and "prev" variables provide the needed information to fix things. If this was production code, this part of the code would have to be protected in a thread-lock)
Otherwise, if you want to produce a reversed copy of the list, you will have to copy the old nodes along the way, and just fix where they are pointing.
#include <stdlib.h>
#include <string.h>
typedef struct node_t Node;
struct node_t {
int n;
Node next;
};
// create a new node with value n
Node *nodeCreate(int n) {
Node *node = malloc(sizeof(*node));
if (node == NULL) return NULL;
node->n = n;
node->next = NULL;
return node;
}
void nodeCopy(Node *node_dst, Node *node_src) {
if (node_src == NULL || node_dst == NULL || abs(node_dst - node_src) < sizeof(Node)) {
return
}
memcpy(node_dst, node_src, sizeof(Node));
}
// reversing the linked list
Node *reverseList(Node *list) {
Node *new_list, *prev;
if (list == NULL) return NULL;
new_list = nodeCreate(0);
nodeCopy(new_list, list);
new_list->next=NULL;
prev = new_list;
while(list->next != NULL) {
list = list->next;
new_list = nodeCreate(0);
nodeCopy(new_list, list);
new_list->next=prev;
prev = new_list;
}
return new_list;
}
You can simply create a new node for every node in the original list and set the link in opposite order. Code could be:
Node createReversedList(Node node) {
Node result = NULL;
while (node != NULL) {
Node n = nodeCreate(node->n);
n->next = result;
result = n;
node = node->next;
}
return result;
}
There is a simple way in which you can reverse linked list
You can simply create a new linked list and add each node at the start of linked list which will create same linked list in reverse order
Node* revList(Node *start){
Node *startRev=NULL,*temp,*newNode;
temp = start;
while (temp->next!=NULL){
newNode = (Node *) malloc (sizeof(Node));
//Code for copying data from temp to new node
if(startRev == NULL){
startRev = newNode;
}
else {
newNode->next = startRev;
startRev = newNode;
}
temp = temp->next;
}
return startRev;
}
I am rather new to C, and am working on copying a Linked List. It seg faults somewhere in the while loop, I think I am having some pointer troubles. Also, I'm not sure if I need to malloc each 'next' node. Do I? It makes sense for me to have to.
struct node* copyList() {
struct node* walker = head; // starting point to "walk" the list
struct node* temp;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = walker->data;
while( walker != NULL ){ // done when we reach the node pointing to NULL
walker = walker->next; // advance walker to the next node in the list
temp = temp->next;
temp = (struct node*)malloc(sizeof(struct node));
temp->data = walker->data;
}
return walker;
}
The node strut is as follows
struct node {
int data;
struct node* next;
};
Suppose you reach last node..
Now inside loop , you increment walker..so now walker = NULL..
so this statement gives an error temp->data = walker->data..
Also you are just creating nodes and copying data not connecting your new linked list..
You need to maintain new Head pointer to return at the end
Keep reference to previous node so that you can link it to current node
Update the pointers
Change it along the lines of this..
struct node* copyList() {
struct node* walker = head; // starting point to "walk" the list
struct node* newHead=NULL,temp,prev=NULL;
while( walker != NULL ){ // done when we reach the node pointing to NULL
temp = (struct node*)malloc(sizeof(struct node)); //create new node
temp->data = walker->data; //copy data
if(prev==NULL) //if its first node
newHead = temp; //new head pointer
else
prev->next = temp; //else link to previous node
prev = temp; //update pointers
walker = walker->next;
}
return newHead;
}
Just where do you expect the value of temp->next in your loop to come from?
Also, to get a bit more meta, you might be vastly better off using e.g. std::list in C++ rather than implementing your own data structures like this. Even for experienced engineers, such efforts are notoriously error-prone.
if i have a reference to an element in a linked list, how do i swap it with the next element, in c
here's a try,
Node* nRoot, *temp=pNode->next;
nRoot=pNode;
do{
nRoot->next = temp->next;
if(nRoot==pNode) pNode=temp;
temp->next = nRoot;
nRoot=nRoot->next;
}while(nRoot!=NULL)||temp!=NULL);
but it does not work
You can only do this if it double linked list. You need the previous pointer so that you can point it's next to the current's next.
However if you have these then you an do something like this:
Node* next = curr->next;
Nide* prev = curr->prev;
curr->prev = next;
curr->next = next->next;
curr->next->prev = curr;
next->prev = prev;
next->prev->next = next;
next->next = curr;
And the 2 are swapped.
Edit: Of course you can do this with a singly linked list but you do need to know the previous node so that you fix up its next pointer to point to the current's next.
If you have a reference to A and A->next is B, you can do this. I'm assuming they hold a Data* pointer, replace with whatever the data is. Don't actually swap the nodes, just swap the data in the nodes.
void push_forward(Node* curr)
{
Data* currData = curr->data;
curr->data = curr->next->data;
curr->next->data = currData;
}
For the record, I am not a C guy so this might be correct only in algorithm, but not in implementation. I welcome edits, fixes, suggestions, and constructive comments!
If there are no external pointers to the elements that you wish to swap, then you can just swap the data within the list nodes, rather than the nodes themselves, as pointed out in other answers.
If you have external pointers to the list nodes, then you should probably not mess with the node content, unless the rest of your program is find with node contents changing from under its feet.
You will have to swap the nodes, which means that you need to have a pointer to the node that precedes the ones that you need to swap. If you only have the head of the list, then the swap function could be something along these lines:
void swap(Node **list, Node *first) {
Node *i = *list;
Node *p = NULL;
while (i != NULL) {
if (i == first) {
Node *n = i->next;
/* No next node to swap with */
if (n == NULL)
break;
if (p != NULL) {
p->next = n;
} else {
*list = n;
}
i->next = n->next;
n->next = i;
break;
}
p = i;
i = i->next;
}
}