これは、クイックソートアルゴリズムの実装で遭遇したコードです。ここで再帰がどのように機能するか説明していただけますか?
void quickSort(int arr[], int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = arr[(left + right) / 2];
/* partition */
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
}
}
/* recursion */
if (left < j)
quickSort(arr, left, j);
if (i < right)
quickSort(arr, i, right);
}
そして、これは宿題ではないことに注意してください。
「再帰がどのように機能しているか説明してください」とはどういう意味かわかりません。しかし、ここに行きます:
投稿した関数は、intの配列と2つのインデックスを受け取ります。配列全体をソートするのではなく、2つのインデックス間の一部のみをソートして、それらの外側にあるものはすべて無視します。つまり、同じ関数は、最初と最後のインデックスを渡した場合は配列全体をソートできます。配列の最初の要素のインデックスではないleft
値を渡した場合はサブ配列のみをソートできます。最後の要素のインデックスではないright
値。
ソートアルゴリズムは、よく知られているクイックソートです。ピボットとしては中央の要素を使用します(他の要素を使用することもできます)。配列をless than (or equal to) pivot
サブ配列とgreater than (or equal to) pivot
サブ配列に分割し、2つのパーティション間のピボットに等しい要素を残します。
次に、それ自体を再帰的に呼び出して2つのパーティションをソートしますが、必要な場合にのみ行います(したがって、再帰的な呼び出しの前にifsを使用します)。
実装は機能しますが、多くの点で最適ではなく、改善される可能性があります。考えられる改善点は次のとおりです。
返信が遅くなりましたが、私は印刷物をいくつか追加しただけで、これに遭遇した人は誰でもコードを理解するのに役立ちます。
#include<iostream>
using namespace std;
void quickSort(int arr[], int left, int right)
{
int i = left, j = right;
int tmp;
int pivot = arr[abs((left + right) / 2)];
cout<<"pivot is"<<pivot<<endl;
/* partition */
while (i <= j) {
while (arr[i] < pivot)
i++;
while (arr[j] > pivot)
j--;
if (i <= j) {
cout<<"i and j are"<<i<<" "<<j<<"and corresponding array value is"<<arr[i]<<" " <<arr[j]<<endl;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
i++;
j--;
cout<<"entering first big while loop"<<endl;
for(int i=0;i<7;i++)
cout<<arr[i]<<" "<<endl ;
}
}
cout<<"recursion"<<endl;
/* recursion */
if (left < j)
quickSort(arr, left, j);
if (i< right)
quickSort(arr, i, right);
}
int main(){
int arr[7]= {2,3,8,7,4,9,1};
for(int i=0;i<7;i++)
cout<<arr[i]<<" " ;
quickSort(arr,0,6);
cout<<endl;
for(int i=0;i<7;i++)
cout<<arr[i]<<" " ;
int wait;
cin>>wait;
return 0;
}
これがあなたの答えです-一般的なケースでは、それらの上の条件が真であるため、両方の再帰呼び出しが実行されます。ただし、コーナーケースでは、ピボット要素を最大(または最小)の要素にすることができます。その場合、配列からピボット要素を削除した後で、別のピボットを選択することにより、基本的にもう一度プロセスを試行する1回の再帰呼び出しのみを行う必要があります。