在链接列表中按顺序插入节点?

时间:2015-12-18 13:09:42

标签: c++ linked-list

我正在尝试编写一个成员函数Link* add_ordered (Link* n),它在列表中以字典顺序添加节点,但是,当我尝试打印有序列表时,只打印最后添加的节点,即{ {1}}。

以下是我的节点界面的样子:

"Poseidon"

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; }; 中使用的成员函数:

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

以下是我尝试创建有序双链表的方法:

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

我已经尝试了一段时间使它工作,但没有成功,所以任何帮助都会非常感激。我真的看不出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 <<"}"; } 有什么问题。

P.S。如果我使用add_ordered()add()创建相同的列表,则整个列表将完美打印。

2 个答案:

答案 0 :(得分:1)

Link::add_ordered总是返回其参数(如果参数为null,则返回this,但在您的情况下不执行该分支)。因此,所有

greek_gods = greek_gods->add_ordered(new Link(God("Hera", "Greek" )));
程序中的

行将不断使greek_gods指向插入的链接。

答案 1 :(得分:0)

根据@Frerich Raabe的评论,函数add_ordered()被修改,以便始终返回列表的起始节点。此外,添加了新的条件if语句来检查新节点是否已按顺序排列,如果是,则将其添加到列表前面:

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;

    // if node already in order, add it in front of the list
    if (n->god.name < p->god.name) {
        add(n);

        // return current first node of the list
        return n;
    }

    // traverse existing list till new node's name smaller than current node's
    while (!(n->god.name < p->god.name) && p) {

        // previous node
        Link* temp = p;

        // if last node's name is smaller than new node's, add new at the end 
        if (!(p = p->prev)) {
            n->prev = nullptr;
            n->succ= temp;

            temp->prev = n;
            return this;
        }
    } 

    // add n in front of current node
    n->succ = p->succ;
    n->prev = p;

    if (p->succ){
        p->succ->prev = n;
   }

   p->succ = n;

   // return current first node
   return this;
}