One of the arrays in my Linked List are missing - c

Here is the node of Linked List:
struct Node {
char data;
struct Node *next;
int pindex; //this is the first index position in parent[] which is null, next element goes here
int cindex; //this one for child array
char parent[50];
char child[50];
};
This is how i am creating each node.
struct Node *createNode(struct Node *node, char nodeData) {
if(root == NULL) {
int i=0;
node= malloc(sizeof(struct Node));
node->data = nodeData;
while(i<50) {
node->parent[i]= '\0';
node->child[i]= '\0';
i++;
}
node->pindex=0;
node->cindex=0;
node->next= malloc(sizeof(struct Node));
root=node;
return node;
}
else if (node->data == 0) {
int j=0;
node->data = nodeData;
while (j<50) {
node->parent[j]= '\0';
node->child[j]= '\0';
j++;
}
node->pindex=0;
node->cindex=0;
node->next= malloc(sizeof(struct Node));
return node;
}
else
return createNode(node->next, nodeData);
}
Here is my code where i am updating the values of the parent and child arrays in a particular node.
void insert(char a, char b) {
struct Node *pNode, *cNode;
if (hasNode(root,a)) //check if Node with node->data ='a' exists else create it
pNode= getNode(root,a);
else {
pNode= createNode(root,a);
//addToFirst(one); No need as we already have list of all elements
}
if (hasNode(root, b))
cNode= getNode(root,b);
else
cNode= createNode(root, b);
pNode->child[(pNode->cindex)] = b; //insert a char into child array of parent node
pNode->cindex++;
cNode->parent[(cNode->pindex)]= a; // insert char into child array of parent node
cNode->pindex++;
}
Problem is with the following section
pNode->child[(pNode->cindex)] = b; //insert a char into child array of parent node
pNode->cindex++;
cNode->parent[(cNode->pindex)]= a; // insert char into child array of parent node
cNode->pindex++;
as any element is inserted into the parent[] of cNode, its child[] is gone from the memory. And if i insert later anything into child, its working.
Following is the screenshot i took for this linked list, that should help. The child array is missing from the data root->next node
[Screenshot of the data structure]

Related

How to delete a node from the Hashmap C

