I have to make a function which counts how many elements my tree have. My tree is not binary, is the most general kind of tree.
The node is:
typedef struct node{
char item;
int number_of_sons;
node **sons;
}
My counting function is this
void numbering(node *HT,int ok=0)
{
static int number = 0;
if (ok == 1)
{
printf("%d", number);
return;
}
if (HT == NULL)
{
return;
}
else
{
number++;
for (int i = 0;i < HT->nr_of_sons;i++)
{
numbering(HT->next[i], 0);
}
}
}
Is there a way to improve this function to make this faster?
EDIT: the way I use this function is:
int main()
{
//create tree;
numbering(tree,0);
numbering(tree,1);
}
When I call the function the second time it prints my result
You have a very strange recursive function there--you're using a static variable in the function which is never reset, so the function can only be used once per program run!
I'd rewrite it this way:
size_t nodecount(node *root)
{
size_t count = 0;
if (root)
{
count++;
for (int i = 0; i < root->nr_of_sons; i++)
{
count += nodecount(root->sons[i]);
}
}
return count;
}
If you really want to speed things up, you could augment your node structure by adding a size_t subtree_count field which you'd maintain whenever you insert or remove nodes. Another idea is to compact the pointer-to-array-of-sons into the node structure directly:
typedef struct node{
char item;
int number_of_sons;
node_t *sons[0];
} node_t;
What I've done here is made it so the sons variable is an array rather than a pointer to an array. But it has size zero (n.b. use [] or [1] if your compiler requires), because you don't know the number of sons at compile time. But you can simply allocate nodes with the right amount of space:
node_t* tree = (node_t*)malloc(sizeof(node_t) + num_sons*sizeof(node_t*));
This reduces pointer indirection by one layer, which may help performance.
Maybe this is better and more efficient:
int numbering(node *HT)
{
if (!HT)
{
return 0;
}
int num = 1;
for (int i = 0;i < HT->nr_of_sons;i++)
{
num += numbering(HT->next[i]);
}
return num;
}
I deleted your ok variable and changed the returned value from void to int.
In the case base you return 0;
For the leaf so they will return 1;
For inner nodes they will return 1 + the numbers of nodes in the
subtree.
Related
enter code here
#include <stdio.h>
#include <stdlib.h>
typedef struct _node {
int data;
struct _node* rightChild;
struct _node* leftChild;
}Node;
Node* create(int data) { // create node function
Node* node = (Node*)malloc(sizeof(node));
node->rightChild = NULL;
node->leftChild = NULL;
node->data = data;
return node;
}
void Inorder(Node* ptr) { // travel
if (ptr)
{
printf("%c ", ptr->data);
Inorder(ptr->leftChild);
Inorder(ptr->rightChild);
}
}
int main(void)
{
Node* node[300];
for (int i = 1; i < 300; i++) {
if (i == 1) {
node[i] = create(i);
}
else {
if (i % 2 == 0) {
node[i / 2]->leftChild = create(i);
}
else {
node[i / 2]->rightChild = create(i);
}
}
}
Inorder(node[10]);
}
I would like to implement a binary tree using a Node* array, rather than taking variables input one by one. But I keep getting errors in that area. Thanks for the advice.Which part do I need to modify to make that part implemented through a for statement? As far as I understand, both the left and right parts of the node array have passed values, so why am I getting an error?
The only node[i] you assign to is node[1]. All other nodes are linked via the the leftChild or rightChild fields.
You could fix this by doing, for example:
node[i] = create(i);
node[i / 2]->leftChild = node[i];
but I this is a bit roundabout, because you now have the same data – the handle to a node — in two different places.
My guess is that what you really want is a plain array of node structures, which are then linked via pointers into the array:
Node node[300] = {{0}};
node[1].data = 1;
for (int i = 2; i < 300; i++) {
node[i].data = i;
if (i % 2 == 0) {
node[i / 2].leftChild = &node[i];
} else {
node[i / 2].rightChild = &node[i];
}
}
This creates a flat array of nodes, where the nodes are linked like a binary tree. For example, node[1].leftChild is a pointer to node[2]. You can use regular tree functions by passing &node[1] as head:
Inorder(&node[1]);
(What you call Inorder is really a pre-order traversal.)
The advantage is that you don't need to create and allocate anything. When main ends, the whole tree is gone without needing to free. (It also gets rid of a bug in create, where you allocate space for a pointer only, not for a node; it should be node = malloc(sizeof(*node));.)
Perhaps that's not what you want, but the bug in your code comes from accessing node[2] when it hasn't been set.
Im trying to create a recursive function that creates an array of post order integers from a given tree. This is the code:
//structure
typedef struct node
{
// Each node holds a single integer.
int data;
// Pointers to the node's left and right children.
struct node *left, *right;
} node;
// preorder_recursive is same as postorder_recursive(), except
// array[i] comes before the recursive calls
int *postorder_recursive(node *root)
{
int *array = malloc(sizeof(node) * node_count(root)); // node_count(root) counts nodes in binary tree
int i = 0;
if (root == NULL)
return 0;
while (root != NULL)
{
postorder_recursive(root->left);
postorder_recursive(root->right);
array[i] = root->data;
i++;
}
return array;
}
// returns 1 if pre order = post order, returns 0 otherwise
int compare(node *a, node *b)
{
int i = 0;
int *preArray, *postArray;
if (node_count(a) != node_count(b))
return 0;
preArray = preorder_recursive(a);
postArray = postorder_recursive(b);
for (i = 0; i < node_count(a); i++)
{
if (preArray[i] != postArray[i])
return 0;
}
free(preArray);
free(postArray);
return 1;
}
I am not entirely sure if the error is in this function, but if it is, it's probably due to the while loop. Any help would be great.
Edit: Ive included a lot more code. The purpose of this is to compare an array of post order to an array of pre-order.
Your function postorder_recursive() is creating a new array every time it is called. Furthermore, while(root != NULL) will loop forever for non-empty trees, if it weren't for the fact that it writes past the end of array and cause a segmentation fault at some point.
The solution is to split the function into one that creates the array, and then another function that recursively fills in the array, like so:
static size_t postorder_recursive(const node *root, int *array, size_t index) {
if (root == NULL)
return index;
index = postorder_recursive(root->left, array, index);
index = postorder_recursive(root->right, array, index);
array[index++] = root->data;
return index;
}
int *postorder_to_array(const node *root)
{
int *array = malloc(sizeof(node) * node_count(root));
postorder_recursive(root, array, 0);
return array;
}
I was solving a problem which allowed two types of operations: subtracting one from a number or multiplying it by two, with the source and the destination numbers provided. Input constraints are 1<=n<=10^4 for both numbers. I'm supposed to output the number of operations needed to produce the desired number from the given one. The following is my implementation, getting runtime error and, obviously, I do not know why. It'll be awesome if someone explains the bug. Thanks.
#include <stdio.h>
#include <stdlib.h>
int g[22222][3], v[2222], size;//g == graph, v == visited and size == the size of queue
typedef struct _queue
{
int val;
struct _queue *next;
struct _queue *prev;
} queue;
queue *head=NULL, *last=NULL;
void push(int val)
{
queue *ptr=(queue *) malloc(sizeof(queue));
ptr->next=NULL;
ptr->val=val;
if (head)
{
last->next=ptr;
ptr->prev=last;
}
else
{
head=ptr;
ptr->prev=NULL;
}
last=ptr;
}
void pop()
{
if (size)
{
queue *ptr=last;
last=last->prev;
if (head) last->next=NULL;
free(ptr);
}
}
int front() {return last->val;}
int bfs(int s, int d)//s == source and d == destination
{
int cnt=0;
push(s);
size++;
v[s]=1;
while (size)
{
int u=front();
pop();
size--;
for (int j=1; j<=2; j++)
{
if (d==g[u][j]) return (cnt+1);
if (!v[g[u][j]])
{
v[g[u][j]]=1;
size++;
push(g[u][j]);
}
}
cnt++;
}
}
int main()
{
int n, m, val;
scanf("%d%d", &n, &m);
if (n==m) {printf("0"); return 0;}
val=(n>m?n:m)*2;
v[0]=1;
for (int i=1; i<=val; i++)
{
g[i][1]=2*i;
g[i][2]=i-1;
}
printf("%d", bfs(n, m));
return 0;
}
You have implemented a stack i.e. LIFO (last in first out): you are adding to the end and retrieving from the end.
You should implement a queue i.e. FIFO (first in first out), so if you add to end, you should retrieve from front:
void pop()
{
if (size)
{
queue *ptr=head;
head=head->next;
if (head) head->prev=NULL;
free(ptr);
}
}
int front()
{
return head->val;
}
Also, I guess your aim is to count the smallest number of operations required to produce the desired number from a given one. Your cnt variable does not represent the smallest number of operations, it represents the number of times you retrieved an element from the queue. You need to increment it for each new level instead.
Finally, your bfs should return a value even if there is no path from s to d, so you should put return 0; after the while(size){} loop.
UPD. You need to skip g[u][j] if it is larger than 2 * (10^4) inside of bfs, otherwise those values be enqueued which is a waste of space. By the way your v array has only 2222 elements, it should have at least 20001 (v[20000] is the last one)
Here is my list struct:
typedef struct Header {
struct Header* next;
char empty;
int storageSize;
} Header;
And I am looping over a list to check how many elements its has:
int listSize(Header* _header) {
int count = 0;
while(_header->next) {
_header = _header->next;
++count;
}
return count;
}
And I get a segfault after reaching the end of the list.
However if I change it to:
int listSize(Header* _header) {
int count = 0;
while(_header->next) {
if(!_header->next) {
_header = _header->next;
++count;
}
else
break;
}
return count;
}
It doesn't segfault, but it also obviously doesn't count the elements right.
Change this:
while(_header->next) {
to this:
while(_header) {
since you want to loop over your list, as long as the current node is not NULL.
You were facing a segmentation fault, because you were trying to get the next data member of NULL.
It feels like you are passing an empty list to your listSize(), that is that the _header is NULL, and you are trying to get the next data member of NULL, thus a segmentation fault.
You logic is incorrect. The code should be this - and note the comments
int listSize(Header* header) {
int count = 0;
while (header) { // We have a node to count
++count; // Count it
header = header->next; // And move to the next node
}
return count;
}
In my opinion you can initialize next as 0 or *next as 0 whenever you want to create a new node.
I have been working on a program in C99 which is based heavily around structs. I found that I could create linked lists of structs, and thought to give it a try.
The following is a miserable attempt, reworked about 50 times, that is meant to do the following:
1) Create a struct of type BASE in the main method, which contains the head of a linked list (CHAIN).
2) Pass this BASE struct to another function, which will append additional CHAIN elements to the end of the linked list.
3) Print the linked lists elements in main, as proof to myself that the changes are not just in the other method.
#include <stdlib.h>
#include <stdio.h>
typedef struct Base {
//many things
struct Chain *head;
} BASE;
typedef struct Chain {
int x;
struct Chain *next;
} CHAIN;
void extendChain(BASE *Data, int length);
int main() {
BASE Data;
CHAIN *pointer;
Data.head = 0;
int length = 10; //userInput(); // gets integer
extendChain(&Data, length);
pointer = Data.head;
while (pointer) {
printf("%d\n", pointer->x);
pointer = pointer->next;
}
}
void extendChain(BASE *Data, int length) {
CHAIN *position;
position = Data->head;
for (int i=0; i<length; ++i) {
if (!Data->head) {
// this will set the first value, the first time this is run.
Data->head = malloc(sizeof(CHAIN));
Data->head->x = -1; // set values here. Irrelevant.
position = Data->head;
} else if (position) {
while (position->next) {
position = position->next;
}
position = malloc(sizeof(CHAIN));
position->next = 0;
position->x = i; // placeholder
}
}
}
This has turned out terribly, and I realize that my example doesn't begin to work even in theory (but I gave it my best shot). I'm beginning to think that the only way to do this is if I do it all in the same method, which I successfully managed to do earlier, however this will quickly become messy, and a method would definitely be best.
Does anyone have a creative way of adding X elements to a linked list when passed only a struct containing the header of this linked list? Much appreciated, as always.
Logical errors in your code. This code worked:
void extendChain(BASE *Data, int length) {
CHAIN *position;
position = Data->head;
int i;·
for (i=0; i<length; ++i) {
if (!Data->head) {
// this will set the first value, the first time this is run.
Data->head = malloc(sizeof(CHAIN));
Data->head->x = -1; // set values here. Irrelevant.
Data->head->next = NULL; // <=========
position = Data->head;
} else if (position) {
while (position->next) {
position = position->next;
}
CHAIN * position_new_node = malloc(sizeof(CHAIN)); // <=========
position_new_node->next = 0; // <=========
position_new_node->x = i; // placeholder // <=========
position->next = position_new_node; // <=========
}
}
}
Algorithm
Create the original linked list
Send the linked list to be added, to the function
Traverse till the end of first linked list (Let the pointer be t)
repeat:
node next to t=next node of new linked list
move both nodes one unit forward
till the next node of new linked list is Null