RAD Studio 10.3.3 测试√
1、快速排序是一种递归的写法
2、其中需要在待排序的数组中找到一个 基准值(可以是待排序数组中任意一个数,一般为了方便就取数组从左往右数的第一个数)
3、根据选定的 基准值 对数组中的其他数进行遍历比较,小于等于基准数的放在基准数的左边,大于基准数的放在基准数的右边
4、这里的遍历不是从头到尾的遍历,而是用两个变量,分别代表从左往右 和 从右往左 的数组下标,依次往数组中心位置移动
5、先向前(从右往左)移动找到 小于等于 这个 基准值 的数,然后再向后(从左往右)找到 大于 这个 基准值 的数,然后将这个两个下标指向的数进行调换位置
6、在遍历寻找的过程中,一单两个下标相遇(指向同一个数),就可以结束遍历,将结束后将 基准值 填入到对应的位置
7、将分出来的基准数左边数组和基准数右边数组,分别再次进行上述的比较,知道左右两边的数组个数不足2个即为结束
var
mArr: TArray<Integer>;
a, i, j: Integer;
mTempi: Integer;
begin
GenerateRandomArray(mArr, 100, 5, True);
Memo_Log.Lines.Add('============');
ArrToMemo(mArr);
// 数组的开始下标
i := 0;
// 数组的最后一位下标
j := Length(mArr) - 1;
a := mArr[i];
Memo_Log.Lines.Add('本轮基准值=' + IntToStr(a));
// 这里其实也需要判断一下数组的是否有2个及以上个数
while j > i do
begin
// 首先从[j]开始向前(从右往左)找到一个 <= a 的数,将其放在[i]中
while j > i do
begin
if mArr[j] <= a then
begin
mArr[i] := mArr[j];
// 这里 i 进行 +1 是表示 mArr[i] 已经满足 <= a 本轮不用再次比较
i := i + 1;
ArrToMemo(mArr);
Break;
end;
// 这里 j 进行 -1 是表示 mArr[j] 满足 > a 本轮不用再次比较
j := j - 1;
end;
// 然后从[i]开始向后(从左往右)找到一个 > a 的数,将其放在[j]中
while i < j do
begin
if mArr[i] > a then
begin
mArr[j] := mArr[i];
// 这里 j 进行 -1 是表示 mArr[j] 已经满足 > a 本轮不用再次比较
j := j - 1;
ArrToMemo(mArr);
Break;
end;
// 这里 i 进行 -1 是表示 mArr[i] 满足 <= a 本轮不用再次比较
i := i + 1;
end;
// 上面的连个遍历就类似,找到一个 <= a 的数 和一个 > a 的数将它们进行调换位置,然后继续同上往中间找
// 但其实写法是按照基准值提出来,作为一个空的坑位,然后有满足条件的就将这个数填入基准值的原始坑位,
// 然后满足条件的那个原来的坑位又空出来了,就这样一直找一直填坑
end;
// 到这里出来的时候就是 i = j(相遇) 的时候,将基准值填入到空余的坑位
mArr[i] := a;
Memo_Log.Lines.Add('↓↓↓↓第一轮结果↓↓↓↓');
ArrToMemo(mArr);
// 这里是因为没有用递归,需要记录一下上一轮基准值最终坑位的下标,方便进行分开左右两边的数组
mTempi := i;
// 开始第二轮
Memo_Log.Lines.Add('↓↓↓↓开始第二轮 左边的↓↓↓↓');
// 第二轮左边数组开始的下标
i := 0;
// 第二轮左边数组结束的下标
j := mTempi - 1;
// 数组中个数不足2个不用排
if j > i then
begin
a := mArr[i];
Memo_Log.Lines.Add('本轮基准值=' + IntToStr(a));
while j > i do
begin
// 首先从[j]开始向前(从右往左)找到一个 <= a 的数,将其放在[i]中
while j > i do
begin
if mArr[j] <= a then
begin
mArr[i] := mArr[j];
i := i + 1;
ArrToMemo(mArr);
Break;
end;
j := j - 1;
end;
// 然后从[i]开始向后(从左往右)找到一个 > a 的数,将其放在[j]中
while i < j do
begin
if mArr[i] > a then
begin
mArr[j] := mArr[i];
j := j - 1;
ArrToMemo(mArr);
Break;
end;
i := i + 1;
end;
end;
// 到这里出来的时候就是 i = j 的时候
mArr[i] := a;
Memo_Log.Lines.Add('↓↓↓↓第二轮 左边的结果↓↓↓↓');
ArrToMemo(mArr);
end
else
begin
Memo_Log.Lines.Add('第二轮 左边的数组长度不到2');
end;
// 开始第二轮
Memo_Log.Lines.Add('↓↓↓↓开始第二轮 右边的↓↓↓↓');
// 第二轮右边数组开始的下标
i := mTempi + 1;
// 第二轮右边数组结束的下标
j := Length(mArr) - 1;
if j > i then
begin
a := mArr[i];
Memo_Log.Lines.Add('本轮基准值=' + IntToStr(a));
while j > i do
begin
// 首先从[j]开始向前(从右往左)找到一个 <= a 的数,将其放在[i]中
while j > i do
begin
if mArr[j] <= a then
begin
mArr[i] := mArr[j];
i := i + 1;
ArrToMemo(mArr);
Break;
end;
j := j - 1;
end;
// 然后从[i]开始向后(从左往右)找到一个 > a 的数,将其放在[j]中
while i < j do
begin
if mArr[i] > a then
begin
mArr[j] := mArr[i];
j := j - 1;
ArrToMemo(mArr);
Break;
end;
i := i + 1;
end;
end;
// 到这里出来的时候就是 i = j 的时候
mArr[i] := a;
Memo_Log.Lines.Add('↓↓↓↓第二轮 右边的结果↓↓↓↓');
ArrToMemo(mArr);
end
else
begin
Memo_Log.Lines.Add('第二轮 右边的数组长度不到2');
end;
// ......按照这种情况循环,一直到左右两边的数不足2个结束
end;
procedure TForm_Main.KuaiSuSort(var avArr: TArray<Integer>; avLeft, avRight: Integer);
var
i, j, a: Integer;
begin
if avLeft < avRight then
begin
a := avArr[avLeft];
i := avLeft;
j := avRight;
while i < j do
begin
while j > i do
begin
if avArr[j] <= a then
begin
avArr[i] := avArr[j];
i := i + 1;
Break;
end;
j := j - 1;
end;
while i < j do
begin
if avArr[i] > a then
begin
avArr[j] := avArr[i];
j := j - 1;
Break;
end;
i := i + 1;
end;
end;
avArr[i] := a;
KuaiSuSort(avArr, avLeft, i - 1);
KuaiSuSort(avArr, i + 1, avRight);
end;
end;
var
mArr: TArray<Integer>;
begin
GenerateRandomArray(mArr, 100, 10, True);
Memo_Log.Lines.Add('排序前');
ArrToMemo(mArr);
KuaiSuSort(mArr, 0, Length(mArr) - 1);
Memo_Log.Lines.Add('排序后');
ArrToMemo(mArr);
end;
一点点笔记,以便以后翻阅。