五十道编程小题目 --- 28 八大排序算法 java 之 06快速排序



6. 交换排序—快速排序(Quick Sort)

快速排序算法介绍

      快速排序和归并排序都使用分治法来设计算法,区别在于归并排序把数组分为两个基本等长的子数组,分别排好序之后还要进行归并(Merge)操作,而快速排序拆分子数组的时候显得更有艺术,取一个基准元素拆分之后基准元素左边的元素都比基准元素小,右边的元素都不小于基准元素,这样只需要分别对两个子数组排序即可,不再像归并排序一样需要归并操作


基本思想:

1)选择一个基准元素,通常选择第一个元素或者最后一个元素,

2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。

3)此时基准元素在其排好序后的正确位置

4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。

快速排序的示例:

(a)一趟排序的过程:

(b)排序的全过程


算法的实现:

import java.util.Random;

public class QuickSort {

	// 快速排序
	private static void quickSort(int[] a) {
		System.out.println("在数组中从0到"+(a.length-1)+"基准元素索引:" + 0);
		subQuickSort(a, 0, a.length-1);
	}
	
	private static void subQuickSort(int[] a,int start, int end) {
		if(a == null || end-start<2){
			return ;
		}
		
		int keyIndex = quickSortPortion(a, start, end);
		System.out.println("在数组中从"+start+"到"+end+"基准元素索引变换:" + keyIndex);
		if(keyIndex == start){
			subQuickSort(a, start+1, end);
		}else if(keyIndex == end){
			subQuickSort(a, start, end-1);
		}else{
			subQuickSort(a, start, keyIndex-1);
			subQuickSort(a, keyIndex+1, end);
		}
		
		
	}

	private static int quickSortPortion(int[] a, int start, int end) {
		int minIndex = (end-start) / 2 + start; // minIndex定义为数组的中间索引
		int key = start; // 将数组的第一个元素的索引定义为基准元素
		int h = end;
		
		
		
		System.out.println("快速排序------------>");
		for (int i = start; i < end; i++) { // 比较 length-1次
			if (key <= minIndex) { // 如果基准元素在前半部分
				if (a[key] > a[h]) { // 元素值比基准元素值小
					swap(a, key, h); // 交换位置
					int tmp = h;
					h = key + 1;
					key = tmp;
				} else {
					h--;
				}
			} else { // 如果基准元素在后半部分
				if (a[key] < a[h]) { // 元素值比基准元素值大
					swap(a, key, h); // 交换位置
					int tmp = key;
					key = h;
					h = tmp - 1;

				} else {
					h++;
				}
			}
			print(a);
		}
//		print(a);
		return key;
	}

	// 交换数组元素
	private static void swap(int[] arr, int i, int j) {
		if (i == j) {
			return;
		}
		arr[i] = arr[i] + arr[j];
		arr[j] = arr[i] - arr[j];
		arr[i] = arr[i] - arr[j];
	}

	// 打印数组
	public static void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	public static void main(String[] args) {

		int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
		System.out.println("排序前  : ");
		print(a);

		System.out.println("排序  : ");
		quickSort(a);
		print(a);
		
		// System.out.println("任意数组测试:");
		// Random r = new Random();
		// int[] testArr = new int[20];
		// for (int i = 0; i < 20; i++) {
		// testArr[i] = r.nextInt(100);
		// }
		//
		// System.out.println("排序前 : ");
		// print(testArr);
		//
		// System.out.println("排序后: ");
		// print(quickSort(testArr));

	}

	

}

输出结果:

排序前  : 
49 38 65 97 76 13 27 49 
排序后 : 
在数组中从0到7基准元素索引:0
快速排序------------>
49 38 65 97 76 13 27 49 
27 38 65 97 76 13 49 49 
27 38 65 97 76 13 49 49 
27 38 49 97 76 13 65 49 
27 38 13 97 76 49 65 49 
27 38 13 49 76 97 65 49 
27 38 13 49 76 97 65 49 
在数组中从0到7基准元素索引变换:3
快速排序------------>
13 38 27 49 76 97 65 49 
13 27 38 49 76 97 65 49 
在数组中从0到2基准元素索引变换:1
快速排序------------>
13 27 38 49 49 97 65 76 
13 27 38 49 49 76 65 97 
13 27 38 49 49 65 76 97 
在数组中从4到7基准元素索引变换:6
13 27 38 49 49 65 76 97 



分析:

快速排序是一个不稳定的排序方法。

 

6. 交换排序—快速排序(Quick Sort)

