Insert nodes in order in the linked list?

advertisements

I am trying to write a member function, Link* add_ordered (Link* n) , that adds a node in a lexicographical order in a list, however, when I try to print the ordered list only the last added node is printed, i.e. "Poseidon".

Here is how my node interface looks like:

struct God {
    // public members of God
    std::string name;
    std::string mythology;
    std::string vehicle;
    std::string weapon;

    // constructor
    God (std::string n, std::string m, std::string v = " ", std::string w = " ")
        : name(n), mythology(m), vehicle(v), weapon(w) { }
};
//------------------------------------------------------------------------

class Link {
public:
    God god;

    // consructor
    Link (God g, Link* p = 0, Link* s = 0)
        : god(g), prev(p), succ(s) { } 

    // modifying member functions
    Link* insert (Link* n);
    Link* add (Link* n);
    Link* add_ordered (Link* n);
    Link* erase (void);
    Link* find (const std::string& v);

    // non - modifying member functions
    Link* advance (int n);

    const Link* find (const std::string& n) const;

    Link* previous () { return prev; }
    Link* next () { return succ; }

private:
    Link* prev;
    Link* succ;
};

Member function used in add_ordered():

Link* Link::insert (Link* n) {

    if (n == 0) return this;
    if (this == 0) return n;

    n->succ = this;
    n->prev = prev;

    if (prev) prev->succ = n;

    prev = n;

    return n;
}

Finally, here is the function that performs the node ordering:

Link* Link::add_ordered (Link* n) {

    // check if nodes valid
    if (n == 0) return this;
    if (this == 0) return n;

    // pointer to this object
    Link *p = this;

    // order in lexicographically increasing order in terms of link's god's name
    while (p) {

        // if new node value smaller than the one in current node, insert before current node.
        if (n->god.name < p->god.name){
            insert(n);
            break;

        // otherwise go to previous node in the list
        } else {
            p = prev;
        }
    } 

    // return the newly added, ordered Link
    return n;
}

Here is how I try to create an ordered doubly linked list:

int main () {

    // God(name(n), mythology(m), vehicle(v), weapon(w))
    // Greek mythology list of Gods

    Link* greek_gods = new Link(God("Zeus", "Greek", "", "lightning"));
    greek_gods = greek_gods->add_ordered(new Link(God("Hera", "Greek" )));
    greek_gods = greek_gods->add_ordered(new Link(God("Athena", "Greek")));
    greek_gods = greek_gods->add_ordered(new Link(God("Ares", "Greek")));
    greek_gods = greek_gods->add_ordered(new Link(God("Poseidon", "Greek" )));

   // print the list
   std::cout <<"{";

   while (greek_gods) {

       std::cout << greek_gods->god.name <<", "
                 << greek_gods->god.mythology <<", "
                 << greek_gods->god.vehicle <<", "
                 << greek_gods->god.weapon;

       // I've tried both directions, using greek_gods->next()
       if (greek_gods = greek_gods->previous()) std::cout <<'\n';
   }

   std::cout <<"}";
}

I've been trying for some time now to make it work, unsuccessfully, so any help would be much appreciated. I really can't see what is wrong with add_ordered().


P.S. If I create the same list using add() or insert(), the whole list gets printed perfectly.


Link::add_ordered always returns its argument (or this in case the argument is null, that branch is not executed in your case though). Hence, all the

greek_gods = greek_gods->add_ordered(new Link(God("Hera", "Greek" )));

lines in your program will constantly make greek_gods point to the inserted link.