Inserting a node in ascending order - c

I try to insert a node that contains a string to the linkedlist in ascending order. It works if the initial of first element is higher than other initials of strings. For example,
"Zeynep"
"Ceylan"
"Demir"
this way works fine.
However if the initial of first string is smaller than any initial of strings in the list, it prints nothing.
"Ali"
"Zeynep"
"Ceylan"
This corrupts.
I traced the code but couldnt find.
struct friendNode
{
char firstName[30];
char lastName[30];
char gender[1];
char birthYear[10];
struct friendNode *next;
};
struct friendRecord
{
struct friendNode *head;
struct friendNode *tail;
int size;
};
void insertFriend(struct friendNode *node, struct friendRecord *list)
{
struct friendNode *temp_node;
temp_node = list->head;
if(temp_node->next == NULL)
{
temp_node->next = node;
list->tail = node;
}
else
{
while(strcmp(node->firstName, temp_node->next->firstName) >= 0 )
temp_node = temp_node->next;
if(temp_node->next == NULL)
{
temp_node->next = node;
list->tail = node;
return;
}
node->next = temp_node->next;
temp_node->next = node;
}
}

Inserting into a linked list is pretty basic stuff. Here is one way to do it:
void insertFriend(struct friendNode *node, struct friendRecord *list)
{
struct friendNode *pre = NULL;
struct friendNode *post = list->head;
while (post && strcmp(node->firstName, post->firstName) >= 0)
{
pre = post;
post = post->next;
}
if (pre == NULL)
{
list->head = node;
}
else
{
pre->next = node;
}
node->next = post;
if (post == NULL)
{
list->tail = node;
}
}

void insertFriend(struct friendNode *node, struct friendRecord *list)
{
struct friendNode *temp_node;
temp_node = list->head;
if(strcmp(node->firstName, list->head->firstName) < 0)
{
node->next = list->head;
list->head = node;
}
if(temp_node->next == NULL)
{
temp_node->next = node;
list->tail = node;
}
else
{
while(strcmp(node->firstName, temp_node->next->firstName) >= 0 )
temp_node = temp_node->next;
if(temp_node->next == NULL)
{
temp_node->next = node;
list->tail = node;
return;
}
node->next = temp_node->next;
temp_node->next = node;
}
}
you forgot to write code to append the node at the head of list if it is going to be the first element. I have not tried because i dont have full code. try out. if still doesn't work, i request to comment.

Related

Implementing LinkedList in C

I implemented a linked list for my school assignment but when I try to print out value of a node, the first node always get printed with memory address and I can't figure out why it's happening. 
I tried debugging and as I assign tail of list to the new node, the value of the node gets printed out as memory address.
Why is this happening?
int AppendLinkedList(LinkedListPtr list, int value) {
LinkedListNodePtr newNode = CreateLinkedListNode(value);
if (list->head == NULL) {
list->head = newNode;
list->tail = newNode;
return 0;
}
LinkedListNodePtr tailCopy = list->tail;
newNode->prev = tailCopy;
tailCopy->next = newNode;
list->tail = newNode;
return 0;
}
LinkedListNode *CreateLinkedListNode(int data) {
LinkedListNodePtr newNode;
newNode = (LinkedListNodePtr)malloc(sizeof(LinkedListNode));
newNode->data = data;
printf("%d\n", data);
return newNode;
}
int main() {
LinkedListPtr list = CreateLinkedList();
int data = 5;
AppendLinkedList(list, data);
}
typedef struct ll_node {
int data; // Data this node holds
struct ll_node *next; // next node in list, or NULL
struct ll_node *prev; // prev node in list, or NULL
} LinkedListNode, *LinkedListNodePtr;
typedef struct ll_head {
uint64_t num_elements; // # elements in the list
LinkedListNodePtr head; // head of linked list, or NULL if empty
LinkedListNodePtr tail; // tail of linked list, or NULL if empty
} *LinkedListPtr;
LinkedListPtr CreateLinkedList() {
LinkedListPtr list;
list = (LinkedListPtr)malloc(sizeof(LinkedListPtr));
if (list == NULL) {
return NULL;
}
return list;
}
There are multiple problems in your code:
you do not initialize the prev and next members to NULL in CreateLinkedListNode().
the allocation size is incorrect in CreateLinkedList(): you should use:
LinkedList *list = malloc(sizeof(*list));
and you should initialize the members num_elements to 0 and head and tail to NULL.
the order of definitions is inadequate and the header files are missing.
AppendLinkedList() does not update num_elements.
More generally, hiding pointers behind typedefs is error prone. The code is much more readable with the explicit pointer syntax.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct ll_node {
int data; // Data this node holds
struct ll_node *next; // next node in list, or NULL
struct ll_node *prev; // prev node in list, or NULL
} LinkedListNode;
typedef struct ll_head {
uint64_t num_elements; // # elements in the list
LinkedListNode *head; // head of linked list, or NULL if empty
LinkedListNode *tail; // tail of linked list, or NULL if empty
} LinkedList;
LinkedList *CreateLinkedList() {
LinkedList *list = malloc(sizeof(*list));
if (list != NULL) {
list->num_elements = 0;
list->head = NULL;
list->tail = NULL;
}
return list;
}
LinkedListNode *CreateLinkedListNode(int data) {
LinkedListNode *newNode = malloc(sizeof(*newNode));
if (newNode != NULL) {
newNode->data = data;
newNode->prev = NULL;
newNode->next = NULL;
}
return newNode;
}
int AppendLinkedList(LinkedList *list, int value) {
if (list == NULL)
return -1;
LinkedListNode *newNode = CreateLinkedListNode(value);
if (newNode == NULL)
return -1;
if (list->head == NULL) {
list->head = newNode;
} else {
LinkedListNode *tail = list->tail;
newNode->prev = tail;
tail->next = newNode;
}
list->tail = newNode;
list->num_elements += 1;
return 0;
}
int main() {
LinkedList *list = CreateLinkedList();
int data = 5;
AppendLinkedList(list, data);
}

