本文代码用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;
}