一个简单的Fortran递归快速排序
Fortran指针在使用时,所指向的变量或结构体在声明时必须加target,因此Fortran指针形式快速排序的通用性较差。这里选择用几个整形变量来标记排序的当前位置,函数可以被直接调用而不用重新声明待排序数组或结构体。
执行过程为:
Step1:将数组最左端元素X[l]、最右端元素X[r]、中间元素X[abs((r-l)/2)]的中值作为阈值,并将阈值与数组最左端元素交换位置;
Step2:若阈值右侧相邻元素X[a]小于阈值,则X[a]与阈值交换位置;
Step3:执行Step2,直至阈值小于右侧相邻元素X[a+n];
Step3:若阈值大于数组待排序部分最右端的元素X[b],则X[b]与阈值交换位置;
Step4:若有元素未排序,则执行Step2;
Step5:将数组的l到a+n-1号元素作为原始数据,执行Step1;
Step6:将数组的a+n到r号元素作为原始数据,执行Step1。
这样就将一组数据完整排序。
代码如下:
module module_FastSort
implicit none
integer rec_num
double precision,allocatable :: source_data(:)
double precision a,b,c
contains
recursive subroutine half_cut(low,high)
integer low,high
integer edge_mid,edge_high,edge_low
integer my_current,my_low,my_high
edge_high=high
edge_low=low
edge_mid=abs((edge_high-edge_low)/2)
!Check the border of this sort
if(edge_high<edge_low)then
write(*,*) "*******boundary error!*********"
return
endif
if(edge_high==edge_low) return
!Select the middle data of source_data array and put it into the first position
if(edge_high-edge_low>=2)then
a=source_data(edge_high)-source_data(edge_low)
b=source_data(edge_mid)-source_data(edge_low)
c=source_data(edge_high)-source_data(edge_mid)
if(a>0 .and. b>=0) then
if(c>0)then
call exchange_data(source_data(edge_low),source_data(edge_mid))
else
call exchange_data(source_data(edge_low),source_data(edge_high))
endif
elseif(a<=0 .and. b<0) then
if(c>0)then
call exchange_data(source_data(edge_low),source_data(edge_high))
else
call exchange_data(source_data(edge_low),source_data(edge_mid))
endif
endif
endif
!Set boundary of my sort
my_low=edge_low
my_high=edge_high
my_current=edge_low+1
!Do fast sort
do while(my_current<my_high)
do while(source_data(my_current)<=source_data(my_low))
call exchange_data(source_data(my_low),source_data(my_current))
my_low=my_low+1
my_current=my_current+1
enddo
if(my_low==my_high) return
do while(source_data(my_current)<=source_data(my_high))
my_high=my_high-1
if(my_high==my_current) then
exit
endif
enddo
if(my_high>my_current) call exchange_data(source_data(my_current),source_data(my_high))
enddo
call half_cut(edge_low,my_low)
call half_cut(my_low+1,edge_high)
return
endsubroutine
subroutine exchange_data(aa,bb)
!Exchange data of aa and bb
double precision aa,bb,mid
mid=aa
aa=bb
bb=mid
endsubroutine
endmodule