插入到有序LLL中
inserting into ordered LLL
到目前为止,我已经能够正确地将项目添加到线性链表中,但我无法比较列表中两个不同位置的数据成员,以便找到插入新节点的正确位置。我试图创建一个伪指针,这样当我获得线性链表中的下一个对象时,就不会丢失任何数据,这样我就可以比较当前项和以前项。但是,上一个项只是被新项覆盖。如何在不重写最后一个对象的情况下创建一个伪指针来存储数据?(代码如下)
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-->工作(单链表)。然后返回并修改它,使得<--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;打印后,你就能到达你想去的地方。
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 预处理器:插入结构名称中的前一个行号
- 在未初始化映射的情况下,将值插入到映射的映射中
- 如何在c++中只将键插入到bimap的一侧
- 如何将结构插入到集合中并打印集合的成员
- C++json插入数组
- Visual Studio 2019:插入多个C++风格的单行注释
- nlohmann-json将一个数组插入到另一个数组中
- 有效地使用std::unordered_map来插入或增加键的值
- 为字符串中每 N 个字符插入空格的函数没有按照我认为的方式工作?
- 正在插入动态数组
- 插入或删除时获取usb的dos_name
- 叮叮当当在修复时插入多个"覆盖"说明符
- 链表c++插入,所有情况都已检查,但没有任何工作
- 将重物插入std::map
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- 在数字之间插入 + 或 - 符号以使其等于整数
- 在字符串中插入空格
- 插入到有序LLL中