#define NUMBEROFPILE 3
struct NodeType
{
struct PileType
{
int AmountInPile;
struct NodeType *NodePointer;
} *PilePointer;
};
int main(void)
{
}
struct NodeType *Create(int num[])
{
struct NodeType *NodePointer;
int i;
int j;
NodePointer=(struct NodeType *)malloc(sizeof(struct NodeType));
NodePointer->PilePointer=(struct PileType *)calloc(NUMBEROFPILE,sizeof(struct PileType));
for (i=0;i<NUMBEROFPILE;i++)
{
NodePointer->PilePointer[i].AmountInPile=num[i];
NodePointer->PilePointer[i].NodePointer=(struct NodeType *)calloc(num[i],sizeof(struct NodeType *));
for (j=0;j<num[i];j++)
/*----------------------------------------------------*/
NodePointer->PilePointer[i].NodePointer[j]=NULL;/*<---INCOMPATIBLE ??? WHY? */
/*----------------------------------------------------*/
}
}
I'm trying to declare an array of pointers using the above structure to
create a special trinary tree. I was wondering why I cannot set all pointers
to NULL in the array of pointers that I declared.
Many thanks in advance.
--
-------------------------------------------------------------------------------
msim __ __ ____ ___ ___ ____
ms...@primenet.com /__)/__) / / / / /_ /\ / /_ /
/ / \ / / / / /__ / \/ /___ /
-------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#define NUMBEROFPILE 3
struct NodeType
{
struct PileType
{
int AmountInPile;
struct NodeType *NodePointer;
} *PilePointer;
};
This is seriously fscked up. There's no reason to declare a structure
that contains only a pointer to another structure. Instead, you want
a single structure:
struct PileType
{
int AmountInPile;
struct PileType *Next;
};
int main(void)
{
}
struct NodeType *Create(int num[])
{
struct NodeType *NodePointer;
int i;
int j;
NodePointer=(struct NodeType *)malloc(sizeof(struct NodeType));
NodePointer->PilePointer=(struct PileType *)calloc(NUMBEROFPILE,sizeof(struct PileType));
for (i=0;i<NUMBEROFPILE;i++)
{
NodePointer->PilePointer[i].AmountInPile=num[i];
NodePointer->PilePointer[i].NodePointer=(struct NodeType *)calloc(num[i],sizeof(struct NodeType *));
for (j=0;j<num[i];j++)
/*----------------------------------------------------*/
NodePointer->PilePointer[i].NodePointer[j]=NULL;/*<---INCOMPATIBLE ??? WHY? */
Okay, ignoring my correction on the structure declaration, you are
trying to assign a pointer (NULL) to a struct NodeType
(NodePointer[j]). You can't do that. If that's what you want to do
then you'll have to declare NodePointer as a struct NodeType **.
/*----------------------------------------------------*/
}
}
I'm trying to declare an array of pointers using the above structure to
create a special trinary tree. I was wondering why I cannot set all pointers
to NULL in the array of pointers that I declared.
You didn't declare an array of pointers, you declared an array of
structures. And if it's a trinary tree why not hardcode the number of
subtrees as 3?
--
(supporter of the campaign for grumpiness where grumpiness is due in c.l.c)
Please: do not email me copies of your posts to comp.lang.c
do not ask me C questions via email; post them instead
Hi Sim Mong Chuan,
I'll get right down to your problem below. Just a sidenote first:
it is not required to cast the return value of "malloc()" or
"calloc()". A "void*" is automatically compatible to all other data
pointer types. And the cast can indeed hide the error of having
no prototype in scope.
And another very important point is to *always* check the return
value of memory allocation against NULL. Not doing this is very
dangerous and results in very insecure code.
> NodePointer->PilePointer[i].NodePointer[j]=NULL;/*<---INCOMPATIBLE ??? WHY? */
Now lets have a look at the above line. Here's the declaration of
your structures:
struct NodeType
{
struct PileType
{
int AmountInPile;
struct NodeType *NodePointer;
} *PilePointer;
};
"NodePointer" is a pointer to a structure. If you dereference this
pointer (take it's contents) you get the actual structure. That's
what happens in your line of code:
NodePointer->PilePointer[i].NodePointer[j]
dereferences the component "NodePointer" and what you get is a
structure of type "struct NodeType". IAW the component "NodePointer"
is not an array of pointer, it is an array of structures.
> I'm trying to declare an array of pointers using the above structure to
> create a special trinary tree.
To get an array of pointers you can either use a real static array
with a fixed maximum size:
struct NodeType *NodePointer[MAX_SIZE];
Or if you want to have it dynamically you need an additional level
of indirection:
struct NodeType **NodePointer;
and a considerably more complex function for dynamic allocation.
> I was wondering why I cannot set all pointers
> to NULL in the array of pointers that I declared.
You can only set *pointers* to NULL, not structures.
Stephan
(initiator of the campaign against grumpiness in c.l.c)
I would prefer:
struct PileType {
int AmountInPile;
struct NodeType * NodePointer;
};
struct NodeType {
PileType * PilePointer;
};
But that's a stylistic issue, nothing wrong with your declaration per se,
except that you obviously intend to use NodePointer as a pointer to an array
of pointers to these nodes and then you get it all wrong.
Also, I don't quite understand what is the usage of the 'NodeType'. As it is
it only contains a pointer to a 'PileType'.... Doesn't look like a very well
organized data structure to me. Remember that if you declare a structure you
should first make up your mind as to what is the PURPOSE of that structure.
As I can see you only need ONE structure (the one you call PileType) to
contain all the information.
The other issue is to determine if the subnodes of a node is ALWAYS 3. If so
it is easiest to define the subnode pointers in an array:
struct PileType {
int AmountInPile;
struct PileType * NodePointer[NUMBER_OF_PILE];
};
If it is sometimes less than 3 this is still a good data structure, you simply
set the non-used pointers to NULL.
If it is often less than 3 (all leaf nodes have no subnodes) then you should
probably dynamically allocate space for the node pointers and use only those
that you need. However, that require you to 'know' how many subnodes a node
has. If this number can be determined from the 'AmountInPile' you have then
that's fine otherwise you need some 'stop signal' such as an extra pointer
set to NULL to terminate the list of subnode pointers. Thus if a node has 2
subnodes you still allocate 3 subnodes and set the last one to NULL. If a
node has 3 you may either allocate 4 subnodes and set the last one to NULL or
you may allocate only 3 subnodes and not set any to NULL (3 is max so you
don't need the stop marker then). If a node has only one subnode you allocate
two pointers and if it is a leaf node and has no sub nodes you allocate one
pointer and set it to NULL or you allocate nothing and set the NodePointer to
NULL. In either case you will then not declare it as an array but as a
pointer to a pointer.
struct PileType {
int AmountInPile;
struct PileType * * NodePointers;
};
with the understanding that 'NodePointers' point to an array of nodes.
A away to handle this is by also doing this:
struct PileType {
int AmountInPile;
struct PileType * NodePointers[1];
};
and when you allocate the struct you allocate 1 or 2 extra sizeof(struct
PileType *) to make room for NodePointers[1] and NodePointers[2].
Yet another way is to avoid the allocation of space to all those pointers. If
you know that you need 3 subnodes for the current node you can already
allocate space for all those three subnodes and then have a single pointer to
point to the first of these. This requires that you create all subnodes to a
specific node at the same time. I.e. whenever you create a node you also
create also at the same time create all its siblings (i.e. all other nodes
that share the same parent). In this case you only need ONE pointer to all of
them and ptr + 1 gives you the next subnode under the same parent etc.
>
> int main(void)
> {
> }
>
> struct NodeType *Create(int num[])
> {
> struct NodeType *NodePointer;
> int i;
> int j;
>
> NodePointer=(struct NodeType *)malloc(sizeof(struct NodeType));
> NodePointer->PilePointer=(struct PileType
*)calloc(NUMBEROFPILE,sizeof(struct PileType));
> for (i=0;i<NUMBEROFPILE;i++)
> {
> NodePointer->PilePointer[i].AmountInPile=num[i];
> NodePointer->PilePointer[i].NodePointer=(struct NodeType
*)calloc(num[i],sizeof(struct NodeType *));
> for (j=0;j<num[i];j++)
> /*----------------------------------------------------*/
> NodePointer->PilePointer[i].NodePointer[j]=NULL;/*<---INCOMPATIBLE ???
Since the assignment is trying to store a NULL into a struct NodeType the
compiler is quite right in complaining about it.
WHY? */
Since NodePointer is of type struct NodeType * the NodePointer[j] is of type
struct NodeType, since this is not a pointer you can't assign a NULL pointer
to it.
Try:
PilePointer[i].NodePointer[j].PilePointer = NULL;
That this expression seem messy indicates that yoru data structure is messy.
You should fix it by fixing up your data structure. Get your head straight,
when you declare a struct, make up your mind WHY you want that struct, what
is the PURPOSE. NodeType as you have defined it serves no purpose other than
complicating matters.
> /*----------------------------------------------------*/
> }
> }
>
> I'm trying to declare an array of pointers using the above structure to
> create a special trinary tree. I was wondering why I cannot set all pointers
> to NULL in the array of pointers that I declared.
Depending on the properties and context for creating that tree the structure
you define can take several widely different forms. First figure out what is
known at the time of creating or generating one single node.
If you know how many subnodes a node is supposed to have when you generate it
you can create all those subnodes in one chunk and have one single pointer to
point to all of them. This is by far the most efficient way to make a
semi-general tree. The main drawback is that it is not easy to insert or
remove a nodes in such a tree once it is created.
Note that this method is more useful than you think in that a problem that may
not seem to be able to use such a way to create the tree can be made into one.
1. Create the root node (it is always one so we know how many nodes to create
here).
2. Call a function to fill data into the root node.
3. The function in (2) will among other things figure out how many subnodes
under the root there is.
4. Create the subnodes of the current node since you know how many you need
from (3).
5. Call the function in (2) recursively for each of the subnodes created at
(4).
If you want full flexibility then an array of pointers to the subnodes for a
ternary (it is ternary not trinary as far as I know) is needed. If the number
of subnodes may vary a lot and is indefinite you must use a list (single
linked or double linked - take your pick) or a growable/shrinkable array.
A list is not that difficult since each node will simply have a pointer to
subnodes and also to siblings so that the sibling pointer is in the nodes
themselves:
struct NODE { struct NODE * parent; /* Only present if you need it */
struct NODE * next_sibling; /* Or just 'sibling' if single linked list */
struct NODE * prev_sibling; /* Only present if you need it */ struct NODE *
first_child; /* Of just 'child' if you don't need last_child */ struct NODE
* last_child; /* Only present if you need it */ /* Other node data */ };
It may appear to be many pointers but many of them are marked 'Only present if
you need it' so it doesn't have to be as many pointers as shown above.
Also note that there are a zillion or so variations of the scheme. For one
thing: A pointer in a data structure doesn't have to be a pointer. I.e. it
doesn't have to be a C pointer data type. In the scheme described here the
integer ptr function as a pointer for all practical purposes.
struct NODE {
int ptr;
/* Other node data */
};
struct NODE * get_node(int ptr)
{
/*
Function that can compute a node address based on the integer value ptr
*/
}
ptr above is declared as an 'int' but as far as the data structure is
concerned it is a pointer. In fact any pattern of bits that allow you to use
them as input to some function or algorithm to compute a location of some
data is a pointer in this context. For this reason: if your data structure
calls for a pointer don't be too fast to declare a struct NODE * data type
immediately. It MIGHT be the best way but then again it might NOT be the
best. This is a case by case problem with no definite answer.
>
> Many thanks in advance.
You're welcome.
>
> --
>
-------------------------------------------------------------------------------
> msim __ __ ____ ___ ___ ____
> ms...@primenet.com /__)/__) / / / / /_ /\ / /_ /
> / / \ / / / / /__ / \/ /___ /
>
-------------------------------------------------------------------------------
>
Alf
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum