题目:
Class A{
Public:
Intk1;int k2;
};
一个数组A a[5]={{3,4},{6,5},{2,7},{3,1},{1,2}}
下面哪一个是函数调用之后的结果
{{1,2},{2,7},{3,1},{3,4},{6,5}}
f1:选择排序;f2:直接插入排序;f3:冒泡,f4:快排
A. f1(a,5,cmp)
B. f2(a,5,cmp)
C. f3(a,5,cmp)
D. f4(a,5,cmp)
E. 以上都不对
分析:
这道题出的很有意思,乍一看,题干这么大,可能会被唬住,其实冷静下来看一下,很简单,就是一个排序的稳定性非稳定性的分析。所谓稳定性,即:保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同,如果排序的结点仅仅是一个数,则稳定性意义不大,但是如果有多个键值,就需要考虑稳定性的分析。例如,对于本题,如果排序算法是稳定的,那么因为原数组{3,4}排在{3,1}前,根据稳定性的定义,排序的结果就一定不会出现{3,1}排在{3,4}前的情况。而如果算法是不稳定的,那么只能说,{3,1}有排在{3,4}前面的可能,需要根据具体的排序过程判断是否相等的值会变换位置。关于八种算法稳定性的分析,可以查看http://hi.baidu.com/shismbwb/item/404c94898cfd2855850fab24。选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。
所以,首先明确四个函数都采用了什么样的排序算法:
f1:选择排序;f2:直接插入排序;f3:冒泡,f4:快排
f2和f3是稳定的,直接pass掉。然后非稳定的再看是否变换了位置。A和D如果走一遍程序的话,会发现{3,4}和{3,1}这两个元素是变了顺序的。
对于A答案,a[5]={{3,4},{6,5},{2,7},{3,1},{1,2}}
第一遍排序:{{1,2},{6,5},{2,7},{3,1},{3,4}}
第二遍排序:{{1,2},{2,7},{6,5},{3,1},{3,4}}
第三遍排序:{{1,2},{2,7},{3,1},{6,5},{3,4}}
第四遍排序:{{1,2},{2,7},{3,1},{3,4},{6,5}}
所以正确
对于D答案,a[5]={{3,4},{6,5},{2,7},{3,1},{1,2}}
第一遍排序的运行过程是这样的。
初始:low=0,high=4,i=0,t={3,4}
For循环:
J=1, c({6,5},t)>0,i=0,没有交换(a[i],a[j]),{{3,4},{6,5},{2,7},{3,1},{1,2}}
J=2,c({2,7},t)<0,i=1,交换({6,5},{2,7}),{{3,4},{2,7},{6,5},{3,1},{1,2}}
J=3, c({3,1},t)=0,i=2,交换({6,5},{3,1}),{{3,4},{2,7},{3,1},{6,5},{1,2}}
J=4, c({1,2},t)<0,i=3,交换({6,5},{1,2}),{{3,4},{2,7},{3,1},{1,2},{6,5}}
最后,执行exchange(a,low,i), 交换({3,4},{1,2}),{{1,2},{2,7},{3,1},{3,4},{6,5}}
得到第一遍排序结果:{{1,2},{2,7},{3,1},{3,4},{6,5}},找到了{3,1}的位置,已经在{3,4}的前面,所以最后的结果一定与预期结果相同。这里需要非常注意的是在_f41函数中,if(c(a[j],t)<=0),如果写成c(a[j],t)<0的话,则该答案也不会选择。所以最终的答案是A和D