すでに回答のあるノードにアクセスしているため、直接回答としてコードがクラッシュしています。アクセスする以外に、既に削除されているノードを削除しています。この「ダブルフリー」は、ほぼいつでもクラッシュやその他の混乱を招くでしょう。 C/C++のヒープ機構を強く理解すれば、多くの悲惨さを取り除くことができます。勉強する価値があります。
要件が何であるかわかりませんが、あなたは循環リンクリストを確認しようとしています。私はなぜあなたが '検出'方法でノードのいずれかを削除しているのか明確ではない。あなたはループを壊そうとしていますか?もしそうなら、すべてのノードはまだリストに残っていますので、何も削除されません。ループバックするノードでnullptrの隣の - >を変更してください。
オリジナルのコード例です。私はあなたのコードをベースとして使用し、それをデバッグするためにgdbデバッガを使用して作成しました。効果的なソフトウェアエンジニアは、デバッガのマスターであり、それを受け入れます。コメントに記述されているように、最小、完全、および検証可能な例です。
「ユースケース」、ループなし、縮退ループ、長いループの例として、いくつかのテストを行いました。ソフトウェアエンジニアとして、私たちの仕事の大きな部分は、境界で頻繁に発生するエラーのケースを考えることです。私がカバーしていないものもあるかもしれません。
コメントに記載されているように、コンパイルや成功したユースケースは、欠陥のないソフトウェアではありません。信頼性を得るためには徹底したテストが必要です。このようなテストは、「ユニットテスト」と呼ばれることが多く、その件については多くの文献があります。
#include <iostream>
struct ListNode
{
int val;
ListNode* next;
};
//Look for a loop back to A
ListNode* detectCycle(ListNode* A) {
if(A == nullptr) // can't be a loop if list is empty
return nullptr;
ListNode* temp = A;
while(temp->next!=NULL && temp->next !=A){
temp = temp->next;
}
if(temp->next==NULL) {
return nullptr; // No loop
}
else {
return temp; // Node where loop starts, may be A itself
}
}
int main(int argc,char* arv[])
{
ListNode *a = new ListNode;
ListNode *loop = nullptr;
loop = detectCycle(a);
if(loop == nullptr)
std::cout << "Case 1 passed" << std::endl;
a->next = a;
loop = detectCycle(a);
if(loop == a)
std::cout << "Case 2 passed" << std::endl;
ListNode *b = new ListNode;
ListNode *c = new ListNode;
ListNode *d = new ListNode;
a->next = b;
b->next = c;
c->next = d;
d->next = a;
loop = detectCycle(a);
if(loop == d)
std::cout << "Case 3 passed" << std::endl;
loop = detectCycle(b);
if(loop == a)
std::cout << "Case 4 passed" << std::endl;
return 0;
}
あなたのプログラムのどの行でエラーが発生しているかご存知ですか? – NathanOliver
あなたのリストでループを見つけようとしているなら、なぜあなたは最初のループであなたのリストのすべてを踏んでいるのですか? –
デバッガを使用してコードステートメントをステートメントごとに進める方法を学ぶ必要があるようです。良いデバッガでは、プログラムを1行ずつ実行して、変数の値を見て、期待どおりにどこからずれているのかを監視することができます。これはプログラミングをする場合に不可欠なツールです。 –