插入到有序LLL中

inserting into ordered LLL

本文关键字:LLL 插入      更新时间:2023-10-16

到目前为止,我已经能够正确地将项目添加到线性链表中,但我无法比较列表中两个不同位置的数据成员,以便找到插入新节点的正确位置。我试图创建一个伪指针,这样当我获得线性链表中的下一个对象时,就不会丢失任何数据,这样我就可以比较当前项和以前项。但是,上一个项只是被新项覆盖。如何在不重写最后一个对象的情况下创建一个伪指针来存储数据?(代码如下)

int political_party::insert_republican_party(candidate_info & a_candidate) {
    republican_party * current = new republican_party();    //intiates the new node 
    current->a_candidate = a_candidate;                   //gives the new node a perticular value: 
    current->next = NULL;                                 // declares next the next as null 
    if (rep_head == NULL)                                    //no nodes exist so far
    {
        current->next = rep_head;                     //the node after current contains the value rep_head
        rep_head = current;                             //rep head equals the value of current
    }
    else if (rep_head->next == NULL) {
        republican_party * current2 = rep_head;
        current2 = current2->next;
        republican_party * previous = rep_head;
        // previous -> a_candidate = current -> a_candidate;
        // current -> a_candidate = a_candidate;           
        if (current->a_candidate.get_rank() > previous->a_candidate.get_rank()) {
            current->next = rep_head;
            rep_head = current;
        }
    }
    else {
        republican_party * current2 = rep_head;
        while (current->next != NULL) {
            current = current->next;
        }
        current->next = current2->next;
        current2->next = current;
        return 2;
    }
}

欢迎使用C++,欢迎使用StackOverflow。

你还有一些障碍需要克服,所以我要做以下几点:
1) 对代码进行一些观察。
2) 然后,我将向您展示一些使用eough"打印"运行的示例代码,这样您就可以知道发生了什么。
3) 然后,我将以一两个关于如何继续的提示结束。

我想让你学到的一件大事是学习如何在代码中放入足够的打印输出,这样你就可以了解正在发生的事情。它们不一定很漂亮,它们只是用来帮助您排除故障的,然后您可以对它们进行评论。

1) 对代码的观察

这会有点长,我正在包括你的代码版本来谈谈它。

让我们勾勒出你发布的代码将如何运行:

0: (step 0, the beginning)
    rep_head = NULL
    pretty much an empty list.
1: insert_republican_party( c1 );
   current points to c1
   execute /*A*/ if() block since rep_head is null (see below for /*A*/,
   I might edit the original question to have these values for discussion).
   after:
      rep_head = current, so...
      rep_head points to c1.
      rep_head next = NULL
   at the end of /*A*/ if-block, the list looks something like this:
      rep_head-----+
                   |
                   v
      current----> R[c1] ---next--> NULL
   I'm kind of smashing R (republican_party pointer) together with c1 (a_candidate reference).
2:  insert_republican_party( c2 );
    rep_head points to c1, rep_head.next = NULL
    current points to c2, current.next = NULL
    We execute the "/*B*/ else if() block" since rep_head->next == NULL.
       local var current2 gets pointed to same place rep_head points to.
       current2 then pointed to rep_head->next, so current2 = NULL
       At this point we don't do anything else with current2.
       we'll skip the commented-out lines.
       And you're looking to do an in-order insertion for your linked list based on candidate rank...
       so we have 3 possible conditions:
          maybe c1.rank < c2.rank
          maybe c1.rank == c2.rank
          maybe c1.rank > c3.rank
       The /*C*/ if statement is checking to see if c2.rank > c1.rank
       Suppose c2.rank > c1.rank then fine, c2 becomes the new head of the list.
         after that:
            current->next points to c1.
            rep_head points to c2.
            So the list might look like this, more or less (assuming c2.rank > c1.rank).
            rep_head---+
                       |
                       v
            current--> R[c2]--next--> R[c1]--next--> NULL
            At this stage your previous pointers seem out synch.
       Suppose c2.rank <= c1.rank, then... nothing happens and c2 never makes it onto your linked list.
       This seems like a hole.
       However I would recommend patching that hole in your else-block, /*E* below.

3:  insert_republican_party( c3 );
    Lets say we somehow get down to /*D*/ else.
    and this list looks like step 2, above.
    current is pointing to c3 (current.next points to NULL)
    rep_head is pointing to c2.
    rep_head.next is pointing to c1.
    current2 is pointed to same as rep_head, which means c2.
    the while() loop walks current down the linked list,
    which seems like a logic errror? Should it be walking current2 (instead of current)?

     int political_party::insert_republican_party(candidate_info & a_candidate)
     {
        republican_party * current = new republican_party(); //intiates the new node
        current -> a_candidate = a_candidate;                //gives the new node a perticular value:
        current -> next = NULL;                              // declares next the next as null
 /*A*/ if(rep_head == NULL)                                  //no nodes exist so far
        {
           current -> next = rep_head;                       //the node after current contains the value rep_head
           rep_head = current;                               //rep head equals the value of current
        }
 /*B*/  else if (rep_head -> next == NULL)
        {
           republican_party * current2 = rep_head;
           current2 = current2 -> next;
           republican_party * previous = rep_head;
           // previous -> a_candidate = current -> a_candidate;
           // current -> a_candidate = a_candidate;
 /*C*/     if(current -> a_candidate.get_rank() > previous -> a_candidate.get_rank())
           {
              current -> next = rep_head;
              rep_head = current;
           }
        }
 /*D*/  else
       {
           republican_party * current2 = rep_head;
 /*E*/     while(current -> next != NULL)
           {
              current = current -> next;
           }
           current -> next = current2 -> next;
           current2 -> next = current;
           return 2;
        }
     }

