到目前为止,我已经能够正确地将项目添加到我的线性链接列表中,但我无法比较列表中两个不同位置的数据成员,以便找到插入新节点的正确位置。我尝试创建一个虚拟指针,以便在我获得线性链表中的下一个对象时不会丢失任何数据,以便我可以比较当前和之前的项目。但是,之前的项目只会被新项目覆盖。如何在不写入最后一个对象的情况下创建存储数据的虚拟指针? (以下代码)
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;
}
}
答案 0 :(得分:0)
欢迎使用C ++,欢迎使用StackOverflow。
你有一些障碍要清除,所以我要做以下事情:
1)对你的代码做一些观察。
2)然后我将向您展示一些样本代码,这些代码与足够的"打印"所以你可以知道发生了什么。
3)然后,我将以一两个关于你如何继续的方式结束。
我希望您获得的最重要的事情是学习如何在代码中添加足够的打印输出,以便您可以了解正在发生的事情。 他们不必非常漂亮,他们只是帮助您排除故障,然后您可以对其进行评论。
这将有点长,我包括你的代码版本来讨论它。
让我们勾勒出您发布的代码将如何运行:
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;
}
}
我已经砍掉了一个非常粗糙的&#34; linked_list.cpp&#34;只有足够代码才能运行的版本。 我建议你采用打印输出部分(输出流的覆盖&lt;&lt;因为我们在c ++土地上)。 然后在代码中添加自由打印输出。搜索&#34; ostream&amp;&#34;在代码中找到那些覆盖。
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
$
===结束样本输出===
=== begin linked_list.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;
}
}
=== end linked_list.cpp ===
我认为你实际上与/ E / while循环相当接近。
我鼓励您将精力集中在/ E / while循环上,并注释掉之前的所有内容/ A /和/ B < / em> / if块。暂时注释一下,因为有些人如果想要在教你的while()循环之后想要抢救和重复使用,那么如何找出新的candidate_info应该去哪里。
这有点复杂,因为&#34; prev&#34;链接部分还没有工作,所以我建议修改你的代码,以便--next - &gt;作品(单链表)。 然后回来修改它,以便&lt; - prev--也可以工作(使它成为一个双向链表)。
要考虑制作&#34; next&#34;链接部分工作一直到...
我们假设你要插入c25(一些候选名称,等级为25)。
existing list: rep_head--> R[c10]--next--> R[c20]--next--> R[c30]--next--> NULL goal list: rep_head--> R[c10]--next--> R[c20]--next--> R[c25]--next--> R[c30]--next--> NULL
问题1)你需要知道在c25中拼接到哪里?
问题2)如何修改/ E / while循环以找到拼接点? 提示:除了检查命中列表末尾之外,还需要考虑什么? (例如,为什么我们希望c25在c20之后,但在c30之前?
问题3)您是否在寻找单个拼接点?或者在拼接点之前和之后解决它会更容易吗?
您已经拥有有效的代码来创建新的R []并将candidate_info放入其中。 接下来的处理有点粗糙,所以让我们关注一下。
问题4)如图所示拼接R [c25],哪个R具有需要改变的下一个值? 你的while循环如何找到这些值?
最后,需要注意一些潜在的空值。
如果您在列表的开头插入,那么&#34;之前的价值是多少?拼接点有吗?
如果您要添加到列表的末尾,那么&#34;之后会是什么价值?拼接点有吗?
插入空列表与插入开头和结尾之间有什么区别吗?
祝你好运,我认为从cout&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;打印你能够到达你想去的地方。