I don't kill flies, but I like to mess with their minds. I hold them above globes. They freak out and yell "Whooa, I'm *way* too high." -- Bruce Baum
1
2
3
| my_struct_s **array; *array = malloc(sizeof(my_struct_s)*aantalstructs); (*array)[i].blablabla = 1; |
zoiets...
Verwijderd
my_struct *array[MAX_VAL];
...geheugen vrijmaken:
array[8]=new my_struct;
...en vrijgeven:
delete array[8];
Althans, zo doe ik dat normaal. Ik zorg gewoon dat MAX_VAL een waarde heeft, die ik zeker niet zal overschrijden...
Maar zoals ik zei, dat is C++. Ik weet niet of je het daar ook over hebt...
Verwijderd
1
| my_struct_s struct; |
Wat jij declareert is enkel een pointer.
Hieruit volgt voor een dynamische array van structs:
1
2
3
4
| my_struct_s* structs; structs = malloc(sizeof(my_struct_s) * amount); structs[20].value = 684; |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| typedef struct node {
int max;
boolean has_sub_nodes;
struct node *small;
struct node *big;
} node_t;
typedef struct {
int count;
node_t *tree[1];
} treelist_t;
int main (){
treelist_t list;
list = (treelist_t *) malloc (sizeof(treelist_t));
list->count = 1;
list->tree[0] = (node_t *) malloc(sizeof(node_t));
list->tree[0]->max=3;
list->tree[0]->small = (node_t *) malloc(sizeof(node_t));
list->tree[0]->big = (node_t *) malloc(sizeof(node_t));
list->tree[0]->has_sub_nodes = 1;
...
free(list->tree[0]->big);
free(list->tree[0]->small);
free(list->tree[0]);
free(list);
return 0;
} |
Nu kan ik e.e.a. zo benaderen:
1
2
3
| list->count;
printf("%d\n", list->tree[0]->max);
list->tree[0]->small->max = 2; |
En ik vind het prima als ik slechts een pointer definieer, dat scheelt toch weer het kopieeren van gegevens als ik ze als parameter gebruik?
In ieder geval werkt wat ik nu heb staan, enkel moet ik bij de declaratie van "list" dit opgeven:
1
| list = (treelist_t *) malloc (2*sizeof(treelist_t)); |
Ik reserveer dus teveel geheugen, waardoor ik wat 'speel ruimte' heb voor andere geheugen fouten, maar dat is niet echt de oplossing.
Als ik malloc goed aan het werk heb lukt realloc ook wel (die gebruik ik al vor list->tree[1] e.d.). En een MAXVAL constante is geen optie, want de array omvang kan tussen 2 en 1024 liggen (vandaar ook de vraag dynamische arrays
I don't kill flies, but I like to mess with their minds. I hold them above globes. They freak out and yell "Whooa, I'm *way* too high." -- Bruce Baum
Aha dus je wil gewoon botweg een nested tree. Wat niets aan je probleem verandert (!!!) want het is niets anders dan dat: nested, en dus hetzelfde probleem als een platte dynamische array maar dan toevallig in elkaar gefrot. Not a single difference to be found...Op vrijdag 26 april 2002 16:52 schreef ajvdvegt het volgende:
Excuses, ik had m'n probleem te ver versimpeld. Ik wil een struct definieren met een array van (andere) structs daarin:
Uhmmmmmmmmm ik twijfel als ik dit lees of je het concept pointers en declaraties wel 100% doorhebt. Het doorgeven van een struct by-pointer kan ook als volgt met de address-of operator oftewel de ampersand:En ik vind het prima als ik slechts een pointer definieer, dat scheelt toch weer het kopieeren van gegevens als ik ze als parameter gebruik?
1
2
3
4
5
6
7
8
9
10
11
| void DoSomething(TreeNode* p_TreeNode)
{
p_TreeNode->Elements... etc.
}
int main()
{
TreeNode l_MyTreeNode;
DoSomething(&l_MyTreeNode);
} |
Maar volgens mij heb je gewoon nog weinig idee over hoe je een tree opzet... toch?
Sowieso heb je overigens die has_sub_nodes property niet nodig daar dat automatisch volgt uit het al of niet NULL zijn van je beide subnodelists (indien goed opgezet
De beste manier imho:
1
2
3
4
5
6
7
8
9
| struct TreeNode
{
// Zut
TreeNode* m_First;
TreeNode* m_Last;
TreeNode* m_Previous;
TreeNode* m_Next;
}; |
Hiermee vorm je een nested linked list die add-to-tail, add-to-head en probleemloze by-pointer recursies toestaat, wat volgens mij exact je bedoeling is, EN je hebt niet het geemmer met dynamische pointerarrays.
Verwijderd
Als je add-to-head/tail doet moet je vervolgens alle treeNodes updaten. Ik vind het moier als je gewoon een linkedlist idee gebruikt, dus:Op zaterdag 27 april 2002 01:37 schreef curry684 het volgende:
De beste manier imho:
code:
1 2 3 4 5 6 7 8 9struct TreeNode { // Zut TreeNode* m_First; TreeNode* m_Last; TreeNode* m_Previous; TreeNode* m_Next; };
Hiermee vorm je een nested linked list die add-to-tail, add-to-head en probleemloze by-pointer recursies toestaat, wat volgens mij exact je bedoeling is, EN je hebt niet het geemmer met dynamische pointerarrays.
1
2
3
4
5
6
7
| struct TreeNode
{
// Zut
TreeNode* m_Previous;
TreeNode* m_Next;
}; |
En dan while (tree->m_Previous) tree = tree->m_Previous; om bij de eerste te komen, en m_Next voor de laatste... Dat scheelt weer wat zut.
Maak 'm dan cyclisch, dan kun je in constante tijd elementen aan 't begin en 't eind toevoegen. (Zonder while-lusje dus).Op zaterdag 27 april 2002 09:54 schreef beelzebubu het volgende:
Als je add-to-head/tail doet moet je vervolgens alle treeNodes updaten. Ik vind het moier als je gewoon een linkedlist idee gebruikt
...
En dan while (tree->m_Previous) tree = tree->m_Previous; om bij de eerste te komen, en m_Next voor de laatste...
Verwijderd
Op zaterdag 27 april 2002 14:48 schreef Soultaker het volgende:
Maak 'm dan cyclisch, dan kun je in constante tijd elementen aan 't begin en 't eind toevoegen. (Zonder while-lusje dus).
Dan zit er geen volgorde meer in welke de eerste is en welke de laatste...
Of snap ik je nu verkeerd?
nou de volgorde blijft hetzelfde, maar het begin en eindpunt is niet meer bekend... of tenminste, tree->m_Next wijst naar de laatste, maar als je een willekeurige node hebt kun je vandaar uit niet de eerste of laatste vinden.Op zaterdag 27 april 2002 16:20 schreef beelzebubu het volgende:
[..]
.
Dan zit er geen volgorde meer in welke de eerste is en welke de laatste...
Of snap ik je nu verkeerd?.
Maar het punt is nou juist dat het laatste element weer naar de eerste wijst, dus als tree->m_Next de laatste is, dan is tree->m_Next->m_Next de eerste
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Nee, ook dat is niet waar. Het begin- en eindpunt ligt nog steeds vast. In elke 'schakel' hou ik een pointer bij naar het volgende en vorige element, maar dan cyclisch: het volgende element van het laatste element is het eerste element, het vorige element van het eerste element is het laatste element:Op zaterdag 27 april 2002 16:34 schreef .oisyn het volgende:
nou de volgorde blijft hetzelfde, maar het begin en eindpunt is niet meer bekend...
1
2
3
4
5
6
7
8
| | pointer naar eerste element
|
v
Normaal:
1 -> <- 2 -> <- 3
Cyclisch:
... 3 -> <- 1 -> <- 2 -> <- 3 -> <- 1 ... |
Net zoals in de niet-cyclische variant, werk ik met een pointer die het eerste element aanwijst. Ik kan dus altijd een eerste en een laatste element (dit is het element met het eerste element als volgende) aanwijzen en de volgorde is ook behouden. Ik kan nu echter wel efficient elementen invoegen aan het begin, omdat ik een enkele stap naar het laatste element kan springen (dat is immers het vorige element van het eerste element).
Ik vermoed dat dit niet de meest heldere uitleg is die ik ooit heb geschreven, maar ik hoop dat het idee toch duidelijk is.
let ook even op het stukje: maar als je een willekeurige node hebt kun je vandaar uit niet de eerste of laatste vinden.Op zaterdag 27 april 2002 18:19 schreef Soultaker iets
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Kan je dan niet beter een variant maken waarvan de root-node (of whatever) zowel de eerste als de laatste aanwijst. En verder elke node alleen "links en rechts" aanwijst. Zodat je even snel voorwaarts als achterwaarts kan zoeken in je lijst EN je altijd de eerste en laatste weet? (Het is sowieso vrij lastig als je de root-node kwijtraakt, dus dat moet je toch wel voorkomenOp zaterdag 27 april 2002 18:19 schreef Soultaker het volgende:
Cyclisch:
Imho is cyclisch niet echt jouw 2e voorbeeld, maar je eerste met dien verstande dat punt 3 weer naar 1 wijst (en andersom).
En in welke situatie vormt dit dan een probleem? Meestal geef je alleen de pointer naar de eerste node mee en niet een willekeurige node. Als je toch een willekeurige node meegeeft, kun je ook wel de eerste node meegeven om te weten waar het begin zit. Ik kan me echter niet herinneren dit ooit nodig gehad te hebben.Op zaterdag 27 april 2002 18:23 schreef .oisyn het volgende:
let ook even op het stukje: maar als je een willekeurige node hebt kun je vandaar uit niet de eerste of laatste vinden.
Dat snap ik niet helemaal. Wat is een root-node dan? In de tot nu toe gegeven mogelijkheden zijn alle nodes gelijk.Op zaterdag 27 april 2002 18:23 schreef ACM het volgende:
Kan je dan niet beter een variant maken waarvan de root-node (of whatever) zowel de eerste als de laatste aanwijst. En verder elke node alleen "links en rechts" aanwijst. Zodat je even snel voorwaarts als achterwaarts kan zoeken in je lijst EN je altijd de eerste en laatste weet? (Het is sowieso vrij lastig als je de root-node kwijtraakt, dus dat moet je toch wel voorkomen)
Eigenlijk snap ik dit ook niet =) Het eerste voorbeeld is niet cyclisch, het tweede wel. In het eerste geval zijn punt 1 en 3 niet verbonden, in het tweede wel.Imho is cyclisch niet echt jouw 2e voorbeeld, maar je eerste met dien verstande dat punt 3 weer naar 1 wijst (en andersom).
Mja, ergens hou je bij dat je een lijst hebt (zou een leuke bug zijn als je dat vergeetOp zaterdag 27 april 2002 18:31 schreef Soultaker het volgende:
Dat snap ik niet helemaal. Wat is een root-node dan? In de tot nu toe gegeven mogelijkheden zijn alle nodes gelijk.
Aargh, misschien dat ik es beter moet lezenEigenlijk snap ik dit ook niet =) Het eerste voorbeeld is niet cyclisch, het tweede wel. In het eerste geval zijn punt 1 en 3 niet verbonden, in het tweede wel.
Een of andere struct die de rest 'omvat' dus zegmaar? Tja, dat zou je inderdaad kunnen doen, maar het lijkt me hier geen toegevoegde waarde bieden. Wat je daar wel weer handig in op zou kunnen slaan, is het aantal elementen in je lijst.Op zaterdag 27 april 2002 18:35 schreef ACM het volgende:
Mja, ergens hou je bij dat je een lijst hebt (zou een leuke bug zijn als je dat vergeet). Dat "bijhouden" zou je als de root-node kunnen zien.
Het weekend is voorbij, dus daar ben ik weer.... Ten eerste: ik heb het concept van pointers e.d. niet helemaal door, dat klopt. Ik ben Delphi gewend, en daar heb je geeen 'last' van pointers als je er niet zelf om gaat vragenOp zaterdag 27 april 2002 19:04 schreef Soultaker het volgende:
[..]
Een of andere struct die de rest 'omvat' dus zegmaar? Tja, dat zou je inderdaad kunnen doen, maar het lijkt me hier geen toegevoegde waarde bieden. Wat je daar wel weer handig in op zou kunnen slaan, is het aantal elementen in je lijst.
Ten tweede was het idee dat ik een bijzondere vorm van een linked-list ga maken, namelijk een boom (een 2-3-boom om precies te zijn, maar dat doet er even niet toe). Elke node houdt nu ook al een verwijzing naar zijn 'kinderen' en zijn 'parent' bij, en de node zonder parent is de root van de boom. (ik heb ook een functie gemaakt die me vanaf een willekeurige node op zoek gaat naar de root door steeds de parent te volgen).
Elk element in mijn array (treelist_t in mijn code) is dus de root van een boom.
Een cyclische oplossing voor de lijst van bomen is trouwens niet handig, ik wil ze graag kunnen indexeren.
Als ik ook de laatste foutjes er uit heb zal ik de code hier wel posten, om mijn idee helder te krijgen (die posting zal zeer waarschijnlijk enkel een uitbreiding van mijn eerdere post zijn trouwens).
I don't kill flies, but I like to mess with their minds. I hold them above globes. They freak out and yell "Whooa, I'm *way* too high." -- Bruce Baum
ho ho, ik heb nooit gezegd dat dat een probleem vormde, ik lichtte het gewoon toe voor beelzebubuOp zaterdag 27 april 2002 18:31 schreef Soultaker het volgende:
[..]
En in welke situatie vormt dit dan een probleem? Meestal geef je alleen de pointer naar de eerste node mee en niet een willekeurige node. Als je toch een willekeurige node meegeeft, kun je ook wel de eerste node meegeven om te weten waar het begin zit. Ik kan me echter niet herinneren dit ooit nodig gehad te hebben.
Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.
Uhm waarom quote je nu exact mijn code minus het gedeelte wat het een tree maakt?!?Op zaterdag 27 april 2002 09:54 schreef beelzebubu het volgende:
Als je add-to-head/tail doet moet je vervolgens alle treeNodes updaten. Ik vind het moier als je gewoon een linkedlist idee gebruikt, dus:
code:
1 2 3 4 5 6 7struct TreeNode { // Zut TreeNode* m_Previous; TreeNode* m_Next; };
En dan while (tree->m_Previous) tree = tree->m_Previous; om bij de eerste te komen, en m_Next voor de laatste... Dat scheelt weer wat zut..
Het idee is dat je een AddChildToTail kunt doen als volgt:
1
2
3
4
5
6
| l_NewNode->m_Previous = l_Parent->m_Last; if(l_Parent->m_Last) l_Parent->m_Last->m_Next = l_NewNode; else l_Parent->m_First = l_NewNode; l_Parent->m_Last = l_NewNode; |
Ongeveer (notepad de gekste...)