6.全国有10000人参加物理竞赛,只录取成绩优异的前10名,并将他们从高分到低分输出。而对落选的其他考生,不需排出名次,问此种情况下,用何种排序方法速度最快?为什么?
堆排序
在内部排序方法中,一趟排序后只有简单选择排序和冒泡排序可以选出一个最大(或最小)元素,并加入到已有的有序子序列中,但要比较n-1次。选次大元素要再比较n-2次,其时间复杂度是O(n2)。从10000个元素中选10个元素不能使用这种方法。而快速排序、插入排序、归并排序、基数排序等时间性能好的排序,都要等到最后才能确定各元素位置。只有堆排序,在未结束全部排序前,可以有部分排序结果。建立堆后,堆顶元素就是最大(或最小,视大堆或小堆而定)元素,然后,调堆又选出次大(小)元素。凡要求在n个元素中选出k(k<<n,k>2)
个最大(或最小)元素,一般均使用堆排序。因为堆排序建堆比较次数至多不超过4n,对深度为k的堆,在调堆算法中进行的关键字的比较次数至多为2(k-1)次,且辅助空间为O(1)。
 
7. 给出一组关键字:29,18,25,47,58,12,51,10,分别写出按下列各种排序方法进行排序时的变化过程:
(1) 归并排序   每归并一次书写一个次序。
(2) 快速排序   每划分一次书写一个次序。
(3) 堆排序     先建成一个堆,然后每从堆顶取下一个元素后,将堆调整一次。
(1)2路归并
第一趟:18,29,25,47,12,58,10,51;
第二趟:18,25,29,47,10,12,51,58;
第三趟:10,12,18,25,29,47,51,58
(2)快速排序
第一趟:10,18,25,12,29,58,51,47;
第二趟:10,18,25,12,29,47,51,88;
第三趟:10,12,18,25,29,47,51,88
(3)堆排序 建大堆
58,47,51,29,18,12,25,10;
①51,47,25,29,18,12,10,58;
②47,29,25,10,18,12,51,58;
③29,18,25,10,12,47,51,58;
④25,18,12,10,29,47,51,58;
⑤18,10,12,25,29,47,51,58;
⑥12,10,18,25,29,47,51,58;
⑦10,12,18,25,29,47,51,58
 
8.请写出应填入下列叙述中( )内的正确答案。 
排序有各种方法,如插入排序、快速排序、堆排序等。
设一数组中原有数据如下:15,13,20,18,12,60。下面是一组由不同排序方法进行一遍排序后的结果。
(快速 )排序的结果为:12,13,15,18,20,60
( 冒泡)排序的结果为:13,15,18,12,20,60
(直接插入 )排序的结果为:13,15,20,18,12,60
( 堆)排序的结果为:12,13,20,18,15,60
 
 
五、算法设计题:
1.冒泡排序算法是把大的元素向上移(气泡的上浮),也可以把小的元素向下移(气泡的下沉)请给出上浮和下沉过程交替的冒泡排序算法。
void BubbleSort2(int a[],int n) //相邻两趟向相反方向起泡的冒泡排序算法
{ change=1;low=0;high=n-1; //冒泡的上下界
while(low<high && change)
{ change=0; //设不发生交换
for(i=low;i<high;i++) //从上向下起泡
if(a[i]>a[i+1]){a[i]<-->a[i+1];change=1;} //有交换,修改标志change
high--; //修改上界
for(i=high;i>low;i--) //从下向上起泡
if(a[i]<a[i-1]){a[i]<-->a[i-1];change=1;}
low++; //修改下界
}//while
}//BubbleSort2
 
2.写出一趟快速排序算法。
int Partition(RecType R[],int l,int h)
//一趟快速排序算法,枢轴记录到位,并返回其所在位置,
{ int i=l; j=h; R[0] = R[i]; x =R[i].key;
while(i<j)
{ while(i<j && R[j].key>=x) j--;
if (i<j) R[i] = R[j];
while(i<j && R[i].key<=x) i++;
if (i<j) R[j] = R[i];
}//while
R[i]=R[0];
return i;
 
3.非递归的快速排序算法。
void QuickSort(rectype r[n+1]; int n)
// 对r[1..n]进行快速排序的非递归算法
{typedef struct
{ int low,high; }node
node s[n+1];//栈,容量足够大
int quickpass(rectype r[],int,int); // 函数声明
int top=1; s[top].low=1; s[top].high=n;
while (top>0)
{ss=s[top].low; tt=s[top].high; top--;
if (ss<tt)
{k=quickpass(r,ss,tt);
if (k-ss>1) {s[++top].low=ss; s[top].high=k-1;}
if (tt-k>1) {s[++top].low=k+1; s[top].high=tt;}
}
} // 算法结束
int quickpass(rectype r[];int s,t)
{i=s; j=t; rp=r[i]; x=r[i].key;
while (i<j)
{while (i<j && x<=r[j].key) j--;
if (i<j) r[i++]=r[j];
while (i<j && x>=r[j].key) i++;
if (i<j) r[j--]=r[i];;
]
r[i]=rp;
return (i);
} // 一次划分算法结束