快速排序算法介绍

      快速排序和归并排序都使用分治法来设计算法,区别在于归并排序把数组分为两个基本等长的子数组,分别排好序之后还要进行归并(Merge)操作,而快速排序拆分子数组的时候显得更有艺术,取一个基准元素拆分之后基准元素左边的元素都比基准元素小,右边的元素都不小于基准元素,这样只需要分别对两个子数组排序即可,不再像归并排序一样需要归并操作


基本思想:

1)选择一个基准元素,通常选择第一个元素或者最后一个元素,

2)通过一趟排序讲待排序的记录分割成独立的两部分,其中一部分记录的元素值均比基准元素值小。另一部分记录的 元素值比基准值大。

3)此时基准元素在其排好序后的正确位置

4)然后分别对这两部分记录用同样的方法继续进行排序,直到整个序列有序。

快速排序的示例:

(a)一趟排序的过程:

(b)排序的全过程


算法的实现:

import java.util.Random;

public class QuickSort {

	// 快速排序
	private static void quickSort(int[] a) {
		System.out.println("在数组中从0到"+(a.length-1)+"基准元素索引:" + 0);
		subQuickSort(a, 0, a.length-1);
	}
	
	private static void subQuickSort(int[] a,int start, int end) {
		if(a == null || end-start<2){
			return ;
		}
		
		int keyIndex = quickSortPortion(a, start, end);
		System.out.println("在数组中从"+start+"到"+end+"基准元素索引变换:" + keyIndex);
		if(keyIndex == start){
			subQuickSort(a, start+1, end);
		}else if(keyIndex == end){
			subQuickSort(a, start, end-1);
		}else{
			subQuickSort(a, start, keyIndex-1);
			subQuickSort(a, keyIndex+1, end);
		}
		
		
	}

	private static int quickSortPortion(int[] a, int start, int end) {
		int minIndex = (end-start) / 2 + start; // minIndex定义为数组的中间索引
		int key = start; // 将数组的第一个元素的索引定义为基准元素
		int h = end;
		
		
		
		System.out.println("快速排序------------>");
		for (int i = start; i < end; i++) { // 比较 length-1次
			if (key <= minIndex) { // 如果基准元素在前半部分
				if (a[key] > a[h]) { // 元素值比基准元素值小
					swap(a, key, h); // 交换位置
					int tmp = h;
					h = key + 1;
					key = tmp;
				} else {
					h--;
				}
			} else { // 如果基准元素在后半部分
				if (a[key] < a[h]) { // 元素值比基准元素值大
					swap(a, key, h); // 交换位置
					int tmp = key;
					key = h;
					h = tmp - 1;

				} else {
					h++;
				}
			}
			print(a);
		}
//		print(a);
		return key;
	}

	// 交换数组元素
	private static void swap(int[] arr, int i, int j) {
		if (i == j) {
			return;
		}
		arr[i] = arr[i] + arr[j];
		arr[j] = arr[i] - arr[j];
		arr[i] = arr[i] - arr[j];
	}

	// 打印数组
	public static void print(int[] arr) {
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i] + " ");
		}
		System.out.println();
	}

	public static void main(String[] args) {

		int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
		System.out.println("排序前  : ");
		print(a);

		System.out.println("排序  : ");
		quickSort(a);
		print(a);
		
		// System.out.println("任意数组测试:");
		// Random r = new Random();
		// int[] testArr = new int[20];
		// for (int i = 0; i < 20; i++) {
		// testArr[i] = r.nextInt(100);
		// }
		//
		// System.out.println("排序前 : ");
		// print(testArr);
		//
		// System.out.println("排序后: ");
		// print(quickSort(testArr));

	}

	

}

输出结果:

排序前  : 
49 38 65 97 76 13 27 49 
排序后 : 
在数组中从0到7基准元素索引:0
快速排序------------>
49 38 65 97 76 13 27 49 
27 38 65 97 76 13 49 49 
27 38 65 97 76 13 49 49 
27 38 49 97 76 13 65 49 
27 38 13 97 76 49 65 49 
27 38 13 49 76 97 65 49 
27 38 13 49 76 97 65 49 
在数组中从0到7基准元素索引变换:3
快速排序------------>
13 38 27 49 76 97 65 49 
13 27 38 49 76 97 65 49 
在数组中从0到2基准元素索引变换:1
快速排序------------>
13 27 38 49 49 97 65 76 
13 27 38 49 49 76 65 97 
13 27 38 49 49 65 76 97 
在数组中从4到7基准元素索引变换:6
13 27 38 49 49 65 76 97 



分析:

快速排序是一个不稳定的排序方法。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值