I have an HashMap (struct table). It contains nodes doubly linked with two parameters: key, value.
Hashmap may contains every data type. Insertion of nodes is generic, so the user must choose what data type insert in the hashmap.
My aim is to create a generic function in order to delete a node with a key that I passed him.
When I try to delete a node canckey doesn't work. It doesn't compile when I use double arrow. For example : temp->prev->next = temp->next; (in this line of code I'm telling him to update the next of the previous node to the one I have to delete.)
canc.c
struct node{
void* key;
void* val;
struct node *next;
struct node *prev;
};
struct table{
int size;
struct node **list;
};
void cancKey(struct table *t, void *key, int(*hash)(void*), int(*comp)(void*, void*)) {
int pos = (*hash)(key);
struct node *list = t->list[pos];
struct node *temp = list;
if (t->list[pos] == NULL) {
printf("%s\n", "The key doesn't exist.");
return;
}
while (temp) {
if (((*comp)(temp->key, key)) == 1) {
if(temp->prev==NULL){
list->next=temp->next;
temp->next->prev=NULL;
temp->next=NULL;
}else {
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
temp->next = NULL;
temp->prev = NULL;
}
}
temp = temp->next;
}
}
main.c
int hashCode(int key){
return (key%500);
}
int compare(int key,int key2){
if(key==key2){
return 1;
}else return 0;
}
int main(){
struct table *t; // table creation and data insertion
int i=1;
int *p = &i;
int i1=2;
int *p2 = &i1;
cancKey(t,p,hashCode, compare);
cancKey(t,p2,hashCode, compare);
}

How to change sinlgy linked list to doubly linked list?

I have a program that I am supposed to change it from a singly linked list to a doubly linked list. This means that I use pointer that points to the next node and a pointer that points to previous node.
How do I do this while recycling my previous code. Is there a way to do this with minimum steps involved?
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//declaring structure
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//prototypes
node *create(int n);
void display_recursive(node *n);
int main()
{
int n = 0;
node *head = NULL;
printf("How many entries?\n");
scanf("%d", &n);
//call to create list
head = create(n);
printf("\nThe linked list in order is:\n");
display_recursive(head);
return 0;
}
node *create(int n)
{
node *head = NULL;
node *temp = NULL;
node *p = NULL;
for (int i = 0; i < n; i++)
{
temp = (node*)malloc(sizeof(node));
printf("What is the name of song %d\n", i + 1);
scanf("%s", &temp->songName);
printf("What is the length of song %d (in seconds)?\n", i + 1);
scanf("%d", &temp->songLength);
printf("Is song %d copyrighted?(1 = YES, 0 = NO)\n", i + 1);
scanf("%d", &temp->copyright);
temp->next = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// if not empty, attach new node at the end
p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
printf("%d minutes, ",n->songLength);
if (n->copyright == 1)
{
printf("Copyrights\n");
}
else if (n->copyright == 0)
{
printf("No copyrights\n");
}
}
I don't really know how the code should look or what I have to add to achieve a doubly linked list.
You just need a pointer point to previous node
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node;
just like #T1412 said, you need to add a new member to the structure.
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node
now you need to modify the create() function so that each node's prev pointer is pointing to previous node, and the HEAD node's prev points to NULL.
Similarly, you need to modify all the linked list related functions to incorporate the prev pointer.
1) strongly suggest changing:
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
to:
struct NODE
{
char songName[20];
int songLength;
int copyright;
struct NODE * prev;
struct NODE * next;
};
typedef struct NODE node;
Then wherever in the code that it is linking in a new node, add the necessary statement to set the 'prior' field. Remember that the firs node will contain NULL in the 'prior' field.

Calling insert function in c from a header file

My professor send me a library to insert,delete and search elements in a linked list:
#include <stdlib.h>
struct NODE
{
char AM[12];
char name[40];
int semester;
struct NODE *head;
struct NODE *next;
struct NODE *prev;
};
void init(struct NODE **head)
{
*head=NULL;
}
struct NODE *Search (struct NODE *head,char CODE[],struct NODE **prev)
{
struct NODE *tmp;
*prev=NULL;
tmp=head;
while (tmp!=NULL && tmp->AM<CODE)
{
*prev=tmp;
tmp=tmp->next;
}
if (tmp==NULL)
return NULL;
if (tmp->AM==CODE)
return tmp;
return NULL;
}
struct NODE *Search2 (struct NODE *head,char name[],struct NODE **prev)
{
struct NODE *tmp;
*prev=NULL;
tmp=head;
while (tmp!=NULL && tmp->name<name)
{
*prev=tmp;
tmp=tmp->next;
}
if (tmp==NULL)
return NULL;
if (tmp->name==name)
return tmp;
return NULL;
}
int Insert (struct NODE **H,struct NODE P)
{
struct NODE *cur,*prev;
cur=Search(*H,P.AM,&prev);
if (cur)
return 0;
cur=(struct NODE *)malloc(sizeof P);
*cur=P;
if (prev==NULL)
{
cur->next=*H;
*H=cur;
}
else
{
cur -> next = prev -> next;
prev -> next = cur;
}
return 1;
}
int Delete (struct NODE **H,char AM[])
{
struct NODE *cur,*prev,*next;
cur=Search(*H,AM,&prev);
if (!cur)
return 0;
if (prev==NULL)
cur=next;
else
prev->next=cur->next;
free(cur);
return 1;
}
void traverse (struct NODE *head)
{
struct NODE *cur;
cur=head;
while (cur)
{
printf ("%p\n",cur);
cur=cur->next;
}
}
Now here is a piece of code from the source file that i created in an attempt to insert an element in the linked list:
case 1:printf ("Input AM,name and semester of student: ");
tmp=(struct NODE *)malloc(sizeof(struct NODE));
if (tmp==NULL)
exit(1);
scanf("%s %s %d",tmp->AM,tmp->name,&tmp->semester);
_flag=Insert(&head,*tmp);
if(_flag)
printf ("Student inserted succesfully!\n");
free(tmp);
break;
When i insert the element i get the "Student inserted succesfully" message,but when i call the search function to find that element,it returns NULL (meaning that the element is not in the list).How should i call the Insert function from the header file? (I assume the problem must be in the Insert function).Also in main() i have declared the following two:
struct NODE *head;
struct NODE *tmp;
Should i change something regarding those two?
I think your problem is in the Search() and Search2() functions, where you've got things like this:
while (tmp!=NULL && tmp->AM<CODE)
and
if (tmp->AM==CODE)
return tmp;
You're comparing the pointers, rather than the contents of the strings. If you want to compare the strings, or find which is first alphabetically, use strcmp().
while (tmp!=NULL && strcmp(tmp->AM, CODE) < 0)
and
if (!strcmp(tmp->AM, CODE))
return tmp;
The same goes for the comparison between tmp->name and name in Search2().

Binary Search Tree in C Segmentation Fault

I've been trying to implement a simple binary search tree in C just as an exercise. I can insert elements into the tree, but at certain points (I haven't been able to figure out where) I'm getting a segmentation fault.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node *left;
struct node *right;
int key;
};
void insert(struct node *treeNode, int key);
void outputTree(struct node *root);
int main(){
//Store how many numbers the user will enter
printf("How many numbers will you enter? > ");
int numNumbers;
scanf("%d", &numNumbers);
//Create a root node
struct node root;
root.key = -1; //-1 Means the root node has not yet been set
root.right = NULL;
root.left = NULL;
//Now iterate numNumbers times
int i;
for(i = 1; i <= numNumbers; ++i){
int input;
scanf("%d", &input);
insert(&root, input);
}
outputTree(&root);
return 0;
}
void insert(struct node *treeNode, int key){
//First check if the node is the root node
if((*treeNode).key == -1){
printf("Root node is not set\n");
(*treeNode).key = key; //If the root node hasn't been initialised
}
else {
//Create a child node containing the key
struct node childNode;
childNode.key = key;
childNode.left = NULL;
childNode.right = NULL;
//If less than, go to the left, otherwise go right
if(key < (*treeNode).key){
if((*treeNode).left != NULL){
printf("Left node is not null, traversing\n");
insert((*treeNode).left, key);
}
else {
printf("Left node is null, creating new child\n");
(*treeNode).left = &childNode;
}
}
else {
//Check if right child is null
if((*treeNode).right != NULL){
printf("Right node is not null, traversing...\n");
insert((*treeNode).right, key);
}
else {
printf("Right node is null, creating new child\n");
(*treeNode).right = &childNode;
}
}
}
}
void outputTree(struct node *root){
//Traverse left
if((*root).left != NULL){
outputTree((*root).left);
}
printf("%d\n", (*root).key);
if((*root).right != NULL){
outputTree((*root).right);
}
}
As of writing this question, I've just had the thought, are the child nodes being created on the stack, so when the recursive calls return, the references in the tree are pointing to a struct that no longer exists?
What is wrong here?
Thank you
You create childs node on the stack by static allocation. When the insert method is finished, the child reference become invalid.
You should use dynamic allocation with malloc.
struct node *new_node(int key, struct node *left, struct node *right) {
struct node *this = malloc(sizeof *this);
this->key = key;
this->left = left;
this->right = right;
return this;
}
don't forget to free all of your allocations with the free function.
edit :
so to create the root just use
struct node *root = new_node(-1, NULL, NULL);