2) 运行的示例代码

我已经破解了一个相当粗糙的"linked_list.cpp"版本,它只有足够的代码来运行。我建议您采用打印输出部分(覆盖输出流<<,因为我们在c++领域)。然后将自由打印输出添加到代码中。在代码中搜索"ostream&"可以找到那些覆盖。

fwiw,如果你发布了足够的C++代码来运行,这会更容易评论;我鼓励你将来也这样做。

===开始样本输出===

$ c++ linked_list.cpp
$ ./a.out
Hello from main()
c1=C[c1, rank=1]
c2=C[c2, rank=1]
c3=C[c3, rank=1]
before, r=R[C[?, rank=-1]]--next--> NULL
after, r=R[C[c1, rank=1]]--next--> NULL
party=Party.rep_head=0
1. calling party.insert_republican_party( C[c1, rank=1] )
insert: adding current=0x1498c20, *current=R[C[c1, rank=1]]--next--> NULL
insert.A: now rep_head=0x1498c20, *rep_head=R[C[c1, rank=1]]--next--> NULL
1. party=Party.rep_head=0x1498c20---> R[C[c1, rank=1]]--next--> NULL
2. calling party.insert_republican_party( C[c2, rank=1] )
insert: adding current=0x1498c50, *current=R[C[c2, rank=1]]--next--> NULL
insert.B: now rep_head=0x1498c20
2. party=Party.rep_head=0x1498c20---> R[C[c1, rank=1]]--next--> NULL
$ 

===结束样本输出===

===开始链接列表.cpp===

#include<iostream>
// disclaimer: I'm not trying to solve anybody's homework problem.
// Just adding enough code (not even good style code at that) to make
// it run well enough to offer a hint or two.
using namespace std;
class candidate_info {
   public:
      int rank;
      const char *name;
      int get_rank() { return rank; }
      candidate_info( );
      candidate_info( int rank, const char *name );
      friend ostream& operator<<(ostream& os, const candidate_info& c);
};
class republican_party {
   public:
      republican_party * next;
      republican_party * prev;
      candidate_info  a_candidate;
      republican_party();
      friend ostream& operator<<(ostream& os, const republican_party& r);
};
class political_party {
   public:
      republican_party * rep_head;
      political_party();
      int insert_republican_party(candidate_info & a_candidate);
      friend ostream& operator<<(ostream& os, const political_party & p);
};
int main( int argc, char **argv ) {
   cout << "Hello from main()n";
   candidate_info c1( 1, "c1" );
   candidate_info c2( 1, "c2" );
   candidate_info c3( 1, "c3" );
   cout << "c1=" << c1 << "n";
   cout << "c2=" << c2 << "n";
   cout << "c3=" << c3 << "n";
   republican_party r;
   cout << "before, r=" << r << "n";
   r.a_candidate = c1;
   cout << "after, r=" << r << "n";
   political_party party;
   cout << "party=" << party << "n";
   cout << "1. calling party.insert_republican_party( " << c1 << " )n";
   party.insert_republican_party( c1 );
   cout << "1. party=" << party << "n";
   cout << "2. calling party.insert_republican_party( " << c2 << " )n";
   party.insert_republican_party( c2 );
   cout << "2. party=" << party << "n";

}
// === CANDIATE_INFO things ===
candidate_info::candidate_info( ) {
   this->rank = -1;
   this->name = "?";
}
candidate_info::candidate_info( int rank, const char *name ) {
   this->rank = rank;
   this->name = name;
}
ostream& operator<<(ostream& os, const candidate_info& c)
{
    os << "C[" << c.name << ", rank=" << c.rank << "]";
    return os;
}
// === REPUBLICAN_PARTY things ===
republican_party::republican_party()
{
   next = prev = NULL;
}
ostream& operator<<(ostream& os, const republican_party& r)
{
    // note about flush: sometimes when I feed a bad pointer to this
    // it can blow up and hit "segmentation fault" so I'm adding
    // flushes here and there to give us an idea of how far along we
    // actually got before then.
    // I strongly encourage you to do something like << for all of your
    // classes to make it easier to see what is going on.
    // Maybe you did this already, dont know (didn't see the full
    // definition for republican_party and other classes).
    os << "R[" << flush << r.a_candidate << "]" << flush;
    republican_party *p = r.next;
    do {
       os << "--next--> ";
       if( p == NULL ) {
          os << "NULL";
       } else {
          os << " R[" << p->a_candidate << "]";
          p = p->next;
       }
    } while( p != NULL );
    return os;
}

