2. 冒泡排序及优化

算法思路:
  每一趟排序都将无序区中的最大值放到最后。通过从左向右依次进行相邻数据的大小比较,来将最大值一点一点的移动到最后。

算法特点:

  1. 每趟排序可能进行多次交换,每次交换都是相邻元素之间的交换;
  2. 稳定排序;

在这里插入图片描述

基础的冒泡排序

public class BubbleSort {
    
    
	/**
	 * 交换数组arr下标为i和j处的值
	 */
	public static void swap(int[] arr, int i, int j) {
    
    
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
	/**
	 * 基础的冒泡排序
	 */
	public static void bubbleSort1(int[] arr) {
    
    
		// 获取数组长度
		int len = arr.length;
		for (int i = 1; i < len; i++) {
    
    
			for (int j = 0; j < len - i; j++) {
    
    
				if (arr[j] > arr[j + 1])
					swap(arr, j, j+1);
			}
		}
	}

  冒泡排序在输入的数据是正序时最快,再输入的数据是逆序时最慢。

冒泡排序优化 I:设置标志位

  即使输入的数据已经是正序的,使用基础的冒泡排序依旧是要进行比较的。例如,待排序的数组是 int[] arr = {1,2,3,4,5,6,7,8,9},冒泡排序在第一趟排序时并没有交换数据,接下来的7趟排序完全是多余的,因此提出了一种优化,使用额外的一个标记,来记录本次排序是否进行过交换,如果没有进行交换表示当前已经是有序的,不需要进行进行。

/**
 * 当某一趟冒牌排序时没有发生交换,表明此时数组已经排好序了。<br>
 * 增加一个标志位,减少无用的比较。
 */
public static void bubbleSort2(int[] arr) {
    
    
	int len = arr.length;
	for(int i = 1; i < len; i++) {
    
    
		// flag 表示数组当前是否已经是有序数组
		boolean flag = true;
		for (int j = 0; j < len - i; j++) {
    
    
			if (arr[j] > arr[j+1]) {
    
    
				swap(arr, j, j+1);
				flag = false;
			}
		}
		if (flag)
			break;
	}
}

冒泡排序优化 II:记录最后一次交换的位置

  如果发生了交换就记录每趟排序最后一次发生交换的位置,并将其作为下一次排序的结束边界。
  主要用于解决待排序数组中,无序区的后面一小半区域是有序的情况,减少排序次数。

/**
 * 记录每趟冒泡排序时最后一次发生交换的下标,在这个下标之后的都是有序的。
 */
public static void bubbleSort3(int[] arr) {
    
    
	int len = arr.length;
	// 最后一次交换的位置
	int pos = 0;
	// 结束边界
	int k = len-1;
	for (int i = 0; i < len && k != 0; i++) {
    
    
		for (int j = 0; j < k; j++) {
    
    
			if (arr[j] > arr[j+1]) {
    
    
				swap(arr, j, j+1);
				pos = j+1;
			}
		}
		// 更新结束边界
		k = pos;
		pos = 0;
	}
}

冒泡排序优化 III:双向冒泡排序

  双向冒泡排序,又叫鸡尾酒排序(Cocktail Sort)。先从左往右比较一次,再从右往左比较一次,然后又从左往右比较一次,以此类推。
  双向排序主要是为了优化前面的大部分元素都已经排好序的数组的排序。例如对于数组 [2,3,4,5,6,7,8,9,1],如果使用普通的冒泡排序,需要比较8次,而换成双向冒泡排序,只需比较3次。

/**
 * 单纯的双向排序,先进行一次从左到右的排序,再进行一次从右到左的排序
 */
public static void bubbleSort4(int[] arr) {
    
    
	int len = arr.length;
	int left = 0; 
	int right = len-1;	
	while (left < right) {
    
    
		for (int i = left; i < right; i++) {
    
    
			if (arr[i] > arr[i+1])
				swap(arr, i, i+1);
		}
		right--;
		for (int i = right; i > left; i--) {
    
    
			if (arr[i - 1] > arr[i])
				swap(arr, i - 1, i);
		}
		left++;
	}
}

冒泡排序优化 IV:结合I、II和III

/**
 * 优化II和优化III结合
 */
public static void bubbleSort5(int[] arr) {
    
    
	int len = arr.length; 
	int left = 0;
	int right = len-1;
	int pos = 0;
	boolean flag = false;
	while (left < right) {
    
    
		for (int i = left; i < right; i++) {
    
    
			if (arr[i] > arr[i+1]) {
    
    
				swap(arr, i, i+1);
				pos = i;
				flag = true;
			}
		}
		if (!flag)
			break;
		flag = false;
		right = pos;
		for (int i = right; i > left; i--) {
    
    
			if (arr[i-1] > arr[i]) {
    
    
				swap(arr, i-1, i);
				pos = i;
				flag = true;
			}
		}
		if (!flag)
			break;
		flag = false;
		left = pos;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40395874/article/details/115062145
今日推荐