I have more experience with linked lists after gaining practice and support from SO, given my last few questions. Essentially, I am now following an algorithm that will convert an array to a singly linked list.
Algorithm: CONVERT (A, N, HEAD)
1. Set HEAD = NULL
2. Repeat steps 3 to 8 while N ≠ -1
3. Allocated memory for NEW node
4. IF NEW = NULL then Print: “Memory not Available” and Return
5. Set NEW→DATA = A[N-1]
6. Set NEW→LINK = HEAD
7. Set HEAD = NEW
8. Set N = N - 1
[End of loop]
9. Return
I have attempted creating the code for this, however, after printing out the node carrying the data, I get a bunch of zeros. I know that with an array, if I assign a large size to the array and do not fill all values in, then these are assigned 0. However, this is not the case for my example.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int DATA;
struct node* LINK;
} node;
void convert(int A[], int N, node* head){
head = NULL;
while(N != -1){
node* new;
new = (node*)malloc(sizeof(node));
if (new == NULL){
printf("Memory not available");
return;
}
printf("%i", new->DATA);
new->DATA = A[N-1];
new->LINK = head;
head = new;
N--;
}
return;
}
int main(){
int arr[10] = {0, 1, 2, 3, 4};
int size = sizeof(arr)/sizeof(arr[0]);
node* former;
former = (node*)malloc(sizeof(node));
convert(arr, size, former);
return 0;
}
Would print out the following:
00000000000%
How do I convert the array values to the singly linked list, what might I be missing?
There are a few problems with your code:
You don't receive the created list head pointer back to main.
You print the data before you assign it and the printing will be inverted if you do during the creation of the list.
You don't free the allocated memory and create memory leaks.
Here is how to fix it:
Return the created list head pointer from the convert function.
Write a separate function for printing the list.
Write a function for freeing the memory of the list.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int DATA;
struct node *LINK;
} node;
node *convert(int A[], int N);
void printList(node *head);
void freeList(node *head);
node *convert(int A[], int N)
{
node *head = NULL;
for (int i = N - 1; i >= 0; i--)
{
node *new = malloc(sizeof(node));
if (new == NULL)
{
printf("Memory not available");
freeList(head); // free already allocated memory
return NULL;
}
new->DATA = A[i];
new->LINK = head;
head = new;
}
return head; // return the head pointer
}
void printList(node *head)
{
node *current = head;
while (current != NULL)
{
printf("%d ", current->DATA);
current = current->LINK;
}
}
void freeList(node *head)
{
node *current = head;
node *next = NULL;
while (current != NULL)
{
next = current->LINK;
free(current);
current = next;
}
}
int main()
{
int arr[5] = {0, 1, 2, 3, 4};
int size = sizeof(arr) / sizeof(arr[0]);
node *former = convert(arr, size);
printList(former);
freeList(former);
return 0;
}
Seems you are trying to print new->DATA value before you assign it's value. print it after assigning the value.
And head pointer is a local variable, so it's changes will not be reflected in Main() function. Change head pointer as follows inside Convert() function.
*head = NULL;
And your Main() function should be updated as follows,
int main(){
int arr[10] = {0, 1, 2, 3, 4};
int size = sizeof(arr)/sizeof(arr[0]);
node* head;
convert(arr, size, &head);
return 0;
}
updated:
Change your Convert() function as follows,
void convert(int A[], int N, node ** head) {
* head = NULL;
while (N != -1) {
node * new;
new = malloc(sizeof new[0]);
if (new == NULL) {
printf("Memory not available");
return;
}
new -> DATA = A[N - 1];
printf("%i", new -> DATA);
new -> LINK = * head;
* head = new;
N--;
}
return;
}
Split the problem into smaller bits. Use functions to program them.
typedef struct node {
int DATA;
struct node* LINK;
} node;
node *add(node *last, int data)
{
node *wrk = malloc(sizeof(*wrk));
if(wrk)
{
wrk -> DATA = data;
wrk -> LINK = NULL;
}
if(last) last -> LINK = wrk;
else last = wrk;
return wrk;
}
node *convert(int *data, size_t size)
{
node *head = NULL, *last;
if(data && size)
{
if((head = add(NULL, *data++)))
{
last = head;
while(--size)
{
if(!(last = add(last, *data++))) break;
}
}
}
return head;
}
void printList(const node *head)
{
while(head)
{
printf("%d\n", head -> DATA);
head = head -> LINK;
}
}
int main(void)
{
int arr[] = {9, 1, 2, 3, 4};
size_t size = sizeof(arr)/sizeof(arr[0]);
node *head = convert(arr, size);
printList(head);
return 0;
}
Related
I gotta write a function that takes the number from a given array and creates a linked list with them without allowing duplicates, my code works for adding the numbers but when I print the list I still get duplicate 4, it's like the function doesn't check if the number is already in the list and I can't find what's wrong.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} SNode;
typedef SNode *TNode;
void makeList(int arr[], int len, TNode *head);
void printList(TNode head);
void main() {
TNode head = NULL;
int array[5] = { 1, 2, 4, 4, 8 };
makeList(array, 5, &head);
printList(head);
}
void makeList(int arr[], int len, TNode *head) {
TNode tmp1, tmp2 = *head;
int i, j;
for (i = 0; i < len; i++) {
if (tmp2 == NULL) {
tmp1 = (TNode)malloc(sizeof(SNode));
tmp1->data = arr[i];
tmp1->next = *head;
*head = tmp1;
}
while (tmp2 != NULL) {
if (tmp2->data != arr[i]) {
tmp1 = (TNode)malloc(sizeof(SNode));
tmp1->data = arr[i];
tmp1->next = *head;
*head = tmp1;
}
tmp2 = tmp2->next;
}
}
}
void printList(TNode head) {
TNode tmp = head;
while (tmp != NULL) {
printf("%d ", tmp->data);
tmp = tmp->next;
}
}
Never ever hide pointers behind the typedefs. It is a very bad practice.
I do not think that you need great performance, you can traverse the linked list
Use the correct type for sizes
Use object not types in sizeofs
Split the problem into smaller tasks (functions)
void main is wrong.
Do not cast the result of the malloc. If the code does not compile it means that you compile it using a C++ compiler wich is not correct.
Avoid double pointers and side effects if possible. Use function return values (instead of void func)
typedef struct Node {
int data;
struct Node* next;
} SNode;
SNode *makeList (const int arr[], size_t len, SNode *head);
void printList (SNode *head);
int main(void)
{
SNode *head, *tmp;
int array[5] = {1,2,4,4,8};
int array2[5] = {6,2,4,7,9};
head = makeList (array, 5, NULL);
if(head) printList (head);
printf("-------------------------\n");
tmp = makeList (array2, 5, head);
if(tmp)
{
head = tmp;
printList (head);
}
/* free the list */
}
int isInList(const int val, const SNode *head)
{
int result = 0;
while(head)
{
if(head -> data == val)
{
result = 1;
break;
}
head = head -> next;
}
return result;
}
SNode *add(int val, SNode *last)
{
if(!last) last = malloc(sizeof(*last));
else
{
last -> next = malloc(sizeof(*last));
last = last -> next;
}
if(last)
{
last -> data = val;
last -> next = NULL;
}
return last;
}
SNode *findLast(const SNode *head)
{
if(head)
{
while(head -> next) head = head -> next;
}
return (SNode *)head;
}
SNode *makeList (const int arr[], size_t len, SNode *head)
{
SNode *last = findLast(head);
while(len--)
{
if(!isInList(*arr, head))
{
last = add(*arr, last);
if(!head) head = last;
if(!last) break;
}
arr++;
}
return head;
}
void printList(SNode *head)
{
while(head) {printf("%d\n", head -> data);head = head -> next;}
}
https://godbolt.org/z/1Wssf6Gz9
Below is a Minimal Reproducible Example from my code. What I am doing is that I am inserting data in a list of structs and printing them on the console.
I want to print from each link only the first element that is inserted into each list of structs.
But how is that possible when instead of data in my struct I have:
typedef struct Node
{
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
(rollnumber, src, dst,gentime are the information I am reading from text files, but the reading code is not nessacary, so I wrote it with testdata.)
MINIMAL REPRODUCIBLE EXAMPLE
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct Node
{
int data;
struct Node* next;
} Node;
int push_front(Node** head, int data)
{
Node* new_node = malloc(sizeof(Node));
int success = new_node != NULL;
if (success)
{
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
return success;
}
void output(Node* head)
{
for (Node* current = head; current != NULL; current = current->next)
{
printf("%d ", current->data);
}
}
void display(Node** set, int i)
{
output(set[i]);
putchar('\n');
}
int main(void)
{
int testdata = 1;
Node* link[N] = { 0 };
struct Node* head = NULL;
for (int i = 0; i < N; i++) {
push_front(&link[i], testdata++);
push_front(&link[i], testdata++);
}
for (int i = 0; i < N; i++) {
printf("link[%d]:", i);
display(link, i);
}
}
If you only want to print the first element of each link list, just do not loop in output:
void output(Node* head)
{
printf("%d ", head->data);
}
If I am right you want the first element of the list right ??
If so than the way you are working you are pushing the new node in front of old node, so your first node is now the last in the line, so all you need to do is to iterate the list till Node* next == null, and that node will be your answer
Node *getLastInLine( Node *Head){
Node *ptr;
ptr = Head;
if( ptr == NULL) return NULL;
while(ptr-> next != NULL){
ptr = ptr->next;
}
return ptr;
}
I'm quite new to C and am still coming to grips with a lot of the syntax and idiosyncrasies. I'm not exactly sure what needs changing in order to make my code work but am open to any ideas. I understand that I need to utilize pointers in order to make this work but I am still lost on the specific implementation. I keep getting an error that my myList function is undeclared but I feel like I have declared it already. Is there something I am missing about how C works? Any help would be appreciated
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
}node;
node*linkedList ();
int main ()
{
struct linkedList* myList = (struct createList*)malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList ()
{
node* head;
node* current;
node*next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search(int value)
{
int index = 0;
node searchNode = head;
while(searchNode.next!= NULL)
{
searchNode = searchNode.next;
index++;
if (node.value = data)
{
break;
}
else {
index = -1;
}
}
return index;
}
}
I will be simplifying the explanations, so the terms that I will use might not be the correct one.
Proper and consistent indentation would always make your code easier to read and to fix. There were missing semi-colons too, you should watch out for that.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node* head;
struct node* next;
} node;
node* linkedList();
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
myList.addNode(5);
myList.addNode(10);
myList.addNode(13);
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
}
node* linkedList()
{
node* head;
node* current;
node* next;
addNode (int x)
{
node keephead = head;
current = head;
while (current.next = NULL)
{
if (current.next = NULL)
{
current.next = node* newnode;
newnode.data = x;
newnode.next = NULL;
newnode.head = keephead;
}
if (head = NULL)
{
head = current;
}
}
}
int getSize ()
{
int counter = 0;
node countNodes = head;
while (countNodes.next != NULL)
{
countNodes = countNodes.next;
counter++;
}
return counter;
}
int search (int value)
{
int index = 0;
node searchNode = head;
while (searchNode.next != NULL)
{
searchNode = searchNode.next;
index++;
if(node.value = data)
{
break;
}
else
{
index = -1;
}
}
return index;
}
}
In main(), you should add the return 0; at the end of the function as it is an undefined behavior (AKA not a good thing to do). You could also change it to void main(), but it doesn't compile in clang.
printf("%d\n", myList.search(10));
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
You can't put a function within a function in C (nested functions). Put addNode(), getSize(), and search() outside the linkedList() function.
node* linkedList()
{
node* head;
node* current;
node* next;
}
addNode (int x)
{
node keephead = head;
...
}
int getSize ()
{
int counter = 0;
...
return counter;
}
int search (int value)
{
int index = 0;
...
return index;
}
linkedList() does literally nothing now and should be removed.
struct node* next;
} node;
int main()
{
struct linkedList* myList = (struct createList*) malloc(sizeof(struct node));
...
printf("The linked list is this big: %d\n", myList.getSize);
return 0;
}
void addNode (int x)
{
node keephead = head;
In main(), myList is the head of the currently empty linked-list, so it should be initialized to NULL. There's no linkedList data type, only node. Change it to:
node* myList = NULL;
You seem to be applying addNode(), getSize(), and search() to a variable, but C doesn't have that feature (C++ have it though). Add the linked-list head as an argument instead. addNode() needs the & address operator since it will be changing where the head starts.
addNode(&myList, 5);
addNode(&myList, 10);
addNode(&myList, 13);
printf("%d\n", search(myList, 10));
printf("The linked list is this big: %d\n", getSize(myList));
Update the function parameters of addNode(). In the while condition current.next = NULL and if statements, you were using an assignment operator instead of a comparison operator != or ==. You used the variables current and newnode, but never declared it anywhere in the function. There were lots of logic errors here. Change it to:
void addNode (node** head, int x)
{
node* current = *head;
node* newnode = malloc(sizeof(node));
newnode->data = x;
newnode->head = *head;
newnode->next = NULL;
if (*head == NULL)
*head = newnode;
else
{
while (current->next != NULL)
current = current->next;
//current is now the last node of linked list
current->next = newnode;
}
}
Do the same for the function parameters of getSize() and search(). Use node * instead for countNodes and searchNode. -> is the operator for accessing the members of a struct pointer. if statement should be put before it goes to the next node, as it would always skip the first node if left as it is. index should be put before the if statement so the index would update before it breaks out of the loop.
int getSize (node* head)
{
int counter = 0;
node* countNodes = head;
while (countNodes != NULL)
{
countNodes = countNodes->next;
counter++;
}
return counter;
}
int search (node* head, int value)
{
int index = 0;
node* searchNode = head;
while (searchNode != NULL)
{
index++;
if(searchNode->data == value)
break;
searchNode = searchNode->next;
}
if(searchNode->data != value)
index = -1;
return index;
}
Add the function prototypes before main().
void addNode (node** head, int x);
int getSize (node* head);
int search (node* head, int value);
int main()
{
node* myList = NULL;
Everything should work properly now.
I was given an simple assignment that deals with doubly linked lists, dynamic data allocation, and recursion. I created an array of just 10 integers and I am trying to put these integers into a sorted doubly linked list using recursion. I am having some trouble with inserting nodes into the linked list; my output is "2 7 9 100" and is missing the other 6 integers for some reason. What am I doing wrong? Thank you for any help! (The language used is C)
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct node_ {
int value;
struct node_ *next;
struct node_ *prev;
} node;
void insert(node **head, node *cur, node *p);
void print_list(node *cur);
void print_list(node *cur)
{
if (!cur) {
printf("\n");
return;
} else {
printf("%d ", cur->value);
print_list(cur->next);
}
}
int main(int argc, char *argv[])
{
int i;
int data[N] = {2, 7, 3, 9, 4, 4, 0, 8, 7, 100};
node *p, *head;
head = NULL;
for (i = 0; i < N; i++) {
p = (node *)malloc(sizeof(node));
p->value = data[i];
insert(&head, head, p);
}
print_list(head);
}
void insert(node **head, node *cur, node *p)
{
if(*head == NULL)
{
p->next = p->prev = NULL;
*head = p;
return;
}
if(p->value < cur->value)
{
p->prev = cur->prev;
p->next = cur;
cur->prev = p;
if(cur->prev != NULL)
cur->prev->next = p;
else
*head = p;
return;
}
if(cur->next == NULL)
{
cur->next = p;
p->next = NULL;
p->prev = cur;
}
else
insert(head, cur->next, p);
}
I believe the problem is here:
cur->prev = p;
if(cur->prev != NULL)
That if is never going to be false since you already lost the value of cur->prev.
You need to save cur->prev into a temporary variable and use that in the if statement, or do the assignment after the if.
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;
}