The last printf call (printf("%d\n", current->val);) will not be executed. After the 1st printf functions' results appear, I am given the error "program.exe has stopped working". I would appreciate some help.
#include <stdio.h>
typedef struct node
{
int val;
struct node * next;
} node_t;
void print_list(node_t * head);
void main()
{
node_t * head = NULL;
head = malloc(sizeof(node_t));
if (head == NULL)
return 1;
head->val = 3;
head->next = malloc(sizeof(node_t));
head->next->val = 2;
head->next->next = malloc(sizeof(node_t));
head->next->next->val = 3;
head->next->next->next = malloc(sizeof(node_t));
head->next->next->next->val = 18;
print_list(head);
head->next->next->next->next = malloc(sizeof(node_t));
head->next->next->next->next->val = 5556;
head->next->next->next->next->next = NULL;
node_t * current = head;
while (current->next != NULL)
{
current = current->next;
}
current->next = malloc(sizeof(node_t));
current->next->val = 32;
current->next->next = NULL;
printf("%d", current->next->val);
system("pause");
}
void print_list(node_t * head) {
node_t * current = head;
while (current != NULL) {
printf("%d\n", current->val);
current = current->next;
}
}
This won't go well:
head->next->next->next = malloc(sizeof(node_t));
head->next->next->next->val = 18;
print_list(head);
You never initialized head->next->next->next->next to NULL. Instead, use calloc, or explicitly set the value to NULL. Even better, write a function to create a new node so you never forget to initialize. Even better still, write a function to insert a node.
What about something like this:
node_t * create_node( int val ) {
node_t *node = malloc(sizeof(*node));
if( node ) {
node->val = val;
node->next = NULL;
}
return node;
}
node_t * insert_value( node_t *list, int value ) {
node_t *new_node = create_node( value );
if( !new_node ) {
return list;
} else if( list ) {
new_node->next = list->next;
list->next = new_node;
}
return new_node;
}
Then you can:
node_t *head = insert_value( NULL, 3 );
node_t *tail = head;
tail = insert_value( tail, 2 );
tail = insert_value( tail, 3 );
tail = insert_value( tail, 18 );
print_list( head );
A common approach for lists is to use a dummy head node, which you never print out. It only contains a next pointer which is the start of your list and you ignore the value. If you did this, then you could also use that insert_value function to insert a value before the first element of the list. You also get the benefit that head always manages your entire list and you never have to worry about it changing.
Related
I try to insert an Element in an empty single Linked List and print that.
The code looks like this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Node{
int val;
struct Node* next;
}ll;
void addElement(ll* List, int num){
ll* new = malloc(sizeof(ll));
if(new == NULL){
printf("NO MEMORY\n");
exit(0);
}
new->val = num;
new->next = NULL;
if(List == NULL){
List = new;
return;
}
ll* curr = List;
while(curr->next != NULL){
curr = curr->next;
}
curr->next = new;
}
void printElements(ll* List){
ll* curr = List;
while(curr != NULL){
printf("%i\n", curr->val);
curr = curr->next;
}
}
*int main(){
ll* list = NULL;
addElement(list, 20);
addElement(list, 30);
addElement(list, 19);
printElements(list);
return 0;*
}
Does anybody see my mistake? Because it only works if i already have an Element in my List and nothing will be printed.
The function deals with a copy of the value of the pointer to the head node used as the function argument.
void addElement(ll* List, int num){
So this statement
List = new;
does not change the value of the original pointer. It changes the value of the copy of the original pointer.
The function can be defined the following way
int addElement( ll **List, int num )
{
ll *new_node = malloc( sizeof( ll ) );
int success = new_node != NULL;
if ( success )
{
new_node->val = num;
new_node->next = NULL;
while ( *List != NULL ) List = &( *List )->next;
*List = new_node;
}
return success;
}
And the function is called like
ll* list = NULL;
addElement( &list, 20);
addElement( &list, 30);
addElement( &list, 19);
This is the code I tried writing down to add an element in a double linked list, that takes an index and a value and adds a new element to the original list.
It is taking index and value but just adds the elements I give like a stack.
node *add(node *head, int index, int val)
{
node *new = create(val);
node *temp = malloc(sizeof(node));
if (head == NULL)
{
head = new;
temp = head;
//printf(": %d",temp->data);
}
temp = head;
int i = 1;
while (i < (index - 1) && (temp->next != NULL))
{
i++;
temp = temp->next;
}
temp->next = new;
new->next = NULL;
new->prev = temp;
return head;
}
however this code(for a doubly linked list) just adds elements one after the other, disregarding the index passed.
My prof gave us a code for a singly linked list where he did something similar.
struct Node *insert(struct Node *listp, int pos, int info)
{
/*Inserts a Node in list at position pos with data info
pos>0. If pos>list length then new node added at end.
If pos<1 adds at beginning.
*/
struct Node *new=malloc(sizeof(struct Node)), *prev;// new is the new node we create everytime.
//create new node and initialize fields
new->data=info;
new->next=NULL;
if (listp==NULL) listp=new;
else
if (pos<=1) { //negative or 1 index.
new->next=listp; //first node bann gaya new
listp=new; //head is pointing at new
}
else {
//pos>1. Go to node at pos-1.
prev=listp;
int i=1;
while ((i++<pos-1) && prev->next!=NULL) { //indexing
prev=prev->next;
}
new->next=prev->next;
prev->next=new;
}
return listp;
}
how do I address this problem?
To implement a doubly linked list, your node needs to have pointers to the previous node and next node, then you can write something almost as similar to what your professor gave you for single linked list:-
#include <stdlib.h>
#include <stdio.h>
//Doubly linked list Node
typedef struct Node{
int info;
struct Node* next;
struct Node* prev;
} Node;
Node* insert(Node* listp, int pos, int info){
//Allocate memory for node and its previous neighbor
Node* new = malloc(sizeof(Node));
Node* prev = malloc(sizeof(Node)), *tail;
//initialize new node with these values
new->info = info;
new->next = NULL;
new->prev = NULL;
//if head doesn't exist then create one
if(listp == NULL){
/*
listp gets whatever new had, ie
listp->info = info
listp->next = NULL
listp->prev = NULL
*/
Node* tail = malloc(sizeof(Node));
tail->info = 0;
tail->next = NULL;
tail->prev = NULL;
listp = new;
listp->next = tail;
tail->prev = listp;
}
//Lets Loop through the List and insert node at pos
else {
if(pos <= 1){
/*
This should replace the current head
listp = new
*/
new->next = listp;
new->prev = listp->prev;
listp->prev = new;
listp = new;
}
else{
int i = 2;
prev = listp->next;
printf("%d\n", prev->prev->info);
while(i != pos){
printf("%d\n", new->info);
prev = prev->next;
i++;
}
new->next = prev;
new->prev = prev->prev;
prev->prev->next = new;
prev->prev = new;
}
}
return listp;
}
// Test case
int main(){
Node* listp;
listp = insert(NULL, 0, 2);
listp = insert(listp, 1, 3);
listp = insert(listp, 2, 5);
Node* cnt = listp;
printf("|");
while(cnt->next != NULL){
printf("--%d-->", cnt->info);
cnt = cnt->next;
}
printf("\n");
}
Try that. Make any typo corrections if any
#include <stdio.h>
#include <stdlib.h>
/**
* add_node_end - adds a new node at the end of a dllist list
* #head: head of linked list
* #n: integer value of node
*
* Return: address of new element, NULL if fails
*/
node *add_node_end(node **head, const int n)
{
node *new, *temp;
new = malloc(sizeof(node));
if (new == NULL)
return (NULL);
new->n = n;
new->next = NULL;
if (*head == NULL)
{
new->prev = NULL;
*head = new;
return (*head);
}
temp = *head;
while (temp->next)
{
temp = temp->next;
}
temp->next = new;
new->prev = temp;
return (new);
}
/**
* add_dnodeint - adds a new node at the beginning of a dlistint_t list
* #head: head of linked list
* #n: integer value of node
*
* Return: address of new element, NULL if fails
*/
node *add_node_start(node **head, const int n)
{
node *new;
new = malloc(sizeof(node));
if (new == NULL)
return (NULL);
new->n = n;
new->prev = NULL;
if (*head == NULL)
{
new->next = NULL;
*head = new;
return (*head);
}
new->next = *head;
(*head)->prev = new;
*head = new;
return (*head);
}
/**
* node_len - returns the number of elements in a dllist list
* #h: head of doubly linked list
*
* Return: number of nodes
*/
size_t node_len(const node *h)
{
int count = 0;
while (h)
{
count++;
h = h->next;
}
return (count);
}
/**
* insert_dnodeint_at_index - inserts a new node at a given position
* #h: a pointer to a pointer of the first node of node linked list
* #index: the position to add the new node
* #val: the data n of the new node
* Return: if the function fails = NULL
* otherwise - the address of the new node/element
*/
node *insert_dnodeint_at_index(node **h, unsigned int index, int val)
{
node *newNode, *current;
size_t list_length;
unsigned int i = 0;
if (h == NULL)
return (NULL);
if (index == 0)
return (add_node_start(h, n));
list_length = node_len(*h);
if (index == (list_length - 1))
return (add_node_end(h, n));
newNode = malloc(sizeof(node));
if (newNode == NULL)
return (NULL);
newNode->val = val;
if (*h == NULL)
{
newNode->prev = NULL;
newNode->next = NULL;
return (newNode);
}
current = *h;
while (current)
{
if (i == index)
{
newNode->next = current;
newNode->prev = current->prev;
current->prev->next = newNode;
current->prev = newNode;
return (newNode);
}
current = current->next;
i++;
}
free(newNode);
return (NULL);
}
I have a linked list in which I am trying to free a char* which I used strdup for.
These are the methods I have for adding a node into my list:
node* add_first(char* name, node* head) {
node* new_node;
new_node = (node*)malloc(sizeof(node));
char* c = strdup(name);
new_node->name = c;
new_node->next = head;
head = new_node;
return head;
}
node * add_last(char* name, node *head ) {
node* new_node;
node* current;
new_node = (node*)malloc(sizeof(node));
char* c = strdup(name);
new_node->name = c;
new_node->next = NULL;
if ( head == NULL ){
head = new_node;
}
else{
current = head;
while ( current->next ) current = current->next;
current->next = new_node;
}
return head;
}
For removing nodes:
int remove_last( node **head, char **ret )
{
int result = *head == NULL ? -1 : 0;
if ( result == 0 )
{
while( ( *head )->next != NULL ) head = &( *head )->next;
*ret = strdup( ( *head )->name );
free( *head );
*head = NULL;
}
return result;
}
And for cleaning up the list:
void deleteList(node** head){
node* current = *head;
node* next;
while(current != NULL){
next = current->next;
free(current->name);
free(current);
current = next;
}
*head = NULL;
}
But valgrind says I have "definitely lost" memory when it comes to the strdup I have in my add_last function (but oddly not my add_first function).
Why is it only happening for the add_last method and how can I free it properly? I thought I was freeing all the nodes and the names in my deleteList method?
You are needlessly duplicating the string from the last-node removal algorithm, and leaking the original string. That algorithm should find the last node in the list, pass ownership of the name pointer to the out-param, then delete the node without deleting the name (since the out-param now owns it).
I.e. You should be doing something along these lines (fair warning, not compile-tested, but you hopefully get the idea):
int remove_last( node **head, char **ret )
{
int res = -1;
if (*head)
{
// find last node in the list
while ((*head)->next)
head = &(*head)->next;
// out-param takes ownership
*ret =(*head)->name;
// free last node *without* freeing the string
free(*head);
*head = NULL;
// result indicates success
res = 0;
}
return res;
}
Basically what title says, Im trying to append (add to end of my list). my BuildList function takes in a size parameter that determines how many nodes the list will have. my problem is with my append function. So if I have 5 as my head, how do I fix my append function so that random numbers will be added after 5?
typedef struct Node
{
int value;
struct Node* next;
} Node;
Node *createNode( int num )
{
Node *ptr;
ptr = (Node *) malloc( sizeof( Node ) );
ptr->value = num;
ptr->next = NULL;
return ptr;
}
Node* append (Node* head, Node* newNode)
{
if (head == NULL)
return newNode;
while (head -> next != NULL);
head -> next = newNode;
return head;
}
Node* buildList (int size)
{
Node* newNode = (Node*) malloc (sizeof(Node));
Node* head = NULL;
for (int i = 0; i < size; i++)
{
Node* newNode = createNode (rand () % 10);
head = append (head, newNode);
}
return head;
}
Well, the most glaring issue is this
while (head -> next != NULL);
I believe you meant to write something like this
Node *tmp = head;
while (tmp -> next != NULL) {
tmp = tmp->next;
}
tmp->next = newNode;
You don't want to modify head here since you return it later in the function. If you didn't use tmp, head would always point to the penultimate node in the list.
You just need to modify your while, why do you have an empty instruction there? If the head is not NULL then you will never exit:
while (head -> next != NULL)
{
head = head -> next;
}
The below is my code to recursive swap the adjacent elements of a linked list. I am losing the pointer to every second element after the swap.
The input is 1->2->3->4->5->6->7, I expected the output 2->1->4->3->6->5->7,
but my output is 1->3->5->7.
void nodelist::swap(node* head)
{
node* temp = head->next;
if (head->next!= nullptr)
{
node* temp2 = temp->next;
temp->next = head;
head->next = temp2;
head = head->next;
temp = nullptr;
temp2 = nullptr;
swap(head);
}
}
Any help would be appreciated,thanks in advance.
In fact it is enough to swap only the data members of nodes. There is no need to swap the pointers themselves.
Nevertheless if to use your approach then the function can look like
void SwapList( node *head )
{
if ( head != nullptr && head->next != nullptr )
{
node *next = head->next;
std::swap( *head, *next );
std::swap( head->next, next->next );
SwapList( head->next->next );
}
}
Here is a demonstrative program
#include <iostream>
#include <utility>
struct node
{
int value;
node *next;
};
node * AddNode( node *head, int value )
{
head = new node { value, head };
return head;
}
void PrintList( node *head )
{
for ( ; head != nullptr; head = head->next )
{
std::cout << head->value << ' ';
}
}
void SwapList( node *head )
{
if ( head != nullptr && head->next != nullptr )
{
node *next = head->next;
std::swap( *head, *next );
std::swap( head->next, next->next );
SwapList( head->next->next );
}
}
int main()
{
node *head = nullptr;
for ( int i = 10; i != 0; )
{
head = AddNode( head, --i );
}
PrintList( head );
std::cout << std::endl;
SwapList( head );
PrintList( head );
std::cout << std::endl;
return 0;
}
The output is
0 1 2 3 4 5 6 7 8 9
1 0 3 2 5 4 7 6 9 8
You can use the shown function as a template (or base) for your function.
With no recursion:
void swap(node **head)
{
while (*head && (*head)->next)
{
node* tmp = *head;
*head = tmp->next;
tmp->next = (*head)->next;
(*head)->next = tmp;
head = &tmp->next;
}
}
Invoke swap( & list_head_ptr).
Alternatively, you can pass the head pointer by reference-to-pointer and utilize a local pointer-to-pointer member:
void swap(node*& head)
{
node **pp = &head;
while (*pp && (*pp)->next)
{
node* tmp = *pp;
*pp = tmp->next;
tmp->next = (*pp)->next;
(*pp)->next = tmp;
pp = &tmp->next;
}
}
and invoke as swap(list_head_ptr). Either method works.
Using recursion:
void nodelist::swap(node** head) {
if (!*head || !(*head)->next) return;
node* const sw = (*head)->next;
(*head)->next = sw->next;
sw->next = *head;
*head = sw;
swap(&(sw->next->next));
}
If head is the pointer which stores the address of firstNode (value=1), then try following function:
void nodelist::swap(node* head){
node* temp = head->next; //head->next is first-node which needs to switch with it's next node
if (temp!= nullptr && temp->next!=nullptr){
head->next=temp->next; //move second node to first
temp->next = head->next->next; //put second's next in first's
head->next->next = temp; //and first will be second's next
temp = nullptr; // swaping done
swap(head->next->next); //do it for next couple
}
}
http://coliru.stacked-crooked.com/a/e1cc0d02b5599da4
OR
http://coliru.stacked-crooked.com/a/a1e200b687825d80
If head itself is the firstNode (value=1), then passing head by value will not work, either you need to pass it by address/reference OR do it like in following link:
http://coliru.stacked-crooked.com/a/a1e200b687825d80