使用插入排序对10个元素的一维数组进行升序排序。
出现了元素丢失和排序不正确的情况
具体代码如下:
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
if(a[i] < a[i - 1])
{
int t = a[i];
int j = i - 1;
for(j = i - 1;a[j] > a[i] && j > 0;--j)
{
a[j] = a[j - 1];
}
a[j +1] = t;
}
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
输出结果
1 3 3 5 5 6 7 12 12 45
首先我们先看一个正确的选择插入的代码示例:
#include
int main(void)
{
int i = 0;
int k = 0;
int n = 0;
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int len = sizeof(a)/sizeof(a[0]);
for(i = 1;i < len;++i)
{
int temp = a[i];
k = i - 1;
while(k >=0 && a[k]>temp)
{
a[k + 1]=a[k];
--k;
}
a[k + 1] = temp;
}
for(n = 0;n < len;++n)
{
printf("%d ",a[n]);
}
printf("\n");
return 0;
}
输出结果为:
1 3 5 6 7 12 24 45 47 89
语句冗余
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
7 if(a[i] < a[i - 1])//判断a[i] 和 a[i -1]大小
{
int t = a[i];
int j = i - 1;//将 j 赋值为i - 1;
11 for(j = i - 1;a[j] > a[i] && j > 0;--j)//循环条件判断a[i] 和 a[j]
{
a[j] = a[j - 1];
}
a[j + 1] = t;
}
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
阅读代码可知,j = i - 1,那么11行代码a[i]与a[j]的比较可以等价为a[i] 和 a[i - 1]的比较,与4行的语句作用重复。因为插入排序要求进行a[i] 和 a [i - 1]多次比较,所以应该删除4行语句。
修改为:
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
int t = a[i];
int j = i - 1;
for(j = i - 1;a[j] > a[i] && j > 0;--j)
{
a[j] = a[j - 1];
}
a[j +1] = t;
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
改变的对象错误
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
int t = a[i];
int j = i - 1;
for(j = i - 1;a[j] > a[i] && j > 0;--j)//循环条件判断a[i] 和 a[j]
{
a[j] = a[j - 1]; //如果a[j] > a[i],将 a[j - 1]赋值给a[j]
}
a[j + 1] = t;
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
这里是一个明显的逻辑错误,对 a[i] 与 a[j] 进行比较,最后却将 a[j - 1] 的值赋值给 a[j]。
相当于比较a[i] 和a[i - 1],a[i - 1]赋值为a[ i - 2]。插入排序要求我们两个数值进行比较,将大值赋值给位号大的那一个。根据判断条件来看,我们对于a[ i -2]的情况是未知的(不清楚a[i -2] 和 a[ i -1]的大小关系),因此这种赋值是不恰当的。
修改为
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
int t = a[i];
int j = i - 1;
for(j = i - 1;a[j] > a[i] && j > 0;--j)//循环条件判断a[i] 和 a[j]
{
a[j + 1] = a[j]; //如果a[j] > a[i],将 a[j]赋值给a[j + 1]
// 即赋值给a[i]
}
a[j + 1] = t;
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
比较的对象错误
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
int t = a[i];
int j = i - 1;
for(j = i - 1;a[j] > a[i] && j > 0;--j)//循环条件判断a[i] 和 a[j]
{
a[j + 1] = a[j]; //如果a[j] > a[i],将 a[j]赋值给a[j + 1]
// 即赋值给a[i]
}
a[j + 1] = t;
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
再上一轮修改后,可以发现,a[i] 的值被改变。在第一轮循环后,循环条件变成了a[ j ]和被改变后的a[i]的比较。然而选择插入的思想是将希望被排序的元素temp与a[i]之前的元素作比较,为temp选择一个适合的位置将其插入。第一次循环后,a[i] 的值为 temp和a[j]二者比较中的较大值,因此我们无法保障始终进行的是temp和a[i]前面的元素比较。
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
int t = a[i];
int j = i - 1;
for(j = i - 1;a[j] > temp && j > 0;--j)//循环条件判断 temp 和 a[j]
{
a[j + 1] = a[j]; //如果a[j] > a[i],将 a[j]赋值给a[j + 1]
// 即赋值给a[i]
}
a[j + 1] = t;
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
阅读代码没有其他错误,进行编译检验。
修改后的代码:
int main(void)
{
int a[10] = {1,24,3,47,5,6,7,89,12,45};
int i;
for(i = 1 ; i < 10;++i)
{
int t = a[i];
int j = i - 1;
for(j = i - 1;a[j] > t && j > 0;--j)
{
a[j + 1] = a[j ];
}
a[j +1] = t;
}
for(int i = 0;i < 10;++i)
{
printf("%d ",a[i]);
}
printf("\n");
}
运行结果
1 3 5 6 7 12 24 45 47 89
结果正确。