例5-3 编写程序,用起泡法对10个数排序(按由小到大顺序)。
起泡法的思路:将相邻两个数比较,将小的调到前面。然后进行第2趟比较,对
余下的数按上法进行比较。
可以推知,如果有n个数,则要进行n-1趟比较(和交换)。在第1趟中要进行
n-1次两两比较,在第j趟中要进行n-j次两两比较。
根据以上思路写出程序,今设n=10,本例定义数组长度为11,a[0]不用,只用 a[1]~
a[10],以符合人们的习惯。从前面的叙述可知,应该进行9趟比较和交换。
源程序:
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, t;
cout << "input 10 numbers :" << endl;
for (i = 1; i < 11; i++) //输入a[1]~a[10]
cin >> a[i];
cout << endl;
for (j = 1; j <= 9; j++)//共进行9趟比较
for (i = 1; i <= 10 - j; i++)
//在每趟中要进行(10-j)次两两比较
if (a[i] > a[i + 1])//如果前面的数大于后面的数
{
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
} //交换两个数的位置,使小数上浮
cout << "the sorted numbers :" << endl;
for (i = 1; i < 11; i++)//输出10个数
cout << a[i] << " ";
cout << endl;
return 0;
}
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, t;
cout << "input 10 numbers :" << endl;
for (i = 1; i < 11; i++) //输入a[1]~a[10]
cin >> a[i];
cout << endl;
for (j = 1; j <= 9; j++)//共进行9趟比较
for (i = 1; i <= 10 - j; i++)
//在每趟中要进行(10-j)次两两比较
if (a[i] > a[i + 1])//如果前面的数大于后面的数
{
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
} //交换两个数的位置,使小数上浮
cout << "the sorted numbers :" << endl;
for (i = 1; i < 11; i++)//输出10个数
cout << a[i] << " ";
cout << endl;
return 0;
}
我写的:
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 1; i <= 10; i++)
cin >> j;// cin >> a[i];
j = a[i];
cout << endl;
k = 10;
for (i = 1; i <= k; i++)
if (a[i] > a[i + 1])
{
a[i] = t;//t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
k--;
}
else
k--;
cout << "the sorted numbers :" << endl;
for (i = 1; i <= 10; i++)
cout << a[i] << " ";
}
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 1; i <= 10; i++)
cin >> j;// cin >> a[i];
j = a[i];
cout << endl;
k = 10;
for (i = 1; i <= k; i++)
if (a[i] > a[i + 1])
{
a[i] = t;//t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
k--;
}
else
k--;
cout << "the sorted numbers :" << endl;
for (i = 1; i <= 10; i++)
cout << a[i] << " ";
}
结果不对:
存在的问题(错误):
输入数值的时候,直接“cin >> a[i];”即可;
实在不行一定要这么写,那也得改正两个错误:
(1):赋值语句的格式为:把等号右边的值赋给等号左边的变量。
你不能把两边位置颠倒,我们这里是想把已经赋给j的值传递给a[i],a[i]才是被赋值的变量。
“j = a[i];”显然错误,应改为“a[i] = j;”。而跟这个同理的,后面的“a[i] = t;”也一样,t才是被赋值的变量,应改为“t = a[i];”
(2):for语句后面如果有多个语句(即后面为复合语句)
如果我们不把它们用花括号括起来
那么程序默认只把后面的第一句作为循环内最后的那个语句模块
后面的其他语句一律看作循环外的语句,即只有当循环结束后才会开始执行后面的语句,详见:
C语言日记 13 循环结构程序设计(for语句)_宇 -Yu的博客-CSDN博客_c语言日记程序
也就是说,要改也必须改为“{cin >> j; a[i] = j;}”即必须把这两个语句用大括号括起来
否则,只有当循环结束后才开始执行a[i] = j语句
而这时i已经等于11,也就是说这样的话a[i]里面一个被赋值的都没有,自然最终结果输出的全都是一堆乱七八糟没用的值。
此外,关于该程序具体逻辑结构(关于k),也需要大改,改之前(为了知道到底我们应该要怎么改),让我们先看一下该程序设计流程框架与思路:
程序设计思路:
关于对于k的函数的设计,我们本来的设计思路为两两比较:
第一次循环 : 第一个和第二个比较(第一次),第二个和第三个比较(第二次)...第n-1个和第n个比较(第n-1次);共进行了n-1次比较。(每次比较都为的是把大的数字移到最后去)
第二次循环 : 第一个和第二个比较(第一次),第二个和第三个比较(第二次)...第n-2个和第n-1个比较(第n-2次);最后有一个最大数字已经确定;共进行了n-2次比较。
第三次循环 :...最后有2个最大数字已经确定;共进行了n-3次比较。
...
最后一次循环:
应该是最后把第一个数和第二个数比较一下就行,也就是说只进行1次比较。n-?=n-1;---->共进行了n-1次比较。
想办法把上述流程转化为程序,即:
第一次循环 : 第一个和第二个比较(第一次),第二个和第三个比较(第二次)...第n-1个和第n个比较(第n-1次);
//代入本例:第一次最后以a[9]和a[10]相比较为结束,那么由此,我们自然容易写出第一次的程序:
for (i = 1; i <= 9; i++){(每个数去和下一个数去比较)}
第二次循环 : 第一个和第二个比较(第一次),第二个和第三个比较(第二次)...第n-2个和第n-1个比较(第n-2次);
//同理,第二次的程序即为:for (i = 1; i <= 8; i++){(每个数去和下一个数去比较)}
...
最后一次循环:第一个数和第二个数比较。
//同理,程序即为for (i = 1; i <= 1; i++){(和下一个数去比较)}
每一次比较循环结束以后都自动进入下一轮的比较循环
//要在关于i的for语句之上再写一个关于限定()决定我们到底进行多少次比较的循环的for语句
并且每往后一次循环,我们就少比较一个数字
//(k--)
就如同上面已经说的,一共进行n-1次比较循环。
//次数排序应为:第一次,第二次,第三次...第n-1次;结束。
综上,我们可以写出(构造出)如下语句:
for(k = 9; k >= 1 ; k--)
for (i = 1; i <= k; i++)
此时,k即相当于n-1。
但是,这里面一开始我们写的程序:
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 1; i <= 10; i++)
cin >> j;// cin >> a[i];
j = a[i];
cout << endl;
k = 10;
for (i = 1; i <= k; i++)
if (a[i] > a[i + 1])
{
a[i] = t;//t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
k--;
}
else
k--;
cout << "the sorted numbers :" << endl;
for (i = 1; i <= 10; i++)
cout << a[i] << " ";
}
实现的却是
两两比较以后不管怎么样,都进行(k--)操作,这个当然也没问题。
但是进行完了(k--)操作以后,没有让程序进入下一轮循环,也没有任何其他的额外要求与操作
就这么结束了?!这样显然不行,自然会出大问题。
我们只要把上面写出来的双重嵌套的for语句加到程序里,把程序里原来写的(k--)的语句减掉(删掉),自然程序就能够正常运行和输出一系列的数字了:
最终,我们得到以下程序:
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 1; i <= 10; i++)
{
cin >> j;
a[i] = j;
}
cout << endl;
for(k = 9; k >= 1 ; k--)
for (i = 1; i <= k; i++)
if (a[i] > a[i + 1])
{
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
}
cout << "the sorted numbers :" << endl;
for (i = 1; i <= 10; i++)
cout << a[i] << " ";
}
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 1; i <= 10; i++)
{
cin >> j;
a[i] = j;
}
cout << endl;
for(k = 9; k >= 1 ; k--)
for (i = 1; i <= k; i++)
if (a[i] > a[i + 1])
{
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
}
cout << "the sorted numbers :" << endl;
for (i = 1; i <= 10; i++)
cout << a[i] << " ";
}
结果:
另外,如果想要把双重嵌套的for语句的k改为10也可以:
for (k = 10; k >= 2; k--)
for (i = 1; i <= k-1; i++)
此时,k即相当于n;
由于次数排序应为:第一次,第二次,第三次...第n-1次;结束。
如果对应这里的本例,也就是说一共要循环n-1=9次。
1,2,3,4,5,6,7,8,9:一共9个数
同理,10到2应该也是9个数。改后即为:
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[11];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 1; i <= 10; i++)
{
cin >> j;
a[i] = j;
}
cout << endl;
for (k = 10; k >= 2; k--)
for (i = 1; i <= k-1; i++)
if (a[i] > a[i + 1])
{
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
}
cout << "the sorted numbers :" << endl;
for (i = 1; i <= 10; i++)
cout << a[i] << " ";
}
另外,我们也可以不按题目要求的“a[0]不用”,就用a[0]到a[9]算:
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[10];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 0; i <= 9; i++)
{
cin >> j;
a[i] = j;
}
cout << endl;
for (k = 10; k >= 2; k--)
for (i = 0; i <= k-1; i++)
if (a[i] > a[i + 1])
{
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
}
cout << "the sorted numbers :" << endl;
for (i = 0; i <= 9; i++)
cout << a[i] << " ";
}
结果:
可能是爆内存了,因为:
就拿第一次来说吧:k=10;i <= k-1=9;a[9]执行(a[i] > a[i + 1])操作时
一来我们没有给a[10]赋值过,二来本例里面一开始给出定义的空间就只到a[9]
根本就不存在a[10]这玩意的空间和内存啊,所以就爆内存,随便给了一个数插了进来。
改为如下程序即可:
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
int a[10];
int i, j, k, t;
cout << "请输入10个数字 :" << endl;
for (i = 0; i <= 9; i++)
{
cin >> j;
a[i] = j;
}
cout << endl;
for (k = 10; k >= 2; k--)
for (i = 0; i <= k-2; i++)
if (a[i] > a[i + 1])
{
t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
}
cout << "the sorted numbers :" << endl;
for (i = 0; i <= 9; i++)
cout << a[i] << " ";
}
另外,额外增加一个思考题:
出了这样两两比较一个一个比的方法之外,还有没有其他的更快更便捷的方法排序求最大值?