#include <stdio.h>
void main(){
int i, j, m;
int min, index;
int a[6] = {5,2,4,6,1,3};
for (i = 0; i < 6; i++){
min = a[i];
for (j = i+1; j < 6; j++){
if (a[j] < min) {
min = a[j];
index = a[i];
a[i] = min;
a[j] = index;
}
}
}
for (m=0; m<6; m++) {
printf("%d ", a[m]);
}
}
以上程序正确输出。
错误程序:
#include <stdio.h>
void main(){
int i, j, m;
int min, key, index;
int a[6] = {5,2,4,6,1,3};
for (i = 0; i < 6; i++){
min = a[i];
for (j = i+1; j < 6; j++){
if (a[j] < min) {
min = a[j];
key = j;
}
}
index = a[i];
a[i] = min;
a[key] = index;
}
for (m=0; m<6; m++) {
printf("%d ", a[m]);
}
}
原因分析:
在这三步中
index = a[i];
a[i] = min;
a[key] = index;
如果此次j循环没有做任何动作,那么此时的key值仍然为上一个i循环中的值,这时的交换出现错误
例如 5 2 4 6 1 3 第一个i循环后,key=4,序列变成 1 2 4 6 5 3
index = a[1] = 2;
a[1] = 2;
a[4] = 2;
此时错误出现,将 a[4] 原本为5的值擅自改变为2
但是程序一,交换次数太多。引入key的改进
#include <stdio.h>
void main(){
int i, j, m;
int min, key, index;
int a[6] = {5,2,4,6,1,3};
for (i = 0; i < 6; i++){
min = a[i];
key = i;
for (j = i+1; j < 6; j++){
if (a[j] < min) {
min = a[j];
key = j;
}
}
if (key > i) { //保证只有需要交换时才交换
index = a[i];
a[i] = min;
a[key] = index;
}
}
for (m=0; m<6; m++) {
printf("%d ", a[m]);
}
}
第一个关于 i 的 for 循环,i < 5 就行。
应用loop invariant思想,sequence最后一个数肯定是最大的。
As a loop invariant, we choose that A[1...i-1] are sorted and all other elements are greater then these. We only need to iterate to n-1 since according to the invariant the n-th element will be the largest.