Linked List inserting trouble

I am having trouble with inserting items in linked list. All the elements end up having the same *data content that is inserted in the last. The program compiles successfully. I use gcc and gdb.
I am new to coding so please mention troubles if any that you see in my programming style.
typedef struct Node{
void* data;
struct Node* next;
} *node;
node allocate(){
node current = malloc(sizeof(struct Node));
current->data = NULL;
current->next = NULL;
return current;
}
void insert(node *head, void *data){
// if head has no data then set the data on head and return
if(((*head)->data == NULL)&&((*head)->next == NULL)){
(*head)->data = data;
return;
}
node newHead = allocate();
newHead->data = data;
newHead->next = *head;
*head = newHead;
//printf("Node Data : %d\tNext Node Data : %d",
//*(int *)((*head)->data), *(int *)((*head)->data));
}
int main(int argc, char *argv[]){
node head = allocate();
int count = inputSequence(&head);
int *aod = calloc((size_t) count, sizeof(int));
generateAOD(head, aod);
if(checkJolly(aod, count) == TRUE)
printf("Jolly\n");
else
printf("Not Jolly\n");
return 0;
}
int inputSequence(node *input){
int *num = malloc(sizeof(int));
int count = 0;
while((scanf("%d", num) != EOF)){
insert(input, (void *)num);
count++;
}
traverse(*input, fn);
return count;
}
Your insert logic is non-existant. And you're literally making your life harder by attempting to manage a linked list in the fashion you're using.
The head pointer itself should indicate whether the list is empty. If it is NULL, its empty. If it isn't, there's data. Code the insertion logic accordingly.
And your inputSequence is utterly broken. It only allocates ONE data point, then uses the same data allocation for every insertion. You need one for each insertion.
First, change allocate() to accept the data being inserted. It will make the remaining code less cluttered:
node allocate(void *data)
{
node current = malloc(sizeof(*current));
current->data = data;
current->next = NULL;
return current;
}
Second, insert by allocating a new node as needed.
void insert(node *head, void *data)
{
node p = allocate(data);
p->next = *head;
*head = p;
}
Next, fix inputSequence() to properly allocate memory for each entry:
int inputSequence(node *input)
{
int count = 0;
int num = 0;
// note: check for number of params *successfully* parsed.
// if it isn't 1, its time to leave the loop.
while(scanf("%d", &num) == 1)
{
int *data = malloc(sizeof(num));
*data = num;
insert(input, data);
++count;
}
return count;
}
And lastly, make sure your head pointer is initially NULL in main().
int main(int argc, char *argv[])
{
node head = NULL;
// load linked list
inputSequence(&head);
// ... the rest of your code....;
return 0;
}
With the above, the logical answer of "Is my list empty" is simply if (!head) Further, this makes things like traversal trivial.
void traverse(node ptr, void (*pfn)(void *))
{
while (ptr)
{
pfn(ptr->data);
ptr = ptr->next;
}
}
Freeing the list is equally trivial:
void destroy(node *head)
{
while (*head)
{
node p = *head;
*head = p->next;
free(p->data);
free(p);
}
}
typedef struct Node{
void* data; // Make it as int or any other data type
struct Node* next;
} *node;
In function inputSequence() you are allocating memory for num at the very beginning and making node->data point to this memory each time you are adding a node. Hence data pointer of each node of your linked list points to the same memory location and hence contains the same value.
If you still want to continue with data as a void pointer, allocate num for each iteration of the while loop and pass this to insert function.
while((scanf("%d", num) != EOF)){
num = malloc(sizeof(int);
insert(input, (void *)num);
count++;
}

Resources