交换排序—冒泡排序(Bubble Sort)

举报
JavaEdge 发表于 2022/02/08 21:26:01 2022/02/08
【摘要】 1 思想待排序的一组数中,对当前还未排序的范围内的全部数,自上而下对相邻两数依次进行:比较调整让较大数往下沉,较小往上冒,故名冒泡排序。即每当两相邻的数比较后,发现它们的排序与排序要求相反时,就互换。 2 实现package com.sss;import java.util.Arrays;/** * @author JavaEdge */public class BubbleSort { ...

1 思想

待排序的一组数中,对当前还未排序的范围内的全部数,自上而下对相邻两数依次进行:

  • 比较
  • 调整

让较大数往下沉,较小往上冒,故名冒泡排序。

即每当两相邻的数比较后,发现它们的排序与排序要求相反时,就互换。
冒泡排序的示例

2 实现

package com.sss;

import java.util.Arrays;

/**
 * @author JavaEdge
 */
public class BubbleSort {

	public static void bubbleSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		for (int e = arr.length - 1; e > 0; e--) {
			for (int i = 0; i < e; i++) {
				if (arr[i] > arr[i + 1]) {
					swap(arr, i, i + 1);
				}
			}
		}
	}

	public static void swap(int[] arr, int i, int j) {
		arr[i] = arr[i] ^ arr[j];
		arr[j] = arr[i] ^ arr[j];
		arr[i] = arr[i] ^ arr[j];
	}

	// for test
	public static void comparator(int[] arr) {
		Arrays.sort(arr);
	}

	// for test
	public static int[] generateRandomArray(int maxSize, int maxValue) {
		int[] arr = new int[(int) ((maxSize + 1) * Math.random())];
		for (int i = 0; i < arr.length; i++) {
			arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
		}
		return arr;
	}

	// for test
	public static int[] copyArray(int[] arr) {
		if (arr == null) {
			return null;
		}
		int[] res = new int[arr.length];
		for (int i = 0; i < arr.length; i++) {
			res[i] = arr[i];
		}
		return res;
	}

	// for test
	public static boolean isEqual(int[] arr1, int[] arr2) {
		if ((arr1 == null && arr2 != null) || (arr1 != null && arr2 == null)) {
			return false;
		}
		if (arr1 == null && arr2 == null) {
			return true;
		}
		if (arr1.length != arr2.length) {
			return false;
		}
		for (int i = 0; i < arr1.length; i++) {
			if (arr1[i] != arr2[i]) {
				return false;
			}
		}
		return true;
	}

	// for test
	public static void printArray(int[] arr) {
		if (arr == null) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	// for test
	public static void main(String[] args) {
		int testTime = 500000;
		int maxSize = 100;
		int maxValue = 100;
		boolean succeed = true;
		for (int i = 0; i < testTime; i++) {
			int[] arr1 = generateRandomArray(maxSize, maxValue);
			int[] arr2 = copyArray(arr1);
			bubbleSort(arr1);
			comparator(arr2);
			if (!isEqual(arr1, arr2)) {
				succeed = false;
				break;
			}
		}
		System.out.println(succeed ? "Nice!" : "Fucking fucked!");

		int[] arr = generateRandomArray(maxSize, maxValue);
		printArray(arr);
		bubbleSort(arr);
		printArray(arr);
	}

}

3 改进

3.1 标志变量flag

标志某趟排序过程中,是否有数据交换。若某趟排序时并无数据交换,则说明数据已排好,可提前结束排序,避免后续多余的比较过程。

private void bubbleSort1(int[] arr) {
  int length = arr.length;
  boolean flag;
  for (int i = 0; i < length - 1; i++) {
    exchange = false;
    for (int j = 0; j < length - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        flag = true;
        int tmp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = tmp;
      }
    }
    // 若本次循环无任何数据交换,则跳出循环
    if (!flag) {
      break;
    }
  }
}

3.2 标志变量pos

记录每趟排序中最后一次进行交换的位置。

由于pos位置后的记录均已排序到位,所以执行下一趟排序时,只要扫描到pos位置即可!

void bubbleSort2(int[] arr) {
  int length = arr.length;
  // 初始时,最后位置保持不变
  int i = length - 1;
  while (i > 0) {
    // 每趟开始时,无记录交换
    int pos = 0;
    for (int j = 0; j < i; j++) {
      if (arr[j] > arr[j + 1]) {
        // 记录交换的位置
        pos = j;
        int tmp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = tmp;
      }
    }
    // 为下一趟排序作准备
    i = pos;
  }
}

3.3 正向和反向两遍冒泡

传统冒泡排序中每一趟排序操作只能找到一个max或min,考虑利用在每趟排序中进行正向和反向两遍冒泡的方法,一次便可得到max和min , 从而使排序趟数几乎减少一半。

void bubbleSort3(int[] arr) {
  int length = arr.length;
  // 设置变量初始值
  int low = 0;
  int high = length - 1;
  int tmp, j;
  while (low < high) {
    // 正向冒泡,找到max
    for (j = low; j < high; ++j) {
      if (arr[j] > arr[j + 1]) {
        tmp = arr[j];
        arr[j] = arr[j + 1];
        arr[j + 1] = tmp;
      }
    }
    // 修改high值, 前移一位
    --high;
    // 反向冒泡,找到min
    for (j = high; j > low; --j) {
      if (arr[j] < arr[j - 1]) {
        tmp = arr[j];
        arr[j] = arr[j - 1];
        arr[j - 1] = tmp;
      }
    }
    // 修改low值,后移一位
    ++low;
  }
}

相邻值相同时不交换情况下,可以保持稳定性。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。