在总结冒泡排序前:先从头开始,对冒泡排序(BubbleSort)进行一个系统性了解:
冒泡排序法,又称交换排序法,是从观察水中的气泡变化构思而成的,原理是从第一个元素开始,比较相邻元素的大小,如果大小顺序不对,则进行两个数据的调换,就好像气泡从水中逐渐上升到水面上一样。经过这样的扫描,就可以一次接着一次的排序,直到完成所有元素的排序工作。
如图对数据进行排序 55,23,87,62,16:
通过代码的方式进行表达:
//冒泡排序法
#include<stdio.h>
#include<stdlib.h>
void Swap(int array[],int index1,int index2)//定义交换函数
{
int temp = array[index1];
array[index1] = array[index2];
array[index2] = temp;
}
void Bubble_sort(int array[], int n)//定义排序函数
{
int i = 0;
int j = 0;
int temp;
for (i = 0; i < n-1;i ++){//与除自己以外的其他9个元素进行比较,
for (j = 0; j < n - 1 - i; j++)//n-1-i的意思是每比较一趟元素就会少一个,比如说如果是执行的第三趟,那么元素的个数就是:10-1-3=6个
{
if (array[j] > array[j+1])//升序排法,如果前面的数大于后面的数,即调换位置
{
Swap(array,j,j+1);
}
}
}
}
int main(){
int array[10];
int i;
printf("请输入10个数\n");
for (i = 0; i < 10; i++){ //接收用户的数值
scanf("%d", &array[i]);
}
printf("排序前的各元素是:");
for (i = 0; i < 10; i++){
printf("%d ", array[i]);
}
printf("\n经过冒泡排序后的数组是:");
Bubble_sort(array, 10);
for (i = 0; i < 10; i++){
printf("%d ", array[i]);
}
return 0;
}
如图,我输入十个数据:10,9,8,7,6,5,4,3,2,1
输出完成
如图,从程序的执行结果来,冒泡排序已经执行完毕,并且把数组中的十个元素从小到大排序了出来。
补充:数组作为函数形参时退化为指针,那么我们对代码进行修改。
void Bubble_sort(int *array, int len)//定义排序函数
{
assert(array != NULL && len >= 0);//断言指针不为空指针,数组的长度大于等于0
int i = 0;
int j = 0;
int temp;
for (i = 0; i < len - 1;i ++){//与除自己以外的其他9个元素进行比较,
for (j = 0; j < len - 1 - i; j++)//n-1-i的意思是每比较一趟元素就会少一个,比如说如果是执行的第三趟,那么元素的个数就是:10-1-3=6个
{
if (array[j] > array[j+1])//升序排法,如果前面的数大于后面的数,即调换位置
{
Swap(array,j,j+1);
}
}
}
}
如图我输入十个数字被数组接收,然后排序:
输出完成
在这里我重新使用while循环重写冒泡排序函数,将打印外置为函数,并将原来的数据由用户输入改为系统自动随机生成12个小于等于20的数然后进行排序:
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<time.h>
#define MAXSIZE 12
void initar(int *ar,int len)
{
assert(ar != nullptr);
for(int i = 0;i < len;i++){
ar[i] = rand() % 20;
}
}
void showar(int *ar,int len)
{
assert(ar != nullptr);
for(int i = 0;i < len;i++){
printf("%d ",ar[i]);
}
printf("\n--------------------------\n");
}
void swap(int *ar,int index1,int index2)
{
assert(ar != nullptr);
int temp = ar[index1];
ar[index1] = ar[index2];
ar[index2] = temp;
}
void Bubble_sort(int *ar,int len)
{
while(len--){
for(int i = 0;i < len;i++){
if(ar[i] > ar[i + 1]){
swap(ar,i,i + 1);
}
}
}
}
int main()
{
srand((unsigned int)time(NULL));
int ar[MAXSIZE];
initar(ar,MAXSIZE);
printf("原始数据为:\n");
showar(ar,MAXSIZE);
printf("排序后的数据为:\n");
Bubble_sort(ar,MAXSIZE);
showar(ar,MAXSIZE);
return 0;
}
随机生成12个数,如图为运行结果:
这里,我对代码进行优化,以减少检查的趟数,定义一个标签flag,把它放在while循环里面,参与循环的条件,当程序只走到while循环里面时flag = 0,当程序走到了交换元素这里,flag = 1;这样做的优点是,如果提前几趟已经排序好,flag值为0,那么len下标就不用一直挪动直到len = ar(数组首元素地址),优化后的代码为:
void Bubble_sort(int *ar,int len)
{
int flag = 1;
while(len-- && flag){
flag = 0;
for(int i = 0;i < len;i++){
if(ar[i] > ar[i + 1]){
flag = 1;
swap(ar,i,i + 1);
}
}
}
}
优化后的冒泡排序比优化前的冒泡排序效率高的原因是:当序列在找到所有的最大值之前就已经将序列排好序,直接结束掉函数。
补充:自定义函数sizeof的用法:
在数组中,我如果先开始定义数组为:
int array[] = {1,2,3,4,5,6,7,8,9,10};
可以直观的看到,数组的元素个数是10个,我们可以通过sizeof函数来获取到数组元素的个数:
sizeof(array) / sizeof(array[0]);
在此处,sizeof(array)的意思是,整个array数组占据的存储单元数;
sizeof(array[0])的意思是第一个数组元素暂时占据的存储单元数,等同于每个数组元素暂时占据的存储单元数;
所以,整个数组占据的存储单元数比上每个数组元素暂居的存储单元数就是整个数组的元素个数。