I used the example (exactly that example) given here: https://man7.org/linux/man-pages/man3/tsearch.3.html
But I could not use LEFT macro or struct node_t struct. I just want to move left or right node by myself because I need to check the tree created by tsearch if it is full tree, or balanced or ccomplete etc.
While using LEFT, I am getting implicit declaration error, with struct node_t I am getting dereferencing pointer to incomplete type.
How can I move to left or right child by myself? Is there any way to check the tree created by tsearch is balanced or not (e.g.)
Thanks
I checked search.c source code, found some macros but cannot use them because of compiling errors
Related
I'm implemented a Binary-Search-Tree in C code. Each of my tree nodes looks like this:
typedef struct treeNode {
int key;
struct treeNode *right;
struct treeNode *left;
} treeNode_t;
The construction of the Tree made by the Host. The query of the tree made by the device.
Now, let's assumed that I'm already finished building my Tree in host memory.
I'm want to copy the root of my tree to the memory of my device.
Copying the root of the tree it self isn't enough. Because the right \ left child isn't located in the device memory. This is a problem.
So, my question is what is the easiest way to copy my whole tree to the device memory?
The easiest (and likely also best) way is to change your structure to use node indexes instead of pointers. The issue with pointers is that the device has different pointers and even if you copy all nodes separately, it would still not work as the pointers also need to be updated to device pointers. And unfortunately OpenCL 1.2 does not even guarantee that device pointers stay valid longer than a single kernel invocation. For this reason you have to use indexes instead of pointers at least on the device.
Modify your structure like this:
typedef struct treeNode {
int key;
int left;
int right;
} treeNode_t;
Before you build the tree you allocate one big array of tree nodes, large enough to hold all nodes.
treeNode_t nodes[MAX_NODES]; // or dynamic allocation
int first_free_node=0;
Every time you would normally allocate a new node, you now use nodes[first_free_node] to store the data and increment the first_free_node counter. When you are done building your tree, you can just use a single clEnqueueCopyBuffer call to copy all nodes to the device. You only need to copy first_free_node*sizeof(treeNode_t) bytes from the start of the nodes array to the device. If you cannot change you host tree building code, you can use a simple recursive deep first travesal of the tree to count the number of nodes and convert the nodes from the pointer based format to the index based format.
On some devices you might get a higher performance if you convert the structure of your tree from array of structures to structure of arrays. Padding the structure to 16 byte per node could also help.
If your device supports OpenCL 2.0 then you can use Shared Virtual Memory. The pointers created on the host will be valid on the device too. Here is the description and the binary search tree example: opencl-2-shared-virtual-memory.
This question already has answers here:
self referential struct definition?
(9 answers)
Closed 9 years ago.
Please help me to figure out a very basic confusion as follows,
struct node {
struct node *next; // no compile error
}
is ok, but the following gives an compile error(unknown type). I know it is wrong, but unable to figure out a clear reason.
struct node {
struct node next; // compile error, unknown type..why?
}
C allows you to have pointers to incomplete types.
struct node *next is a forward reference to struct node, but since you're only declaring a pointer to that type, the compiler doesn't mind. This is explicitly allowed, and it enables building structures that refer to each other.
You don't need a complete type to declare a pointer. Now a member struct node next; you'd get an error as it is a never-ending recursion.
Syntactically, it's because a struct type is incomplete until the closing }. You can use an incomplete type to declare a pointer to it, but the the type itself.
Furthermore, it doesn't make sense to define a struct that has itself in it, the size of it is unknown.
the struct is not fully defined at that point. If its a pointer, it does know how big a pointer to a struct is.
and if you think about what you are trying to do, a recursive data type, its gets a tad odd, it would be an infinite recursion.
The main reason is that node is not a complete type until you finish defining node and close it with } and so the compiler does not have enough information but you are allowed to have a pointer to an incomplete type.
The more basic reason is if node contained a node it would require infinite space since the self reference would never end. A node contains a node contains a node ad infinitum.
If we look at the draft C99 standard section 6.2.5 Types says:
[...] incomplete types (types that describe objects but lack information needed to determine their sizes)
and also says (*emphasis mine*0:
A pointer type may be derived from a function type, an object type, or an incomplete
type, called the referenced type.[...]
It would take an infinite amount of memory to store this struct.
The struct has to be large enough to store all of it`s members. However one of it's members is a struct of the same type, so it needs to store enough memory for two sets of members. But wait, that inner struct contains another instance of the struct inside itself - so we have three sets of members. And that inner contains an inner struct, which itself, contains an inner struct, and so on to infinity.
It is then logically impossible for a struct to contain itself.
I am looking at two linked list implementations (queue.h [source] and utlist.h [source]), and I have a few questions regarding their respective implementations:
What is _Q_INVALIDATE all about in queue.h? I suppose it is part of some debugging, but I don't really understand the macro define logic.
Both implementations offer FOREACH and FOREACH_SAFE. The former is straight forward, but what is the logic behind the second? Also, if the former is unsafe in anyway, why has it been implemented in the first place?
Why has queue.h implemented its struct as having different types for next and prev (struct *le_next and struct **le_prev)?
In both implementations, why are there extra parenthesis inserted here and there? Eg. around head in #define LIST_FIRST(head) ((head)->lh_first)
For Question 1:
_Q_INVALIDATE is a macro that sets a pointer that should no longer be used to a value of -1. The intent is that if it is used subsequently, debugging will be made easier because using the pointer will cause an immediate crash. In non-debug mode the macro does nothing, so the pointer is left with its current value - if there's a bug that results in the pointer being used, the problem may be a much more subtle defect.
For Question 2:
The 'safe' versions of these macros take an additional pointer argument that the macro uses internally to point to the next item in the list while the current one is being processed. This allows the code inside the loop to remove the current item from the list. Since the next item has already been remembered in the temp pointer, the macro has no problem picking it up for the next iteration. The non-safe version of the macro doesn't use a temp pointer, so you can't remove the current item from the list while iterating it.
For Question 3:
This makes it easier to add a new element before the current one or to remove the current element from the list without concern about whether the current element is at the head of the list (and therefore only 'pointed to' by the list pointer) or if the current element is elsewhere in the list (and therefore pointed to by another element's le_next pointer). If le_prev were a struct type* then dealing with the first element in the list would need special case code. Since le_prev is a struct type** it can refer to a simple struct type* (like the list head pointer) just as easily as a struct type* that's embedded at some arbitrary offset inside type (like the le_next links in each element).
Question 4 was answered in a comment above.
I am writing a doubly linked list based code in C. I had wrongly assumed that deleting the head node by doing free(head_node). And I could see the computer slowing down as the run progressed (which apparently is due to memory leak). I searched stackoverflow and other sites and the code I usually came across for deleting a linked list was this :
Node* current = head;
while( current != NULL ) {
Node* next = current->Next;
free( current );
current = next;
}
When I tried this in my code, the program just hangs right there after the free statement without returning to the function that calls this one. Is the above code relevant for a doubly linked list? My list member data contains a lot of pointers too. When I do free on one of the links, does it free all data the members point to? Please suggest and clarify with code snippets or references to books.
Thank you.
When I do free on one of the links, does it free all data the members point to?
No. This is what would happen if you deleted the last reference to an object in a garbage-collected language, but C doesn't work like that. You need to manually free each bit of memory that you've allocated.
That code looks like what you'd usually use for a singly- or doubly-linked list, assuming none of its values were pointers.
My list member data contains a lot of pointers too.
Since they are you need to free each current->value as well (and if they're pointers to pointers...).
The code you posted should work for singly or doubly linked lists, but makes some assumptions:
That there's no cleanup of the node to do before freeing it; this is often an incorrect assumption.
That the end of the list is marked with a NULL pointer (i.e. the last node's Next member is NULL)
Regarding the first assumption:
Since you have dynamically allocated data in your nodes, and presuming you don't have another pointer to it somewhere else that you'll use to clean it up later, you'll need to free that data before you free each node. In C, this is not done for you; the general rule is that if you had to allocate it yourself, you have to free it yourself too. A sensible way to deal with this is to write a function to clean up and free a node, and call that instead of just calling free(); your cleanup function would still free the node, but it would free the node's data first.
Regarding the second assumption:
It's a pretty common practice to set the last node's Next pointer to NULL to mark the end since it makes it easy to tell when you've walked all the way through the list. For a doubly linked list, the same goes for the first node's Prev pointer. However, if it's a circular list, the last node just points back to the first node instead -- and that would break the code you posted. In that situation, you'd start with the node head->Next instead of head, and check whether current is not head rather than not NULL. Then deal with head at the end, since you skipped it initially.
And one more thing:
Make sure after you're done freeing your list, that you don't leave head pointing to an invalid (already freed) node and then try to access the list again...
I am trying to learn how structs work in C. I am familiar with constructors in Java. Now, I have an example of creating a tree in C with structs.
struct a_tree_node{
int value;
struct a_tree_node *leftPTR, *rightPTR;
};
I am currently trying to visualize how this works, I am a little confused because this struct contains itself.
I am a little confused because this struct contains itself.
The struct doesn't contain itself, but rather two pointers to the same kind of structure. That's the key point to understand.
The struct containing itself would be nonsense and wouldn't compile because it's an infinitely recursive dependency.
I think your confusion is comparing a struct to a constructor in Java. The closest equivalent in Java would be class:
class ATreeNode{
int value;
ATreeNode left;
ATreeNode right;
}
As the other answers have said, the left and right node in the struct are pointers - much like (but not quite the same as) references from Java.
The struct doesn't contain it self. It contains two pointers to its type. A very important distinction. Pointers are not of the type the point to but can rather be dereferenced into what they point to at a later time.
It doesn't contain itself it contains two pointers to the same defenition. The * in front of the leftPTR and rightPTR point to memory location where other a_tree_node's are stored.
The struct is defined in such a way that it forms a linked list. Inside the struct you define two pointers to structs. So, the struct does not contain itself, rather, it contains two pointers to two different instantiations of a struct. It is even possible the pointer is a pointer to the struct itself.
When coming from Java, you already know the necessary concepts, but lack the rigor C enforces on the concepts of data and pointers. leftPtr is just like a variable of class type (like Object) in Java, that is, it points to another object, might be Null or might point to another object.
It's just a linked list of int representing a binary tree.
It contains the address of a simlar structure.
Like lets take a tree node.
it means that a single tree node also stores the address of two other similar tree nodes.
Here in the question contains a pointer to struct a_tree_node.
The size of a pointer type is always constant i.e. sizeof(unsigned integer)
so it won't create any problem in defining the size of a struct a_tree_node.
It will not be a nested struct... :) :)
struct a_tree_node{int value;struct a_tree_node *leftPTR, *rightPTR; };
This code will work fine as we are referring pointer to structure not its object as size of pointer is not data type specific. It will depend on how much bit is your OS effectively your integer will take how much byte
e.g on gcc sizeof(int) is 4 so sizeof(leftPTR) is also same
so at run time there will be no recursion sizeof(a_tree_node)=12 (Not considering structure padding as it is compiler specific)
struct a_tree_node{int value;struct a_tree_node left;};
This declaration will leads to error as compiler wouldn't be able to compute its size
goes in infite recursion.