Question

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;
    };

This is what I

Was it helpful?

Solution

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
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top