#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node* next;
}
node;
int main(void){
node* list = NULL;
node *n = malloc(sizeof(node));
if(n==NULL){
return 1;
}
n->number = 2;
n-> next = NULL;
list = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list);
return 1;
}
n->number = 3;
n->next = NULL;
list->next = n;
n = malloc(sizeof(node));
if(n == NULL){
free(list->next);
free(list);
}
n->number = 4;
n->next = NULL;
list->next->next =n;
n = malloc(sizeof(node));
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
for( node* tmp = list; tmp != NULL; tmp->next){
printf("%i\n" , tmp->number);
}
while(list!=NULL){
node*tmp = list->next;
free(list);
list=tmp;
}
}
was trying linked list.
expected when running the code:
0
1
2
3
4
$
//asdoihasidashiofdhiohdfgdiwheifiopioioiophfaifjasklfhafiashfauiosfhwuiohwefuiowhfaslfidasdaskdasjdlaksdjqwfiqpweiojfkldfjsdfklwhefiowefweopfiosfkosid;fjwdfp;fdasiopfjew[0fowejfwepfojmofejmiwrfgj;wdfjewio;fijwefjsdp;jfkl;wjw
Actually you are not changing the pointer
for( node* tmp = list; tmp != NULL; tmp->next){
You need to write
for( node* tmp = list; tmp != NULL; tmp = tmp->next){
It will be even better to write
for ( const node* tmp = list; tmp != NULL; tmp = tmp->next ){
because within the loop the list is not being changed.
Also in this code snippet
if(n!=NULL){
n->number = 0;
n->next = NULL;
n->next = list;
list = n;
}
the statement
n->next = NULL;
is redundant.
In this loop, tmp->next has no effect because you don't assign it to anything.
for (node* tmp = list; tmp != NULL; tmp->next) {
printf("%i\n", tmp->number);
}
You must do tmp = tmp->next:
for (node* tmp = list; tmp != NULL; tmp = tmp->next) {
// ^^^^^
printf("%i\n", tmp->number);
}
Also, you can't expect 1 to be in the output because you never create a node with that number. With the above change the program will therefore output:
0
2
3
4
Sidenote: Your program is full of repetition which makes it hard to find errors and it's also what makes it harder to see that you forgot to add the node with the number 1. If you instead make functions of the things that you do repeatedly it'll be much clearer. You can also make functions with descriptive names to make the whole program easier to read and maintain.
If your program was rewritten to make use of functions, it could look like below - and then it'll be very obvious that the node with the number 1 is missing.
#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node {
int number;
node* next;
};
node *create_node(int number, node *next) {
node *nn = malloc(sizeof *nn);
if(!nn) exit(1);
// assign values to the new node:
*nn = (node){.number = number,
.next = next};
return nn;
}
void insert_first(node **list, int number) {
*list = create_node(number, *list);
}
void insert_last(node **list, int number) {
// find the last "next" pointer (the one pointing at NULL):
while(*list) list = &(*list)->next;
// make the pointer pointing at NULL now point at the new node:
*list = create_node(number, NULL);
}
void free_all(node **list) {
for(node *tmp; *list; *list = tmp) {
tmp = (*list)->next;
free(*list);
}
}
void print_all(const node *list) {
for (; list; list = list->next) {
printf("%d\n", list->number);
}
}
int main(void) {
node* list = NULL;
insert_last(&list, 2);
insert_last(&list, 3);
insert_last(&list, 4);
insert_first(&list, 0);
print_all(list);
free_all(&list); // list == NULL after this
}
Related
I am just implementing circular linked list program but in this program i am having to face trouble, as you can see I am going to past code below, when I call insertAtLast and isertAtFirst function it's work fine but as soon as I call viewList function to view list item but it shows "there is no items" which I wrote inside if block for run when last is null but in this program I have already inserted two items before viewList call so I think last should not be null because I have already inserted item, I want to print all items of list by viewList function
#include <stdio.h>
#include <stdlib.h>`
#include <conio.h>
struct node {
int item;
struct node *next;
};
void insertAtFirst(struct node **last, int data) {
struct node *n, *t;
n = malloc(sizeof(struct node));
n->item = data;
t = *last;
if(*last == NULL) {
n->next = n;
t = n;
}
else {
n->next = t->next;
t->next = n;
}
}
void insertAtLast(struct node **last, int data) {
struct node *n, *t;
n = malloc(sizeof(struct node));
n->item = data;
t = *last;
if(*last == NULL) {
n->next = n;
t = n;
}
else {
n->next = t->next;
t->next = n;
t = n;
}
}
void viewList(struct node *last) {
struct node *start;
if(last == NULL)
printf("\n there is no items......");
else {
start = last->next;
while(start->next != last->next) {
printf("%d ", start->item);
start = start->next;
}
}
}
int main(){
struct node *last = NULL;
insertAtLast(&last, 3);
insertAtFirst(&last, 5);
viewList(last);
return 0;
}
You should use *last = n instead of t = n.
And that's because the latter just causes the variable t to point to n and that's it. But by doing *last = n you will at least insert a value in the list even if last == NULL I guess that would give the desired output.
For some reason, if I have a linked list that looks like 3->2->1->0, and I called deleteSecond(head), I get 3->1->0->0. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int data;
struct ListNode *next;
} *LinkedList;
int deleteSecond(LinkedList list) {
if (list == NULL || list->next == NULL)
return 0;
int val = list->next->data;
LinkedList second = list->next;
list->next = list->next->next;
free(second);
return val;
}
int main() {
LinkedList head = NULL;
head = malloc(sizeof(LinkedList));
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(LinkedList));
newNode->data = i;
newNode->next = head;
head = newNode;
}
LinkedList ptr = head;
for (int i = 0; i < 4; i++) {
printf("%d\n", ptr->data);
ptr = ptr->next;
}
printf("\n");
deleteSecond(head);
while (head != NULL) {
printf("%d\n", head->data);
head = head->next;
}
return 0;
}
I believe my deleteSecond function should be correct. I create a pointer to my second node, and then I make the head->next = head->next->next, and the I free the pointer to the second node. I don't know why I have two 0's at the end of the list.
You are creating an empty node head which is creating problem. Your last node should point to NULL. So initializing head = NULL is the correct one.
LinkedList head = NULL;
// head = malloc(sizeof(LinkedList));
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(LinkedList));
newNode->data = i;
newNode->next = head;
head = newNode;
}
head = malloc(sizeof(LinkedList));
This is wrong. Correct would be
head = malloc(sizeof(*head));
Then again same way it would be
LinkedList newNode = malloc(sizeof(*newNode));
Now let's see what you did here.
head's data or link attribute is never initialized. So you get undefined behavior accessing it.
This is the code you wanted to write if you want to allocate memory to head.
...
int main(void) {
LinkedList head = NULL;
head = malloc(sizeof(*head));
if( head == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
head->next = NULL;
head->data = 2017; // dummy data.
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
...
...
deleteSecond(head);
while (head != NULL) {
printf("%d\n", head->data); // prints 2017 also. But deletes the node that was in second position.
head = head->next;
}
return 0;
}
Here we have used one extra node for holding the dummy data. Yes! it's not needed. This dummy node is doing nothing significant other than providing an next link for the newNodes which is not needed if you just use head as LinkedList or struct LinkedNode* and allocates no memory to it. It suggests we can eliminate than and simply use the pointer to struct ListNode namely head.
Then the code will be simply like
LinkedList head = NULL;
for (int i = 0; i < 4; i++) {
LinkedList newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
There are couple of things you can consider
Don't hide pointers under typedef.
Do check the return value of malloc.
Do free the memory that you allocate after you are done working with it.
The code can be written this way also. It doesn't use the pointer under typedef and modularize the reusable codes.
#include <stdio.h>
#include <stdlib.h>
typedef struct ListNode {
int data;
struct ListNode *next;
} ListNode;
void freeMemList(ListNode *head){
ListNode *temp;
while(head!=NULL){
temp = head;
head = head->next;
free(temp);
}
}
int deleteSecond(ListNode * list) {
if (list == NULL || list->next == NULL)
return 0;
int val = list->next->data;
ListNode * second = list->next;
list->next = list->next->next;
free(second);
return val;
}
void printList(ListNode *head){
while (head != NULL) {
printf("%d\n", head->data);
head = head->next;
}
}
struct ListNode * addNodes(struct ListNode* head, int n){
for (size_t i = 0; i < n; i++) {
ListNode * newNode = malloc(sizeof(*newNode));
if( newNode == NULL){
fprintf(stderr, "%s\n","Error in malloc" );
exit(1);
}
newNode->data = i;
newNode->next = head;
head = newNode;
}
return head;
}
int main(void) {
ListNode * head = NULL;
head = addNodes(head,4);
printList(head);
printf("********\n");
int valDeleted = deleteSecond(head);
printf("%s %d\n","Value deleted ", valDeleted );
printList(head);
freeMemList(head);
return 0;
}
As at the last time, suppose we have doubly linked list of nodes
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int value;
struct Node* next;
struct Node* prev;
} Node;
typedef struct LinkedList {
Node *first;
Node *last;
} LinkedList;
void initList(LinkedList* l) {
l->first = NULL;
l->last = NULL;
}
and my task is to code search method, which should find a node with given value
Node* search(LinkedList *list, int value) { ... }
well, my attempt follows
Node* search(LinkedList *list, int value) {
Node *node = malloc(sizeof(Node));
if (node == NULL)
return NULL;
node->value = value;
node->prev = NULL;
node->next = list->first;
while((node->value != value) && (node->next != NULL)){
node->prev = node->next;
node->next = (node->next)->next;
}
return node;
}
according to the implemenatation tests (this is not my job :-)
void test_search_exist() {
printf("Test 3: ");
LinkedList l;
initList(&l);
Node n1, n2;
n1.value = 1;
n1.next = &n2;
n1.prev = NULL;
n2.value = 2;
n2.next = NULL;
n2.prev = &n1;
l.first = &n1;
l.last = &n2;
Node *i = search(&l, 2);
if (i == &n2) {
printf("OK\n");
}else{
printf("FAIL\n");
}
}
void test_search_not_exist(){
printf("Test 4: ");
LinkedList l;
initList(&l);
Node n1, n2;
n1.value = 1;
n1.next = &n2;
n1.prev = NULL;
n2.value = 2;
n2.next = NULL;
n2.prev = &n1;
l.first = &n1;
l.last = &n2;
Node *i = search(&l, 3);
if (i == NULL) {
printf("OK\n");
}else{
printf("FAIL\n");
}
}
my code breaks either for existing or non-existing nodes. So is there any logic mistake or whatever?
Firstly: Dont allocate within search. The data members already exist, since you created them ahead.
Secondly: Iterate through the list and check every node for it's value.
Node* search(LinkedList *list, int value)
{
Node *node = list->first;
Node *found = NULL;
while(node != NULL)
{
if(node->value == value)
{
found = node;
break;
}
node = node->next;
}
return found;
}
To be more specific with the error(s) you made:
You allocated a node then filled it with the pointers of the first node, but with the value you were searching for. Then you started to loop over the list with the condition to stop when node->value equals the value you were searching for. Since node->value was initialized with the value your were searching for, this comparison will always be false (since its the same), the loop will be terminated and you get a bad result.
Besides this, your original code would result in a memory leak, since you malloc a new node, but you dont free it.
I was tasked with implementing a merge sort algorithm on a list written in C/C++. I have the general idea down, wrote my code and have successfully compiled it. However, when I run it, it will begin fine but then hang on "prepared list, now starting sort" without giving any kind of error. I have tried to look through my code but I am at a complete loss as to what the issue could be. I am also pretty amateurish with debugging, so using gdb to the best of my abilities has lead me no where. Any advice or tips would be a tremendous help, thank you all!
#include <stdio.h>
#include <stdlib.h>
struct listnode
{
struct listnode *next;
int key;
};
//Finds length of listnode
int
findLength (struct listnode *a)
{
struct listnode *temp = a;
int i = 0;
while (temp != NULL)
{
i++;
temp = temp->next;
}
return i;
}
struct listnode *
sort (struct listnode *a)
{
// Scenario when listnode is NULL
if (findLength (a) <= 1)
return a;
//Find middle
int mid = findLength (a) / 2;
struct listnode *temp = a;
struct listnode *first = a;
struct listnode *second;
for (int i = 0; i < mid - 1; i++)
{
temp = a->next;
}
second = temp->next;
temp->next = NULL;
//Recursive calls to sort lists
first = sort (first);
second = sort (second);
if (first != NULL && second != NULL)
{
if (first->key < second->key)
{
a = first;
first = first->next;
}
else
{
a = second;
second = second->next;
}
}
struct listnode *head = a;
struct listnode *tail = a;
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail = first;
first = first->next;
tail = tail->next;
}
else
{
tail = second;
second = second->next;
tail = tail->next;
}
}
if (first == NULL)
{
while (second != NULL)
{
tail = second;
second = second->next;
tail = tail->next;
}
}
while (first != NULL)
{
tail = first;
first = first->next;
tail = tail->next;
}
return a;
}
Here is the test code provided, written in C:int
main (void)
{
long i;
struct listnode *node, *tmpnode, *space;
space = (struct listnode *) malloc (500000 * sizeof (struct listnode));
for (i = 0; i < 500000; i++)
{
(space + i)->key = 2 * ((17 * i) % 500000);
(space + i)->next = space + (i + 1);
}
(space + 499999)->next = NULL;
node = space;
printf ("\n prepared list, now starting sort\n");
node = sort (node);
printf ("\n checking sorted list\n");
for (i = 0; i < 500000; i++)
{
if (node == NULL)
{
printf ("List ended early\n");
exit (0);
}
if (node->key != 2 * i)
{
printf ("Node contains wrong value\n");
exit (0);
}
node = node->next;
}
printf ("Sort successful\n");
exit (0);
}
You're close, but with some silly errors. Check the append operations in the merge step. They're not doing what you think they are. And of course you meant temp = temp->next; in the splitting loop.
If gdb is overwhelming, adding printf's is a perfectly fine way to go about debugging code like this. Actually you want to write a list printing function and print the sublists at each level of recursion plus the results of the merge step. It's fun to watch. Just be neat and delete all that when you're done.
Here's code that works for reference:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
while (fst && snd) {
if (fst->key < snd->key) {
tail->next = fst;
tail = fst;
fst = fst->next;
} else {
tail->next = snd;
tail = snd;
snd = snd->next;
}
}
while (fst) {
tail->next = fst;
tail = fst;
fst = fst->next;
}
while (snd) {
tail->next = snd;
tail = snd;
snd = snd->next;
}
tail->next = NULL;
return rtn->next;
}
On my old MacBook this sorts 10 million random integers in a bit over 4 seconds, which doesn't seem too bad.
You can also put the append operation in a macro and make this quite concise:
struct listnode *sort(struct listnode *lst) {
if (!lst || !lst->next) return lst;
struct listnode *q = lst, *p = lst->next->next;
while (p && p->next) {
q = q->next;
p = p->next->next;
}
struct listnode *mid = q->next;
q->next = NULL;
struct listnode *fst = sort(lst), *snd = sort(mid);
struct listnode rtn[1], *tail = rtn;
#define APPEND(X) do { tail->next = X; tail = X; X = X->next; } while (0)
while (fst && snd) if (fst->key < snd->key) APPEND(fst); else APPEND(snd);
while (fst) APPEND(fst);
while (snd) APPEND(snd);
tail->next = NULL;
return rtn->next;
}
Does it have to be a top down merge sort? To get you started, here's a partial fix, didn't check for other stuff. The | if (first != NULL && second != NULL) | check isn't needed since the prior check for length <= 1 takes care of this, but it won't cause a problem.
while (first != NULL && second != NULL)
{
if (first->key < second->key)
{
tail->next = first;
tail = first;
first = first->next;
}
else
{
tail->next = second;
tail = second;
second = second->next;
}
}
if (first == NULL)
{
tail->next = second;
}
else
{
tail->next = first;
}
}
We have a problem with our LinkedList in C.
When I count how many nodes should be in the list, I always get 1
LL count: 1
This is the Add, count and get last element of the list code:
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
newNode = malloc(sizeof(LL));
if(newNode != DEF_NULL)
{
newNode->ID=-1;
newNode->TCB=-1;
newNode->next = DEF_NULL;
if(!head) head = newNode;
else tail->next = newNode;
}
}
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != DEF_NULL)
{
temp = temp->next;
}
return temp;
}
CPU_INT32U countLL(LL * head)
{
CPU_INT32U elements = 0;
LL * temp = head;
while(temp->next != DEF_NULL)
{
temp = temp->next;
elements++;
}
return elements;
}
It's called in this way:
addLL(list);
temp = countLL(list);
Debug_LOG("LL count: %i", temp);
where LL * list; is a global variable, and temp is in local scope.
I hope anyone can see where I went wrong
Greetings,
Sjaak and Gerrit
I see several issues in your code :
you should always protect your linked list operations by testing if the list pointer is valid (i.e. not null)
you cannot allocate a first item to an empty list due to the way you allocate the first new item : you change head but the modification won't be propagated outside of the function. You should pass a "pointer to a list pointer" (i.e. a LL**) that is equivalent to "the address of a LL*"; See how I call addLL() and how I have modified its prototype and the head assignment
if your list is only one block long, it won't be counted as you count only if there is a successor, see how I have modifed the order of the do / while condition
I propose the modified code that works for 1, 2 or any list length (I have just changed the CPU_INT32U to int to compile quickly with MinGW, I could have typedef'ined):
#include <stdio.h>
#define DEF_NULL 0
typedef struct tagL {
int ID;
int TCB;
struct tagL *next;
} LL;
void addLL(LL ** head);
LL * getLastNode(LL * head);
int countLL(LL * head);
void addLL(LL ** head)
{
LL *newNode;
LL *tail = getLastNode(*head);
newNode = malloc(sizeof(LL));
if(newNode != DEF_NULL)
{
newNode->ID=-1;
newNode->TCB=-1;
newNode->next = DEF_NULL;
if(!*head)
*head = newNode;
else
tail->next = newNode;
}
}
LL * getLastNode(LL * head)
{
LL *temp = head;
if (head){
while(temp->next != DEF_NULL)
{
temp = temp->next;
}
}
return temp;
}
int countLL(LL * head)
{
int elements = 0;
LL * temp = head;
if (head){
do {
temp = temp->next;
elements++;
} while(temp != DEF_NULL);
}
return elements;
}
int main(int argc, char *argv[]){
LL *list = 0;
printf("LL test\n");
addLL(&list);
printf("length = %d\n", countLL(list));
addLL(&list);
printf("length = %d\n", countLL(list));
addLL(&list);
printf("length = %d\n", countLL(list));
}
Output :
LL test
length = 1
length = 2
length = 3
On Windows nothing's wrong whit this function - strange ...
ideone also shows good output.
#include <stdio.h>
#include <stdlib.h>
typedef struct LL{
struct LL *next;
}LL;
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != NULL)
{
temp = temp->next;
}
return temp;
}
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
newNode = malloc(sizeof(LL));
if(newNode != NULL)
{
newNode->next = NULL;
if(!head) head = newNode;
else tail->next = newNode;
}
}
int countLL(LL * head)
{
int elements = 0;
LL * temp = head;
while(temp->next != NULL)
{
temp = temp->next;
elements++;
}
return elements;
}
int main() {
LL *h = malloc(sizeof(*h));
addLL(h);
addLL(h);
addLL(h);
printf("%d\n", countLL(h)); // prints 3 as expected
}
CPU_INT32U countLL(LL * head){CPU_INT32U elements = 0;LL * temp = head;while(temp->next != DEF_NULL){temp = temp->next;elements++;}return elements;}
in this function you are declaring elements variable as auto
so its storage gets deallocated as soon as function exits , as memory now free to allocate to different variable, so may be overwritten hence previous cvalue gets lost
so to avoid this please use static in declaring variable.....
as static variables memory gets deallocated only after execution of whole program
please try....
void addLL(LL * head)
{
LL *newNode;
LL *tail = getLastNode(head);
There is a problem here, if (the global) head happens to be NULL, it will be dereferenced by the getLastNode() function:
LL * getLastNode(LL * head)
{
LL *temp = head;
while(temp->next != DEF_NULL)
Here temp->next != ... will cause temp to be dereferenced. That would cause NULL pointer dereferences if temp happens to be NULL. (as in the call by the insert function. You could add an extra test (or use pointers to pointers which is cleaner):
while(temp && temp->next != DEF_NULL)
Update (to show that the pointer to pointer version is cleaner)
#include <stdlib.h>
#include <stdio.h>
#define DEF_NULL NULL
#define CPU_INT32U unsigned
typedef struct link {
struct link *next;
} LL;
LL *globhead=NULL;
LL **getTailPP(LL **ppHead);
CPU_INT32U countLL(LL * ptr);
void addLL(LL **ppHead);
void addLL(LL **ppHead)
{
ppHead = getTailPP(ppHead);
*ppHead = malloc(sizeof **ppHead);
if(*ppHead != DEF_NULL)
{
// newNode->ID=-1;
// newNode->TCB=-1;
(*ppHead)->next = DEF_NULL;
}
}
LL **getTailPP(LL **ppHead)
{
for( ; *ppHead; ppHead = &(*ppHead)->next ) {;}
return ppHead;
}
CPU_INT32U countLL(LL * ptr)
{
CPU_INT32U elements = 0;
for(; ptr != DEF_NULL; ptr=ptr->next) { elements++; }
return elements;
}
int main()
{
unsigned count;
addLL( &globhead);
count = countLL (globhead);
printf("count = %u\n", count);
addLL( &globhead);
count = countLL (globhead);
printf("count = %u\n", count);
return 0;
}