I want to delete node from singly linked list using only one local pointer variable, what error in this code section?

I want to delete node from singly linked list using only one local pointer variable in C, the debugger stops on the free(cur) of the delete function without any error, but it runs normally in free(cur->next), why is this? What error in this code section?
struct node
{
int val;
struct node *next;
};
typedef struct
{
struct node *header;
} List;
void add(List *pList, int val)
{
struct node *new_node = malloc(sizeof pList->header);
if (new_node == NULL)
{
exit(EXIT_FAILURE);
}
new_node->val = val;
new_node->next = pList->header;
pList->header = new_node;
}
void delete(List *pList, int val)
{
struct node *cur = pList->header;
if (cur != NULL)
{
if (cur->val == val)
{
struct node *temp = cur->next;
//debug stop in free(cur) without any error,why?
free(cur);
cur = temp;
}
else
{
while (cur->next != NULL && cur->next->val != val)
{
cur = cur->next;
}
if (cur->next != NULL)
{
struct node *temp = cur->next->next;
// run normally, why?
free(cur->next);
cur->next = temp;
}
}
}
}
There is a problem in the add function: you pass the size of a pointer to malloc instead of the size of the node structure. A safer way to always pass the correct size is this:
struct node *new_node = malloc(sizeof *new_node);
As coded, the memory allocated is too small and you have undefined behavior when you initialize the structure, writing beyond the end of the allocated block.
There is another problem in the delete() function: you do not update pList->header when you free the first node.
Here is a modified block:
struct node {
int val;
struct node *next;
};
typedef struct {
struct node *header;
} List;
void add(List *pList, int val) {
struct node *new_node = malloc(sizeof(*new_node));
if (new_node == NULL) {
exit(EXIT_FAILURE);
}
new_node->val = val;
new_node->next = pList->header;
pList->header = new_node;
}
void delete(List *pList, int val) {
struct node *cur = pList->header;
if (cur != NULL) {
if (cur->val == val) {
pList->header = cur->next;
free(cur);
} else {
while (cur->next != NULL) {
struct node *temp = cur->next;
if (temp->val == val) {
cur->next = temp->next;
free(temp);
break;
}
cur = temp;
}
}
}
}

What is the problem with this piece of code?