// === POLITICAL_PARTY things ===
   political_party::political_party() {
      rep_head = NULL;
   }
   ostream& operator<<(ostream& os, const political_party & p) {
      os << "Party.rep_head=" << p.rep_head << flush;
      if( p.rep_head != NULL ) {
         os << "---> " << *p.rep_head;
      }
      return os;
   }
     int political_party::insert_republican_party(candidate_info & a_candidate)
     {
        republican_party * current = new republican_party(); //intiates the new node
        current -> a_candidate = a_candidate;                //gives the new node a perticular value:
        current -> next = NULL;                              // declares next the next as null
        cout << "insert: adding current=" << current << ", *current=" << *current << "n";
 /*A*/ if(rep_head == NULL)                                  //no nodes exist so far
        {
           current -> next = rep_head;                       //the node after current contains the value rep_head
           rep_head = current;                               //rep head equals the value of current
           cout << "insert.A: now rep_head=" << rep_head << ", *rep_head=" << *rep_head << "n";
        }
 /*B*/  else if (rep_head -> next == NULL)
        {
           republican_party * current2 = rep_head;
           current2 = current2 -> next;
           republican_party * previous = rep_head;
           // previous -> a_candidate = current -> a_candidate;
           // current -> a_candidate = a_candidate;
 /*C*/     if(current -> a_candidate.get_rank() > previous -> a_candidate.get_rank())
           {
              current -> next = rep_head;
              rep_head = current;
              cout << "insert.C: now rep_head=" << rep_head << "n";
           }
           cout << "insert.B: now rep_head=" << rep_head << "n";
        }
 /*D*/  else
       {
           republican_party * current2 = rep_head;
 /*E*/     while(current -> next != NULL)
           {
              current = current -> next;
              cout << "insert.E: current=" << current << "n";
              if( current != NULL ) {
                 cout << "   *current=" << current << "n";
              }
           }
           current -> next = current2 -> next;
           current2 -> next = current;
           cout << "insert.D: now rep_head=" << rep_head << "n";
           return 2;
        }
     }

===结束链接列表.cpp===

3) 关于如何进行的一些提示

我认为您实际上非常接近/E/while循环。

我鼓励您将精力集中在/E/while循环上,并注释掉前一个/A/和/1B/if块中的所有内容。现在就把它注释掉,因为在教while()循环如何确定新的candidate_info应该放在哪里之后,如果你想抢救并重复使用的话。

这有点复杂,因为"prev"链接部分还没有工作,所以我建议修复您的代码,以便--next-->工作(单链表)。然后返回并修改它,使得&lt--prev也有效(使其成为一个双链表)。

关于让"下一个"链接部分贯穿始终,需要考虑的一些问题。。。

假设你插入了c25(某个排名为25的候选人名称)。。

现有列表:rep_head-->R[c10]-next-->R[c20]-next-->R[c30]-next-->NULL目标列表:rep_head-->R[c10]-下一个-->R[c20]-下下一个-->R[c25]--下一个->R[c30]-下个-->NULL

问题1)你需要知道什么才能说出c25中的拼接位置?

问题2)如何修改/E/while循环以找到拼接点?提示:除了检查是否达到列表末尾,您还需要考虑什么?(例如,为什么我们希望c25在c20之后,但在c30之前?

问题3)您是否在寻找单个拼接点?或者,使用前后拼接点来解决问题会更容易吗?

您已经有了创建新R[]并将candidate_info放入其中的有效代码。下一步的处理有点粗糙,所以让我们最后集中讨论一下。

问题4)如图所示,在R[c25]中拼接,哪个R的下一个值需要更改?while循环如何找到这些值?

最后,要注意一些潜在的null值。

如果您在列表的开头插入,您的"之前"拼接点的值是多少?

如果您要添加到列表的末尾,您的"后"拼接点的值是多少?

插入空列表与同时插入开头和结尾有什么区别吗?

祝你好运,我认为来自cout<lt;打印后,你就能到达你想去的地方。