Hey guys I have two structs: one is a key-pair and the other is a node.
typedef struct {
char *key;
void *value;
} VL;
typedef struct node{
struct node *left;
struct node *right;
VL data;
} BST;
How would I go about initializing the node struct and adding the VL struct inside?
This is what I have so far:
// Create new node
struct node *temp = malloc(sizeof(node));
temp->left = NULL;
temp->right = NULL;
struct VL *vl = malloc(sizeof(VL));
vl->key = key;
vl->value = &value;
temp->data= *vl;
And I've also tried many other things like setting temp->data.key to key etc, all of which return errors. So I've come here for help :).
Also how would I go about getting the data from the nodes?
char *key = (char *)5;
void *val = "hello";
// create node with this key/val pair and insert into the tree, then print
printf("key = %d; value = %s\n", (int)head->data.key, (char*)head->data.value);
Would that suffice?
Thanks!
The memory for VL data is allocated as part of the node struct and does not need to be reallocated.
Try:
struct node *temp = malloc(sizeof(node));
temp->left = NULL;
temp->right = NULL;
(temp->data).key = key;
(temp->data).value = &value;
Related
I'm using C and wanted to create a doubly linked list that contains char values. I have another file given to use by the teacher to measure the big O notation so I'm sure it's correct. But when I run it, I get a zsh: segmentation fault from the terminal.
I ran it through valgrind and it gave me the error mentioned in the title and mentioned the following function, more specifically the Malloc and strdup command. I'm not sure what's wrong here, it looks fine to me so was hoping to get some help here.
Here's the struct from the header file:
struct node
{
struct node *next;
struct node *prev;
char *value;
};
and here's the function to create a node in the main file:
static struct node *make_node(const char *value)
{
struct node *result = malloc(sizeof(struct node));
result->value = strdup(value);
result -> next = NULL;
result -> prev = NULL;
return result;
}
And for good measure, here's the function that calls make_node
ListPos list_insert(ListPos pos, const char *value)
{
struct node *node = make_node(value);
struct node *before = pos.node->prev;
struct node *after = pos.node;
node->next = after;
after->prev = node;
node->prev = before;
before->next = node;
pos.node = node;
return pos;
}
here's part of my code for the linked list:
struct node {
float data;
int key;
struct node* next;
};
typedef struct{
struct node *head;
struct node *current;
int length;
} linked_list;
linked_list *init_list(){
linked_list *out = malloc(sizeof(linked_list));
struct node *head = NULL;
struct node *current = NULL;
out->head = head;
out->current = current;
out->length = 0;
return out;
}
void push_core(struct node *head, int key, float data){
struct node *link = malloc(sizeof(struct node));
link->data = data;
link->key = key;
link->next = head;
// readjust to point at the new first node
head = link;
printf("%f; ", head->data);
}
void push(linked_list *list, int key, float data){
push_core(list->head, key, data);
list->length ++;
}
void print_list_core(struct node *head){
struct node* ptr = head;
printf("\n[");
while(ptr != NULL){
printf("(%d,%f)", ptr->key, ptr->data);
ptr = ptr->next;
}
}
void print_list(linked_list *list){
print_list_core(list->head);
}
But in the main, after I initialized the linked list structure, I wasn't able to use push() to link new pointers, why is that?
linked_list *S = init_list();
for (int i = 0; i < n; i++)
{
push(S,i,0);
print_list(S);
printf("%d;", S->length);
}
To clarify, the length of the list does update correctly. But when I try to print the list it doesn't work. Also, it's interesting that in another file when I initially just worked with the node struct and defined global variables for head and current, the code works fine. But when I try to wrap them up inside this linked_list struct, things aren't quite working as expected.
The problem occurred because you passed the pointer value of list->head to your push_code function as a parameter. This is a function call-by-value. So, when you change the head pointer inside the push_core function, it actually do not change the list->head pointer that you are expecting to. One quick fix would be returning the newly created link pointer from the push_core function and save it as list->head. The following code should fix your problem.
struct node * push_core(struct node *head, int key, float data){
struct node *link = malloc(sizeof(struct node));
link->data = data;
link->key = key;
link->next = head;
return link;
}
void push(linked_list *list, int key, float data){
list->head = push_core(list->head, key, data);
list->length ++;
}
I start learning linked list,so my question may be stupid :p . I noticed that in all the exercices, they only take one data element in the node( as below : int data).So i am asking can we define multiple data elements in one node.Otherwise why not?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node* nextptr;
};
struct node* BuildList()
{
/* initialize node's pointers */
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
/* allocate three nodes in the heap*/
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
/* setup first node */
head->data = 1;
head->nextptr = second;
second->data = 2;
second->nextptr = third;
third->data =3;
third->nextptr = NULL;
return head;
}
Yes, int just make it easier for the examples. But in real life, the node will be something more useful. Example:
struct chair {
int nr_or_legs;
int weight_in_kg;
int height_in_cm;
};
struct chair_node {
struct chair data;
struct chair_node* nextptr;
};
or just:
struct chair_node {
int nr_or_legs;
int weight_in_kg;
int height_in_cm;
struct chair_node* nextptr;
};
typedef struct node_ {
avl_node node;
some_struct *data;
}node_t;
Now if a function(API) returns me the pointer to data is there a way, I can get the structure node_t pointer?
For example:
node_t *a = malloc(sizeof(node_t));
a->data = malloc(sizeof(some_struct));
//some code
//a->data->key = some_val;
//avl_insert(a->data->key)
/* API to get the data, which return pointer of type some_struct*/
some_struct *temp;
temp = get_data(key)
Is there a way for me to get the the pointer node_t of the "temp".
Please, let me know what's the best way to get it.
If you need to get back to the node that contains the data, you have to build the association yourself. Perhaps the most straightforward way is to extend some_struct:
typedef struct my_some_struct {
some_struct ss;
struct node_ *back;
} my_some_struct;
typedef struct node_ {
avl_node node;
my_some_struct *data;
}node_t;
node_t *a = malloc(sizeof(node_t));
a->data = malloc(sizeof(my_some_struct));
a->data->back = a;
my_some_struct *temp;
temp = get_data(key);
some_struct *ss = &temp->ss;
node_t *back = tmp->back;
Alternatively, you can extend the AVL tree with an API to return the node_t * for a given key.
node_t *n = get_node(key);
I trying to build a BST and insert nodes in it. However while creating a new node I keep getting exc_bad access error.What can be the reason? Here is my code:
struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);
nodeKey= malloc (sizeof (bst->key_size));
nodeVal = malloc(sizeof(bst->value_size));
size_t sizeKey = sizeof(nodeKey);
memcpy(node->key, nodeKey, sizeKey); // exc_bad access
size_t sizeVal = sizeof (nodeVal);
memcpy(node->val, nodeVal, sizeVal); // exc_bad access
node->right = rightChild;
node->left = leftChild;
return node;
}
struct Node {
void *key;
struct Value *val;
struct Node *left;
struct Node *right;
};
struct BSTree {
size_t key_size, key_alignment;
size_t value_size, value_alignment;
int (*compare_func)(void *, void *);
struct Node *root;
// ... Maybe some other stuff.
};
struct Value {
char name[10];
int id;
};
Without knowing what Node, looks like, I'd say, even though you've allocated for node, you've not allocated all the members (which appear to be pointers).
Change your code to something like:
// Allocate node
struct Node *node = malloc(sizeof *node);
// Now members
node->key = malloc (sizeof (bst->key_size));
// :
If you are passing in the key and value, then do a memcpy of those values to the above locations. But hard to say without further code...
Without looking at the Node structure, I would guess what you want to do is:
if node is defined as
struct Node {
void *key;
struct Value *val;
struct Node *right;
struct Node *left;
};
then
struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);
node->key = malloc(bst->key_size); /* No sizeof here */
node->val = malloc(bst->value_size);
memcpy(node->key, nodeKey, bst->key_size);
memcpy(node->val, nodeVal, bst->value_size);
node->right = rightChild;
node->left = leftChild;
return node;
}
As you don't check for the returns of the mallocs (which is a design choice that can e justified), you can even write it simpler that way.
struct Node *node_create(struct BSTree *bst,void *nodeKey, struct Value *nodeVal, struct Node *rightChild, struct Node *leftChild)
{
struct Node *node = malloc(sizeof *node);
node->key = memcpy(malloc(bst->key_size) , nodeKey, bst->key_size);
node->val = memcpy(malloc(bst->value_size), nodeVal, bst->value_size);
node->right = rightChild;
node->left = leftChild;
return node;
}
There are people that cringe at this style but I prefer to not dilute my code too much on redundancies.