算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)

1、排序算法

排序也称排序算法(Sort Algorithm),排序是将一组数据,依指定的顺序进行排列的过程。

2、排序的分类

2.1按使用内存情况分

  1. 内部排序:
    指将需要处理的所有数据都加载到内部存储器中进行排序。
  2. 外部排序法
    数据量过大,无法全部加载到内存中,需要借助外部存储进行
    排序。
    算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)_第1张图片

2.2按是否为比较类分

  1. 比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
  2. 非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
    算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)_第2张图片

3、算法的复杂度

  • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
  • 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
  • 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
  • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
    (时间复杂度和空间复杂度)
    算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)_第3张图片

4、冒泡排序

4.1冒泡排序基本介绍

冒泡排序(Bubble Sorting)的基本思想:通过对待排序序列从前向后(从下标较小的元素开始),依次比较相邻元素的值,若发现逆序则交换,使值较大的元素逐渐从前部移向后部,就象水底下的气泡一样逐渐向上冒。
算法描述:

  • 比较相邻的元素。如果第一个比第二个大,就交换它们两个;
  • 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数;
  • 针对所有的元素重复以上的步骤,除了最后一个;
  • 重复上面的步骤,直到排序完成。

冒泡排序的优化
因为排序的过程中,各元素不断接近自己的位置,如果一趟比较下来没有进行过交换,就说明序列有序,因此要在排序过程中设置一个标志flag判断元素是否进行过交换。从而减少不必要的比较。(这里说的优化,可以在冒泡排序写好后,再进行)

4.2冒泡排序算法的实现

图解排序过程:
算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)_第4张图片
代码实现:

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class BubbleSort {
     
	public static void main(String[] args) {
     
		int arr1[] = {
     3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};	
		System.out.println("排序前");
		System.out.println(Arrays.toString(arr1));
		bubbleSort(arr1);	
		System.out.println("排序后");
		System.out.println(Arrays.toString(arr1));
			
		//测试一下冒泡排序的速度O(n^2), 给80000个数据,测试
		//创建要给80000个的随机的数组
		int[] arr2 = new int[80000];
		for(int i =0; i < 80000;i++) {
     
			arr2[i] = (int)(Math.random() * 8000000); //生成一个[0, 8000000) 数
		}	
		Date data1 = new Date();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String date1Str = simpleDateFormat.format(data1);
		System.out.println("排序前的时间是=" + date1Str);	
		bubbleSort(arr2);	
		Date data2 = new Date();
		String date2Str = simpleDateFormat.format(data2);
		System.out.println("排序后的时间是=" + date2Str);			
	}
	//冒泡排序算法
	public static void bubbleSort(int[] arr) {
     
		// 冒泡排序 的时间复杂度 O(n^2), 自己写出
		int temp = 0; // 临时变量
		boolean flag = false; // 标识变量,表示是否进行过交换
		for (int i = 0; i < arr.length - 1; i++) {
     
			for (int j = 0; j < arr.length - 1 - i; j++) {
     
				// 如果前面的数比后面的数大,则交换
				if (arr[j] > arr[j + 1]) {
     
					flag = true;
					temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
			if (!flag) {
      // 在一趟排序中,一次交换都没有发生过
				break;
			} else {
     
				flag = false; // 重置flag!!!, 进行下次判断
			}
		}
	}
}
排序前
[3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
排序后
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
排序前的时间是=2020-09-14 12:16:50
排序后的时间是=2020-09-14 12:16:58

5、快速排序算法

5.1快速排序算法的基本介绍

快速排序(Quicksort) 是对冒泡排序的一种改进
基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
算法描述:
快速排序使用分治法来把一个串(list)分为两个子串(sub-lists)

  • 从数列中挑出一个元素,称为 “基准”(pivot);
  • 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
  • 递归(recursive)地把小于基准值元素的子数列和大于基准值元素的子数列排序。

比如:
算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)_第5张图片

5.2快速排序算法的实现

算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)_第6张图片

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class QuickSort {
     
	public static void main(String[] args) {
     
		int arr1[] = {
     3,44,38,5,47,15,36,26,27,2,46,4,19,50,48};
		System.out.println("排序前");
		System.out.println(Arrays.toString(arr1));
		quickSort(arr1,0,arr1.length-1);	
		System.out.println("排序后");
		System.out.println(Arrays.toString(arr1));
		
		//测试快排的执行速度
		// 创建要给80000个的随机的数组
		int[] arr2 = new int[8000000];
		for (int i = 0; i < 8000000; i++) {
     
			arr2[i] = (int) (Math.random() * 8000000); // 生成一个[0, 8000000) 数
		}		
		System.out.println("排序前");
		Date data1 = new Date();
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String date1Str = simpleDateFormat.format(data1);
		System.out.println("排序前的时间是=" + date1Str);	
		quickSort(arr2, 0, arr2.length-1);		
		Date data2 = new Date();
		String date2Str = simpleDateFormat.format(data2);
		System.out.println("排序前的时间是=" + date2Str);
	}
	
	//快速排序算法
	public static void quickSort(int[] arr,int left, int right) {
     
		int l = left; //左下标
		int r = right; //右下标
		//pivot 中轴值
		int pivot = arr[(left + right) / 2];
		int temp = 0; //临时变量,作为交换时使用
		//while循环的目的是让比pivot 值小放到左边
		//比pivot 值大放到右边
		while( l < r) {
      
			//在pivot的左边一直找,找到大于等于pivot值,才退出
			while( arr[l] < pivot) {
     
				l += 1;
			}
			//在pivot的右边一直找,找到小于等于pivot值,才退出
			while(arr[r] > pivot) {
     
				r -= 1;
			}
			//如果l >= r说明pivot 的左右两的值,已经按照左边全部是
			//小于等于pivot值,右边全部是大于等于pivot值
			if( l >= r) {
     
				break;
			}		
			//交换
			temp = arr[l];
			arr[l] = arr[r];
			arr[r] = temp;		
			//如果交换完后,发现这个arr[l] == pivot值 相等 r--, 前移
			if(arr[l] == pivot) {
     
				r -= 1;
			}
			//如果交换完后,发现这个arr[r] == pivot值 相等 l++, 后移
			if(arr[r] == pivot) {
     
				l += 1;
			}
		}		
		// 如果 l == r, 必须l++, r--, 否则为出现栈溢出
		if (l == r) {
     
			l += 1;
			r -= 1;
		}
		//向左递归
		if(left < r) {
     
			quickSort(arr, left, r);
		}
		//向右递归
		if(right > l) {
     
			quickSort(arr, l, right);
		}	
	}
}
排序前
[3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
排序后
[2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
排序前
排序前的时间是=2020-09-14 12:36:40
排序前的时间是=2020-09-14 12:36:41

排序算法相关博文:

算法(Java实现)-图解十大经典排序算法(一)——交换排序(冒泡排序、快速排序)
算法(Java实现)-图解十大经典排序算法(二)——插入排序(直接插入排序、希尔排序)
算法(Java实现)-图解十大经典排序算法(三)——选择排序(简单选择排序、堆排序)
算法(Java实现)-图解十大经典排序算法(四)——归并排序
算法(Java实现)-图解十大经典排序算法(五)——计数排序、桶排序、基数排序

欢迎持续关注:博客主页
我的个人博客站:jQueryZK Blog

你可能感兴趣的:(算法(Java),算法,交换排序,冒泡排序,快速排序,内排序)