冒泡排序及其优化

本文代码用C++实现。

交换排序之冒泡排序。所谓交换排序是:两两比较排序记录的关键字,并交换不满足次序要求的那些偶对,直到全部满足为止。常见的两种是:冒泡排序与快速排序。

冒泡排序思想:通过无序区中相邻记录关键字之间的比较和位置的交换,使关键字最大的数据如气泡一半逐渐往上漂浮直至水面。整个算法是从最下面的记录开始,对每个相邻记录的关键字进行比较,且使得较大的数据换至较小的数据之上,使得经过一次冒泡排序之后,关键字最大的记录到达最上端。接着,在在剩下的数据中找关键字次大的数据,并把它换在第二个位置上。以此类推,直到所有记录都有序为止。

冒泡排序第一版
void bubble_sort1(int *arr,int sz)
{
	int i = 0;
	int j = 0;
	for (j = 0; j < sz-1; j++) {  //循环几趟
		for (i = 0; i < sz - 1 - j; i++) {  //每一趟循环几次
			if (arr[i] > arr[i + 1]) {
				int tmp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = tmp;
			}
		}
	}
}
冒泡排序第二版

优化:若一趟循环中一次交换都没有发生,则说明已经排序完全,后面的趟数就没得必要了,所以对趟数即外循环进行优化

void bubble_sort2(int *arr, int sz)
{
	int i = 0;
	int j = 0;
	int flag = 0;

	for (j = 0; j < sz - 1; j++) {
		flag = 0;//每进入一趟,将flag至为0,若此次遍历中没有发生交换意味着已经排序成功,则直接return
		for (i = 0; i < sz - 1 - j; i++) {

			if (arr[i] > arr[i + 1]) {
				int tmp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = tmp;
				flag = 1;//只要发生了交换就让flag = 1;
			}
		}
		if (0 == flag) {
			return;//每进入一趟,将flag至为0,若此次遍历中没有发生交换意味着已经排序成功,则直接return
		}
	}
}

冒泡排序第三版

优化思路:在一趟排序中若数组后面的数字是有序的,其实是不需要对后面的数字进行遍历排序,所以得对内循环进行优化

void bubble_sort3(int *arr, int sz)
{
	int i = 0;
	int j = 0;
	int flag = 0;
	int k = sz -1;//k用来控制内循环的次数
	int pos = 0;

	for (j = 0; j < sz - 1; j++) {
		flag = 0;		
		for (i = 0; i < k; i++) {

			if (arr[i] > arr[i + 1]) 
			{
				int tmp = arr[i];
				arr[i] = arr[i + 1];
				arr[i + 1] = tmp;
				flag = 1;
				pos = i;//把一趟循环中最后进行交换的下标当做下一趟循环的控制条件(即我下一趟循环只要循环到上一趟最后交换的地方就OK,不用往后走了,后面都排好序了),避免了对数组中已经排好序的元素进行无谓的比较
			}
		}
		if (0 == flag) {
			return;
		}
		k = pos;//把一趟中最后一次的进行交换的下标当做下一趟循环的控制条件,避免了对数组中已经排好序的元素进行无谓的比较
	}
}
冒泡排序第四版

优化:在第一版的基础上加入正向扫描和反向扫描

void bubble_sort4(int *arr, int sz)
{
	int i = 0;
	int j = 0;
	int z = 0;

	//正向循环加上反向循环,只需要循环sz/2次就可以了
	for (i = 0; i <= sz/2 ; i++) 
	{
		//正向扫描->最大值在最右边
		for (j = i; j < sz - 1-i; j++)
		{  
			if (arr[j] > arr[j + 1]) {
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		//反向扫描->最小值在最左边
		for (z = sz -2-i; z > i; z--)
		{
			if (arr[z] < arr[z - 1]) {
				int tmp = arr[z];
				arr[z] = arr[z - 1];
				arr[z - 1] = tmp;
			}
		}

	}
}
冒泡排序第五版

把第四版和第二版,第三版混在一起

void bubble_sort5(int *arr, int sz)
{
	int i = 0;
	int j = 0;
	int z = 0;
	int flag = 0;
	int k = sz - 1;
	int q = 0;
	int temp = 0;
	int ttemp = 0;

	//正向循环加上反向循环,只需要循环sz/2次就可以了
	for (i = 0; i <= sz / 2; i++)
	{
		flag = 0;
		//正向扫描->最大值在最右边
		for (j = i; j < k; j++)
		{
			if (arr[j] > arr[j + 1]) {
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 1;
				temp = j;
			}
		}
		if (0 == flag) {
			return;
		}
		k = temp;

		//反向扫描
		for (z = sz - 2 - i; z > q; z--)
		{
			if (arr[z] < arr[z - 1]) {
				int tmp = arr[z];
				arr[z] = arr[z - 1];
				arr[z - 1] = tmp;
				flag = 1;
				ttemp = z;
			}
		}
		if (0 == flag) {
			return;
		}
		q = ttemp;

	}
}
main函数代码
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<iostream>
using namespace std;

int main()
{
	//创建数组来测试每个方法所占的时间
	int arr[10000];
	int arr1[10000];
	srand((unsigned int)time(NULL));
	for (int i = 0; i < 10000; i++) {
		arr[i] = rand() % 100;//随机数组
	}

	for (int i = 0; i < 10000; i++) {
		arr1[i] = arr[i];
	}

	int sz = sizeof(arr) / sizeof(arr[0]);

	clock_t start, finish;
	double time = 0.0;

	start = clock();
	bubble_sort1(arr, sz);
	finish = clock();
	time = (double)(finish - start) / (CLOCKS_PER_SEC);
	cout << "1号="<< time << endl;

	//之所以这里要创建了循环,是因为上面已经给数组排过序了,数组现在是个有序的数组了,所以我们得把他复原回原来的数组
	for (int i = 0; i < 10000; i++) {
		arr[i] = arr1[i];
	}
	start = clock();
	bubble_sort2(arr, sz);
	finish = clock();
	time = (double)(finish - start) / (CLOCKS_PER_SEC);
	cout << "2号=" << time << endl;


	for (int i = 0; i < 10000; i++) {
		arr[i] = arr1[i];
	}
	start = clock();
	bubble_sort3(arr, sz);
	finish = clock();
	time = (double)(finish - start) / (CLOCKS_PER_SEC);
	cout << "3号=" << time << endl;

	for (int i = 0; i < 10000; i++) {
		arr[i] = arr1[i];
	}
	start = clock();
	bubble_sort4(arr, sz);
	finish = clock();
	time = (double)(finish - start) / (CLOCKS_PER_SEC);
	cout << "4号=" << time << endl;


	for (int i = 0; i < 10000; i++) {
		arr[i] = arr1[i];
	}
	start = clock();
	bubble_sort5(arr, sz);
	finish = clock();
	time = (double)(finish - start) / (CLOCKS_PER_SEC);
	cout << "5号=" << time << endl;

	system("pause");
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值