算法Day03 快速排序 重点

今天是算法学习的第三天,这几天太忙,没有学的太多,昨天花了时间去把排序算法的基础实现弄懂,今天抽个时间来把博客写了。

 

前几天学了选择排序,插入排序,归并排序,今天来学习一门O(n)级别的算法,也是现在最重要的基础排序算法之一,快速排序。

这是一门十分重要的排序算法,这是公认的最伟大的排序算法之一,为什么会中这么说,因为他在效率方面提升了提多,相比于前面提到的几种排序算法,到底提升了多少,稍后我们进行真实的代码检测。

 

废话不多说,开始快速排序算法介绍:

 

思想:

每一轮排序中,将一个数字放到排好序后它应该在的位置。一般这个数字我们都选择数组的第一个数字。这个过程我们一般叫做partition,每一轮patition过后,都会返回一个坐标,这个坐标的上的数字已经处在了一个正确的位置。然后递归对这个数字左边和右边的区间进行排序,(因为这个数字已经排好了,所以只需要考虑它左边和右边),而且每轮partition还会使得这个坐标左右的数都小于等于这个数,这个坐标右边的数都会大于等于这个数。

好像有点绕口,可能会有些难以理解

做法:

   定义两个坐标,i,j

                i:数组循环的索引,用来表示当前需要进行比对的数字的下表

                j:我们的标杆最后应该处的位置(这个过程是动态的,需要不断的进行遍历,最终停下来的位置就是我们要找的位置)

从第二个数字开始依次和我们的标杆(一般是本轮循环中的区间中,数组第一个元素)进行比较,

                       如果这个数字比我们的标杆大,那就不必理会,因为我们需要的就是使得标杆右边的数字都比我们的标杆大

                       如果这个数字比我们的标杆小,那就让他和我们的j位置的后一位进行交换

当 i 循环到最后一个元素的时候,此时我们的 j 位置就是我们的标杆应该处在的位置,这时候我们的标杆还在数组的第一个位置,所以我们需要将 j 位置的数字和我们的标杆数字进行交换,然会 j ;这样下来,j 左边的数字都不大于它,它右边的数字都不小于它,这就是我们要的结果

 

不知道我表达的是否清楚,这个过程有点晦涩难懂,下面是我的代码,小伙伴可以跟着代码走一遍,有疑问的可以评论,我们一起交流。

 

package com.smarking.lzy.part1;

public class QuitSort {
	
	public static void sort(int [] arr,int left,int right) {
		if(left >= right) {
			return;
		}
		
		int p = partition(arr,left,right);
		sort(arr,left,p - 1);
		sort(arr,p + 1,right);
	}
	
	private static int partition(int [] arr ,int left,int right) {
		int value = arr[left];
		int j = left;
		for(int i = left + 1;i <= right;i++) {
			if(arr[i] < value) {
				j++;//要先移动j的位置,再进行交换,因为这样可以保证第一个元素(参考值)不被移动
				/*试想,如果刚开始的时候元素都小于value,那么如果先交换再进行j的自增,那么就会造成一种情况
				 * 在arr[l]的位置,存放的值就不是value了,这时候当我们退出for循环的时候,这时候交换arr[i]和arr[j]
				 * 就没什么意义了,因为交换完成之后,arr[j]存放的值就不是value了
				 * 
				 * 
				 * */
				
				
				
				SortTestHelper.swap(arr, i, j);
			}
		}
		
		SortTestHelper.swap(arr, left, j);
		
		return j;
	}
	
	
	public static void main(String[] args) {
		int testTime = 1000000;
		int maxValue = 100;
		int maxSize = 100;
		boolean success = true;
		for(int i = 0;i < testTime;i++) {
			int [] arr1 = SortTestHelper.generateRandomArray(maxSize, maxValue);
			int [] arr2 = SortTestHelper.copyArray(arr1);
			sort(arr1,0,arr1.length-1);
			SortTestHelper.comparator(arr2);
			if(!SortTestHelper.isEqual(arr1, arr2)) {
				success = false;
				SortTestHelper.printArray(arr1);
				SortTestHelper.printArray(arr2);
				break;
			}
		}
		
		if(success) {
			System.out.println("Nice!!!");
		}else {
			System.out.println("Fuck!");
		}
	}

}

   顺便贴上SortTestHelper的代码,这是一个辅助类

 

