level 1
黄金止手
楼主
这里用到了传递开放数组一部分的功能。
要求 FP 版本在 2.2 以上,NOIP/NOI 的至少是 2.4.0 所以不用担心,但其他地方可能不同。
type
ValSInt=LongInt;// ValSInt for data, LongInt for index
var
SortSwapSInt32:ValSInt;
SortKeySInt32:ValSInt;
procedure QsortSInt32(var a:array of ValSInt);
var
i,j:LongInt;// Using SizeInt is better
begin
i:=0;
j:=High(A);
SortKeySInt32:=A[(i+j) shr 1];
while i<j do
begin
if (i<High(A)) and (A[i]<SortKeySInt32) then
inc(i);
if (0<j) and (SortKeySInt32<A[j]) then
dec(j);
if i<=j then
begin
SortSwapSInt32:=A[i];
A[i]:=A[j];
A[j]:=SortSwapSInt32;
inc(i);
dec(j);
end;
end;
if i<High(A) then
QSortSInt32(A[i..High(A)]);
if 0<j then
QSortSInt32(A[0..j]);
end;
调用的时候写
QSortSInt32(Arr[left..right]);
就行了。传入时的数组下标可以不从 0 开始。
如果是朴素实现的话,比起传统的 QSort(left, right) 的写法更加体现实现的思路,不用在内部把数组名称写上了。
传递开放数组(形参列表的类型写成 array of TypeName)时,实际上会传两个值,一个是数组首地址,一个是数组长度-1 (即最低下标为0时的最高下标)。开放数组在过程内部的下标统一转成0。
(假如传入开放数组时没有用 var 或 const 的话,传值和传址都会发生,时间空间消耗都会很大)
(使用 const 时假如数组是已定义数组或其一部分,那么就不会发生传值)
但这种写法的代价是(3.0.0 版本)每层递归的栈空间占用比传统实现多出 2 个指针长度(32位下是 2*4B)。
而且把尾递归手动去除就不太方便了。传入开放数组时虽然也能进行手动去除尾递归,但需要传更多参数,写法上没有朴素实现那么优雅,复杂度的常数也会大一些。
2016年07月05日 05点07分
1
要求 FP 版本在 2.2 以上,NOIP/NOI 的至少是 2.4.0 所以不用担心,但其他地方可能不同。
type
ValSInt=LongInt;// ValSInt for data, LongInt for index
var
SortSwapSInt32:ValSInt;
SortKeySInt32:ValSInt;
procedure QsortSInt32(var a:array of ValSInt);
var
i,j:LongInt;// Using SizeInt is better
begin
i:=0;
j:=High(A);
SortKeySInt32:=A[(i+j) shr 1];
while i<j do
begin
if (i<High(A)) and (A[i]<SortKeySInt32) then
inc(i);
if (0<j) and (SortKeySInt32<A[j]) then
dec(j);
if i<=j then
begin
SortSwapSInt32:=A[i];
A[i]:=A[j];
A[j]:=SortSwapSInt32;
inc(i);
dec(j);
end;
end;
if i<High(A) then
QSortSInt32(A[i..High(A)]);
if 0<j then
QSortSInt32(A[0..j]);
end;
调用的时候写
QSortSInt32(Arr[left..right]);
就行了。传入时的数组下标可以不从 0 开始。
如果是朴素实现的话,比起传统的 QSort(left, right) 的写法更加体现实现的思路,不用在内部把数组名称写上了。
传递开放数组(形参列表的类型写成 array of TypeName)时,实际上会传两个值,一个是数组首地址,一个是数组长度-1 (即最低下标为0时的最高下标)。开放数组在过程内部的下标统一转成0。
(假如传入开放数组时没有用 var 或 const 的话,传值和传址都会发生,时间空间消耗都会很大)
(使用 const 时假如数组是已定义数组或其一部分,那么就不会发生传值)
但这种写法的代价是(3.0.0 版本)每层递归的栈空间占用比传统实现多出 2 个指针长度(32位下是 2*4B)。
而且把尾递归手动去除就不太方便了。传入开放数组时虽然也能进行手动去除尾递归,但需要传更多参数,写法上没有朴素实现那么优雅,复杂度的常数也会大一些。