算法描述:
- 考虑排序储存在数组A中的n个数:首先找出A中的最小元素并将其与A[1]中的元素进行交换,接着,找出A的次最小元素并将其与A[2]中的元素进行交换,对A中前n-1个元素按该方式继续。——选择算法
问题一:实现该算法
问题二:为什么它只需要对前n-1个元素,而不是前n个元素进行?
问题三:用Θ记号给出线性查找的平均情况和最坏情况的运行时间。
问题四:我们可以如何修改任意算法,使之具有最好最好情况运行时间?
算法实现:
#include <stdio.h>
#include<stdlib.h>
int main(int argc,char*argv[])
{
int *A = NULL;
int n,i,j;
int min = 0;
int min_num = 0;//最小值下标
scanf("%d", &n);
A = (int *)malloc(sizeof(int) * n);
for (i = 0; i < n;i++)
{
scanf("%d", &A[i]);
}
min = A[0];
for (i = 0; i < n - 1;i++)//排到n-1项就停
{
for (j = i; j < n;j++)//比对的时候必须每一个单元都要对比,所以不能是n-1
{
//从第i项开始找最小值,因为排在i与i前的单元已经是前面已经通过交换,已经是前几轮每轮最小的了
//所以每一轮要从i上一轮的下一单元(每一轮完已经加1)项开始找下一个最小值
if(A[j] < min)
{
min = A[j];
min_num = j;
}
}
A[min_num] = A[i];//让找到的最小项与第i项交换位置
A[i] = min;
min = A[i+1];//让最小值等于还未进行交换的第一个单位
min_num = i + 1;
}
for (i = 0; i < n;i++)
{
printf("%d\n", A[i]);
}
}
回答一:上述代码
回答二:当最外层进行n-1次运算时,第n个数组A的元素就已经是未排序元素中最小的了(也是唯一的了),无需交换
回答三:最坏情况即,所有输出以从大到小的顺序排列,那么内层if语句中的赋值运算每一次循环都必须进入并执行。
则:最坏情况(Θ描述) :
读入行 = 1
赋值行 = 5(乘、调用、强制转换、2*赋值)
第一个for = 1+(n+1)(条件)+n(i的自增)+n(循环体)
第二个for = n-1+(n+1)*(n-1)(条件)+n*(n - 1)(j的自增)+3n*(n-1)(内层循环体) + 1(外层循环初始化)+ (n)(条件)+(n-1)(i的自增)+4(n-1)(外循环体)
总 = 5n^2 + 6n + 2(申明定义不占用时间,第三个for是验证用的所以不算在内)
因为在算法分析时,我们真正关心的是该算法运行时间的增长率或增长量级,所以只考虑吧比较重要的项(例如:5n^2),因为当n很大时,低阶项与常数项相对来说不重要。们也忽略最重要的项的常系数,因为对大的输入,在计算效率时常量因子不如增长率重要。
因此我们记该选择算法的最坏情况运行时间为Θ(n^2)
平均情况则输入数据一半从小到大一半从大到小
回答四:可以先对输入数据进行排序、计算等等处理,使任意输入在进入到该算法时都已经是最优输出