好了,在学习了四天之后,Fortran的数组昨晚已经结束了,今天来做几个题练一练,之前我应该是在数组2还是数组3写过一个冒泡排序,那么今天就用数组来做几个其他的排序,也算是对这几个排序算法重新学习一下,比如说选择排序、插入排序、希尔排序、归并排序、快速排序。那么就开始吧
1、算法的性能问题就不多说明了,这个在csdn社区里面早都已经烂大街了,没啥意思;
2、选择排序:
选择排序表现稳定,时间复杂度是O(
) ,但数据规模还是越小越好。优点就是不占用额外的内存空间。 选择排序的原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。
对于n个数组的选择排序可经过n-1趟选择排序得到有序数组。具体算法描述如下:
步骤1:初始状态:无序区为S[1…n],有序区为空;
步骤2:第i趟排序(i=1,2,3…n-1)开始时,当前有序区和无序区分别为S[1…i-1]和S(i…n)。该趟排序从当前无序区中-选出关键字最小的记录 S[k],将它与无序区的第1个记录交换,使S[1…i]和S[i+1…n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区;
步骤3:n-1趟之后排序结束。
program SelectSort
implicit none
integer::a(10)=(/1,5,3,6,8,2,9,4,7,0/)
integer i,j,minIndex,temp
do i=1,10
minIndex=i
do j=i,10
if (a(j)<a(minIndex))then!找到最小的数
minIndex=j!将最小数的索引保存
end if
end do
temp=a(minIndex)
a(minIndex)=a(i)
a(i)=temp
end do
write(*,"(I2,I2,I2,I2,I2,I2,I2,I2,I2,I2)")a
stop "SelectSort"
end
3、插入排序
插入排序是一种简单直观的排序算法。其工作原理是通过构建有序序列,对未排序的数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
算法描述
一般来说,插入排序都采用in-place在数组上实现。具体算法描述如下:
步骤1: 从第一个元素开始,该元素可以认为已经被排序;
步骤2: 取出下一个元素,在已经排序的元素序列中从后向前扫描;
步骤3: 如果该元素(已排序)大于新元素,将该元素移到下一位置;
步骤4: 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
步骤5: 将新元素插入到该位置后;
步骤6: 重复步骤2~5。
program insertSort
implicit none
integer::a(10)=(/1,5,3,6,8,2,9,4,7,0/)
integer i,current,preindex
do i=1,9
current=a(i+1)
preindex=i
do while((preindex>=0).and.(current<a(preindex)))
a(preIndex+1)=a(preindex)
preindex=preindex-1
end do
a(preindex+1)=current
end do
write(*,"(I2,I2,I2,I2,I2,I2,I2,I2,I2,I2)")a
stop "insertSort over"
end
4、希尔排序
希尔排序是一种插入排序,它是插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法的时间复杂度冲破了O()。与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
希尔排序是把数组用一定增量进行分组,每组使用插入排序;随着增量减少,每组所包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
算法描述
我们来看下希尔排序的基本步骤,在此我们选择增量,以
的方式来缩小增量,可以用一个序列来表示,{n/2,(n/2)/2…1},称为增量序列(希尔增量)。
先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:
步骤1:选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
步骤2:按增量序列个数k,对序列进行k 趟排序;
步骤3:每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。
program insertSort
implicit none
integer::a(10)=(/1,5,3,6,8,2,9,4,7,0/)
integer i,length,temp,gap,preindex
parameter(length=10)
gap=length/2
do while(gap>0)
do i=gap,length
temp=a(i)
preindex=i-gap
do while((preindex>=0).and.(a(preindex)>temp))
a(preindex+gap)=a(preindex)
preindex=preindex-gap
end do
a(preindex+gap)=temp
end do
gap=gap/2
end do
write(*,"(I2,I2,I2,I2,I2,I2,I2,I2,I2,I2)")a
stop "insertSort over"
end
至于归并排序、快速排序,这两个等之后学习完函数之后再写,因为我还不知道Fortran是怎么向函数传参的,可能是两种:1、和c++取地址一样,直接对数组修改,2、直接在函数种创建一个新的数组,返回新的数组,这都是又可能的,鬼晓得嘞,学了函数再说吧
跟着书上写一个矩阵乘法:
program MatrixProduce
implicit none
integer,PARAMETER::L=3,M=4,N=2
integer ::a(L,M)
integer ::b(M,N)
integer ::c(L,N)
integer i,j,k
//!唉,书上的赋值方法,一维数组还是对的,到了二维数组,他就有问题,只能用data命令来给两个数组赋值了
data ((a(i,j),i=1,L),j=1,M)/1,2,3,4,5,6,7,8,9,10,11,12/
data((b(i,j),i=1,M),j=1,N)/1,2,3,4,5,6,7,8/
c=0
do i=1,L
do j=1,N
do k=1,M
c(i,j)=a(i,k)*b(k,j)+c(i,j)
end do
end do
end do
do i=1,L
write(*,*)c(i,:)
end do
stop "Matric product over"
end
//!其实Fortran有矩阵运算的内置函数的,比如说这里的三重循环,一个c=matmul(a,b)就可以了
书上其实没啥题好做的,第一个是等比数列赋值并求平均值,还有一个是斐波那契数列,这个我做过,不过当时并没有使用数组,直接是一个一个输出的,今天就写这两个题吧
1、等比数列求均值:
program dbsl
implicit none
integer::a(10)
integer i
real sum
a=0
sum=0.0
do i=1,10
a(i)=2*i
sum=sum+a(i)
end do
write(*,"(I3,I3,I3,I3,I3,I3,I3,I3,I3,I3)")a
write(*,*)"average=",sum/10
stop
end program dbsl
2斐波那契数列:
program fibnoacci
implicit none
integer::a(20)
integer i
a(1)=0
a(2)=1
do i=3,20
a(i)=a(i-1)+a(i-2)
end do
write(*,"(I3,I3,I3,I3,I3,I3,I3,I3,I3,I3,I5,I5,I5,I5,I5,I5,I5,I5,I5,I5)")a
stop "fibnoacci over"
end program fibnoacci
ok,到今天,数组就全部结束啦,之后就要开始学习函数了。