C++ 是否在链表中按顺序插入节点?

C++ 是否在链表中按顺序插入节点?,c++,linked-list,C++,Linked List,我正在尝试编写一个成员函数,Link*add\u ordered(Link*n),它以字典顺序在列表中添加一个节点,但是,当我尝试打印有序列表时,只打印最后添加的节点,即“Poseidon” 以下是我的节点界面的外观: struct God { // public members of God std::string name; std::string mythology; std::string vehicle; std::string weapon;

我正在尝试编写一个成员函数,
Link*add\u ordered(Link*n)
,它以字典顺序在列表中添加一个节点,但是,当我尝试打印有序列表时,只打印最后添加的节点,即
“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::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;
}
Link*Link::添加订单(Link*n){
//检查节点是否有效
如果(n==0),则返回该值;
如果(this==0)返回n;
//指向此对象的指针
Link*p=这个;
//按字母顺序按链接的神的名字递增
while(p){
//如果新节点值小于当前节点中的值,请在当前节点之前插入。
如果(n->god.namegod.name){
插入(n);
打破
//否则,转到列表中的上一个节点
}否则{
p=上一个;
}
} 
//返回新添加的有序链接
返回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 <<"}";
}
int main(){
//神(名字(n)、神话(m)、交通工具(v)、武器(w))
//希腊神话中的众神名单
Link*希腊神=新链接(神(“宙斯”、“希腊”、“闪电”);
希腊众神=希腊众神->添加(新链接(神(“赫拉”,“希腊”));
希腊众神=希腊众神->添加(新链接(神(“雅典娜”,“希腊”));
希腊众神=希腊众神->添加(新链接(神(“战神”,“希腊”));
希腊神=希腊神->添加(新链接(神(“波塞冬”,“希腊”));
//打印列表

std::cout
Link::add_ordered
始终返回其参数(或者
this
如果参数为空,则不会在您的案例中执行该分支)

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

程序中的行将不断使希腊神指向插入的链接。

根据@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;
}
Link*Link::添加订单(Link*n){
//检查节点是否有效
如果(n==0),则返回该值;
如果(this==0)返回n;
//指向此对象的指针
Link*p=这个;
//如果节点已排序,请将其添加到列表前面
如果(n->god.namegod.name){
添加(n);
//返回列表的当前第一个节点
返回n;
}
//遍历现有列表,直到新节点的名称小于当前节点的名称
而(!(n->god.namegod.name)和&p){
//上一节点
链路*温度=p;
//如果最后一个节点的名称小于新节点的名称,请在末尾添加新节点
如果(!(p=p->prev)){
n->prev=nullptr;
n->succ=温度;
温度->上一个=n;
归还这个;
}
} 
//在当前节点前面添加n
n->succ=p->succ;
n->prev=p;
如果(p->succ){
p->succ->prev=n;
}
p->succ=n;
//返回当前第一个节点
归还这个;
}

我应该“倒带”吗
希腊众神
在使用它打印列表之前指向一个结束链接?我的想法是,似乎只有最后一个节点存在,与任何其他节点分离…我是否应该在列表的开头指向
希腊众神
在每次将节点插入正确位置后?它是否应该是
无效添加顺序()?
我不知道(但我的猜测是:不,
add_ordered
不应返回
void
)。您需要确定返回值指示的内容。我的印象是您希望它成为列表的新开始。例如,在调用
a=b->add_ordered(c);
中,
a
的值将是
b
(如果添加的链接
c
大于
b
),或者它将是
c
(如果添加的链接小于
b
)…因此,
add\u ordered
返回*this;
返回n;
。如果给定链接大于
*this
,则前者应发生。如果给定链接小于
*this
(即,它成为列表的新标题),则后者应发生。
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;
}