I am writing for deleting the last node of a doubly linked list. But, every time this function is giving me segmentation fault when I have 2 or more than 2 elements in the list.
void deleteEnd()
{
struct node *ptr;
if(head==NULL)
printf("\nList is empty.First add some numbers");
else if(head->next==NULL)
{
head = NULL;
free(head);
}
else
{
ptr = head;
while(ptr->next != NULL)
{
ptr = ptr -> next;
}
ptr -> prev -> next = NULL;
free(ptr);
}
}
Normally, when you are deleting a node from a linked list it is a good practice to pass a reference to the first node of the list as an argument of the function. In your case you are not showing us where the head is coming from, and I think that it could be quite a useful info, and I bet that the error hides there.
That is how the implementation could look like:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
// insert end node: this is for testing purposes
struct node *insertEnd(struct node *head, int value) {
struct node *ptr, *new_node;
ptr = head;
new_node = (struct node *) malloc(sizeof(struct node));
new_node->data = value;
new_node->next = NULL;
// The list is empty
if (head == NULL) {
head = new_node;
return head;
}
// Non empty list
while (ptr->next != NULL) {
ptr = ptr->next;
}
ptr->next = new_node;
return head;
}
// delete end node
struct node *deleteEnd(struct node *head) {
struct node *ptr, *preptr;
ptr = head;
preptr = NULL;
// The list is empty
if (head == NULL) {
printf("The list is empty. Nothing to delete.\n");
return head;
}
while(ptr->next != NULL) {
preptr = ptr;
ptr= ptr->next;
}
free(ptr);
if (preptr == NULL) {
head = NULL;
}
else {
preptr->next = NULL;
}
return head;
}
int main(void) {
struct node *llist;
llist = NULL;
llist = insertEnd(llist, 10);
llist = insertEnd(llist, 20);
llist = insertEnd(llist, 30);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
llist = deleteEnd(llist);
return 0;
}
It is always a great idea to maintain a global variable head and update it after every push/pop. See this:
struct node
{
int data;
struct node *next;
};
struct node *start = NULL;
struct node *deleteEnd(struct node *start)
{
struct node *ptr = start;
if(ptr==NULL)
{
printf("\nList is empty!!!");
return start;
}
else if(ptr->next == NULL)
{
free(ptr);
start = NULL;
return start;
}
else
{
while((ptr->next)->next!=NULL) //by doing this you dont have to maintain a prev pointer
{
ptr=ptr->next;
}
struct node *temp = ptr->next;
free(temp);
ptr->next = NULL;
return start;
}
}
Hope this helps!!!

Add function in a trie structure does not work properly

I'm trying to write a function to add words in a trie, and count the number of times it has been added. But it always returns 1.
Can anybody help me?
struct node
{
struct node* next;
struct node* child;
char data;
int value;
};
typedef struct node Node;
Node* getNode(char data)
{
Node* newptr;
newptr = calloc(1,sizeof(Node));
newptr->next = NULL;
newptr -> child = NULL;
newptr->data = data;
newptr -> value = 0;
return newptr;
}
Node* add(Node* parent,char* str)
{
Node* current;
current = parent->child;
while (current != NULL && current->data != str[0])
{
current = current->next;
}
if (current == NULL)
{
current = getNode(str[0]);
if (str[0] == 0)
{
current->value = 1;
return current;
}
return add(current,str + 1);
}
if (str[0] == 0)
{
(current->value)++;
return current;
}
return add(current,str+1);
}
cm: getNode() and Node definitions added!

Doubly Linked list not working properly, C

#include <stdio.h>
#include <stdlib.h>
typedef struct list_item {
int value;
struct list_item *next;
struct list_item *prev;
} list_item_t;
typedef struct single_list {
list_item_t *head;
list_item_t *tail;
} slist_t;
void init(slist_t *list) {
list->head = NULL;
list->tail = NULL;
}
void add(slist_t *list, int value) {
list_item_t *newNode = (list_item_t *)malloc(sizeof(list_item_t));
// Case for empty list
if (list->head == NULL) {
list->head = newNode;
list->tail = newNode;
newNode->value = value;
newNode->prev = NULL;
newNode->next = NULL;
}
// Case for nonempty list
else {
newNode->prev = list->tail;
newNode->value = value;
newNode->next = NULL;
list->tail = newNode;
}
}
void print(slist_t *list) {
if (list->head == NULL) {
printf("The list is empty\n");
return;
}
list_item_t *currentNode = list->head;
while (currentNode != NULL) {
printf("%d ", currentNode->value);
currentNode = currentNode->next;
}
printf("\n");
}
int main() {
slist_t myList;
init(&myList);
add(&myList, 5);
add(&myList, 2);
add(&myList, 6);
print(&myList);
}
Ok I got rid of my bus error but now when I try to print my list all it prints out is:
1
Is the problem in init function or my add function? I was wondering if since I don't use malloc in the init function that the list gets erased after every function call of add? Is that true? I have tried allocating it like this:
slist_t *list = (slist_t *)malloc(sizeof(slist_t))
but it gives me an error.
Failing to link old tail's next to the new tail.
// Case for nonempty list
else {
// Add. `list->tail->next` should be NULL before this code.
list->tail->next = newNode;
newNode->prev = list->tail;
newNode->value = value;
newNode->next = NULL;
list->tail = newNode;
}

Resources