私は100、1000、または10000の長いリンクリストでテストするときに動作する次のマージソートアルゴリズムを持っています。ただし、100000または1000000の長いリンクリストを使用すると、Node->Next=Merge(Front,Back->Next,Type);
を含む行にセグメンテーション違反が返されます。これは、セグメント化エラーではなくスタックオーバーフローであると私に信じさせてくれました。エラー時のgdbによると、スタックは非常に満杯です。正確な数字を与えるためにコールスタックにあるアイテムの数を正確に調べる方法は見つけられません。大量のデータを処理するマージソートのリワークに関する助けがあれば、大歓迎です。大量のデータに対してマージソートを使用すると、スタックオーバーフローを防ぐ方法を教えてください。
struct IntList
{
int Value;
int Frequency;
struct IntList* Next;
struct IntList* Prev;
};//Struct for Integer Linked List
void SortList(struct IntList** Values,enum SortBy Type)
{
struct IntList* Head = *Values;
if(Head==NULL||Head->Next==NULL)
{
return;
}//If Base Case
struct IntList* Front;
struct IntList* Back;
Split(Head,&Front,&Back);//Splits Linked List
SortList(&Front,Type);
SortList(&Back,Type);//Recursively Sorts
*Values=Merge(Front,Back,Type);//Merges Halves
return;
}
void Split(struct IntList* Head,struct IntList** Front,struct IntList** Back)
{
struct IntList* Fast;
struct IntList* Slow;
if (Head==NULL||Head->Next==NULL)
{
*Front=Head;
*Back=NULL;
}//If Length <2
else
{
Slow=Head;
Fast=Head->Next;
}
while(Fast!=NULL)
{
Fast=Fast->Next;
if(Fast!=NULL)
{
Fast=Fast->Next;
Slow=Slow->Next;
}
}//Find Midpoint
*Front=Head;
*Back=Slow->Next;
Slow->Next=NULL;//Breaks Link
return;
}
struct IntList* Merge(struct IntList* Front,struct IntList* Back,enum SortBy Type)
{
if(Front==NULL)
{
return Back;
}
if (Back==NULL)
{
return Front;
}//Base Cases
struct IntList* Node;
if(Type==DATA)
{
if(Front->Value <= Back->Value)
{
Node=Front;
Node->Next=Merge(Front->Next,Back,Type);
}
else
{
Node=Back;
Node->Next=Merge(Front,Back->Next,Type);
}//Takes Greatest Value for Sorted List
}//If Sorting by Data
if(Type==FREQUENCY)
{
if(Front->Frequency < Back->Frequency)
{
Node=Front;
Node->Next=Merge(Front->Next,Back,Type);
}
else
{
Node=Back;
Node->Next=Merge(Front,Back->Next,Type);
}//Takes Greatest Frequency for Sorted List
}//If Sorting by Frequency
return(Node);
ストップ再帰を使ってリストをマージする。それを繰り返します。 – user2357112
あなたのホストファイルでそれをブロックすることができます、あなたはペアレンタルコントロールアプリを使用することができます...ああ!あなたは*リテラル*スタックのオーバーフローを意味しました!まあ、その場合、user2357112が正しいです。あなたはおそらく再帰制限に達しました。 ;-) –
再帰を使用すると、エレガントなコードが生成されますが、ここでは手間と制限があります。 'gdb'のsegfault(または任意のブレークポイント)で' bt'(バックトレースの略)と打つことができます。コールスタックを出力します。これを知っているかどうかを_quiiite_ tellできません。 – yano