package com.smarking.lzy.part1;

import java.util.Arrays;

/**
 * 排序校验工具类
 * */
public  class SortTestHelper {
	//交换arr数组中,i和j位置上的数字
	public static void swap(int [] arr,int i,int j) {
		int value = arr[i];
		arr[i] = arr[j];
		arr[j] = value;
	}
	
	public static void heapSort(int[] arr) {
		if (arr == null || arr.length < 2) {
			return;
		}
		for (int i = 0; i < arr.length; i++) {
			heapInsert(arr, i);
		}
		int size = arr.length;
		swap(arr, 0, --size);
		while (size > 0) {
			heapify(arr, 0, size);
			swap(arr, 0, --size);
		}
	}

	public static void heapInsert(int[] arr, int index) {
		while (arr[index] > arr[(index - 1) / 2]) {
			swap(arr, index, (index - 1) / 2);
			index = (index - 1) / 2;
		}
	}

	public static void heapify(int[] arr, int index, int size) {
		int left = index * 2 + 1;
		while (left < size) {
			int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;
			largest = arr[largest] > arr[index] ? largest : index;
			if (largest == index) {
				break;
			}
			swap(arr, largest, index);
			index = largest;
			left = index * 2 + 1;
		}
	}

	// 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();
	}
	
	public static void mPrint(int [] arr) {
		if(arr.length == 0 || arr == null) {
			throw new RuntimeException("Array could not be noll!!");
		}
		int len = arr.length;
		for(int i = 0;i < len;i++) {
			System.out.println(arr[i]);
		}
	}
}

  以上就是快速排序基础版本的实现代码,随时欢迎评论交流

 

为了测试快速排序的速度,我自己做了一个简单的测试demo,分别用选择排序,插入排序,快速排序进行排序,并输出他们的用时,结果如下

 

QuitSort time : 6ms
InsertSort time : 586ms
mergeSort time : 1010ms

 

测试代码如下:

package com.smarking.lzy.part1;

public class Test {
	
	private static long startTime;
	private static long endTime;
	private static long time;
	
	
	public static void main(String[] args) {
		QuitSort quitSort = new QuitSort();
		InserSort insertSort = new InserSort();
		MergeSort mergeSort = new MergeSort();
		
		
		int maxValue = 10000;
		int maxSize = 100000;
		int [] arr = SortTestHelper.generateRandomArray(maxSize, maxValue);
		int [] arr1 = SortTestHelper.copyArray(arr);
		int [] arr2 = SortTestHelper.copyArray(arr);
		int [] arr3 = SortTestHelper.copyArray(arr);
		
		startTime = System.currentTimeMillis();
		quitSort.sort(arr1, 0, arr1.length -1 );
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("QuitSort time : " + time+"ms");
		
		startTime = System.currentTimeMillis();
		insertSort.sort(arr2);
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("InsertSort time : " + time+"ms");
		
		startTime = System.currentTimeMillis();
		mergeSort.sort(arr3,0,arr3.length - 1);
		endTime = System.currentTimeMillis();
		time = endTime - startTime;
		System.out.println("mergeSort time : " + time+"ms");
	}

}

 

算法是计算机的灵魂,也是一名优秀的软件工程师必备的技能,算法的学习是漫长,需要积淀的过程,可能其中很长一段时间都看不到显著的成功,但是我会坚持下去,我知道,这是一次长久的投资,坚持下去,必定成功!一旦成功,那将是自己崭新未来的开始!

有想要一起学习的朋友可以评论留下联系方式,我们一起共同探讨,共同监督!

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值