my knowledge is limited but I have been working (hacking) at this specific data structure for awhile
I use a trie to store ontology strings that are then returned as a stack including the 'gap' proximity when get (string) is called. As an add on the trie stores attributes on the key. The further down the string the greater the detail of the attribute. This is working well for my purposes.
As an additional add on, I use a wildcard to apply an attribute to all child nodes. For example, to add 'paws' to all subnodes of 'mammals.dogs.' I push(mammals.dogs.*.paws). Now, all dogs have paws.
The problem is only the first dog get paws. The function works for push attributes without wild
If you want I can clean this up and give a simplified version, but in the past i've found on stackoverflow it is better to just give the code; I use 'z' as the '*' wild
void Trie::push(ParseT & packet)
{
if (root==NULL) AddFirstNode(); // condition 1: no nodes exist, should this be in wrapper
const string codeSoFar=packet.ID;
AddRecord(root, packet, codeSoFar); //condotion 2: nodes exist
}
void Trie::AddFirstNode(){ // run-once, initial condition of first node
nodeT *tempNode=new nodeT;
tempNode->attributes.planType=0;
tempNode->attributes.begin = 0;
tempNode->attributes.end = 0;
tempNode->attributes.alt_end = 0;
root=tempNode;
}
//add record to trie with mutal recursion through InsertNode
//record is entered to trie one char at a time, char is removed
//from record and function repeats until record is Null
void Trie::AddRecord(nodeT *w, ParseT &packet, string codeSoFar)
{
if (codeSoFar.empty()) {
//copy predecessor vector at level n, overwrites higher level vectors
if (!packet.predecessorTemp.empty())
w->attributes.predecessorTemp = packet.predecessorTemp;
return; //condition 0: record's last char
}
else { //keep parsing down record path
for (unsigned int i = 0; i < w->alpha.size(); i++) {
if (codeSoFar[0] == w->alpha[i].token_char || codeSoFar[0] == 'z') {
return AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
InsertNode(w, packet, codeSoFar); //condition 3: no existing char --> mutal recursion
}
}
//AddRecord() helper function
void Trie::InsertNode(nodeT *w, ParseT &packet, string codeSoFar) // add new char to vector array
{
for (unsigned int i=0; i <=w->alpha.size(); i++) { // loop and insert tokens in sorted vector
if (i==w->alpha.size() || codeSoFar[0] < w->alpha[i].token_char) { //look for end of vector or indexical position
//create new TokenT
tokenT *tempChar=new tokenT;
tempChar->next=NULL;
tempChar->token_char=codeSoFar[0];
//create new nodeT
nodeT *tempLeaf=new nodeT;
tempLeaf->attributes.begin = 0;
tempLeaf->attributes.end = 0;
tempLeaf->attributes.planType = 0;
tempLeaf->attributes.alt_end = 0;
//last node
if (codeSoFar.size() == 1){
tempLeaf->attributes.predecessorTemp = packet.predecessorTemp;
}
//link TokenT with its nodeT
tempChar->next=tempLeaf;
AddRecord(tempLeaf, packet, codeSoFar.substr(1)); //mutual recursion --> add next char in record, if last char AddRecord will terminate
w->alpha.insert(w->alpha.begin()+i, *tempChar);
return;
}
}
}
root is global nodeT *w
struct ParseT {
string ID; //XML key
int begin = 0; //planned or actual start date
int end = 0; //planned or actual end date - if end is empty then assumed started but not compelted and flag with 9999 and
int alt_end = 0; //in case of started without completion 9999 case, then this holds expected end
int planType = 0; //actuals == 1, forecast == 2, planned == 3
map<string, string> aux;
vector<string> resourceTemp;
vector<string> predecessorTemp;
};
In this code
for (unsigned int i = 0; i < w->alpha.size(); i++) {
if (codeSoFar[0] == w->alpha[i].token_char || codeSoFar[0] == 'z') {
return AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
you are returning as soon as you call AddRecord
, even if it is because of a wildcard. It might be easier to have a separate loop when codeSoFar[0] == 'z'
that goes through all the alphas and adds the record. Then have an else clause that does your current code.
Edit: Here is what I meant, in code form:
else { //keep parsing down record path
// Handle wildcards
if (codeSoFar[0] == 'z') {
for (unsigned int i = 0; i < w->alpha.size(); i++) {
AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
else {
// Not a wildcard, look for a match
for (unsigned int i = 0; i < w->alpha.size(); i++) {
if (codeSoFar[0] == w->alpha[i].token_char) {
return AddRecord(w->alpha[i].next, packet, codeSoFar.substr(1)); // condition 2: char exists
}
}
InsertNode(w, packet, codeSoFar); //condition 3: no existing char --> mutal recursion
}
}