自学算法 之 [快速排序](java)

简介

快速排序的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

简单来说就是:
1、取一个基准数,进行一次快速排序(执行一次方法),把所有小于它的数放左边,所有大于它的数放右边。
2、左半部分递归(进行第1步),右半部分递归(进行第1步)。
3、直到整个数组都有序。

举个例子:

我们要对 [3,5,1,2,4] 排序。

1、把 [3,5,1,2,4] 这一部分进行快速排序(执行一次方法)。
2、一路下来,得到数组 [2,1,3,5,4](3左侧的数都小于3,右侧数都大于等于3)
3、把左侧的 [2,1] 和右侧的 [5,4] 两个部分分别进行快速排序(分别执行一次方法)
4、分别得到 [1,2][4,5]
5、排序完毕,得到 [1,2,3,4,5]

思路

1、写两个方法,一个是getIndex(int[] arr, int left, int right), 一个是quickSort(int[] arr, int left, int right)

2、getIndex(int[] arr, int left, int right) 方法:

	public static int getIndex(int[] arr, int left, int right)
	{
		//基准数是该区域[left, right]的第一个数
		int temp = arr[left];	//【此时left的位置是空出来的】
		while(left < right)
		{
			//先从right开始判断, 如果大于等于temp就不管他,right自减;如果小于temp就(跳出循环)和left位置交换
			while(left < right && arr[right] >= temp)
			{
				right --;
			}
			arr[left] = arr[right];	//【此时right的位置是空出来的】
			
			//随后从left开始判断,如果小于temp就不管他,如果大于temp就和right位置交换
			while(left < right && arr[left] <= temp)
			{
				left ++;
			}
			arr[right] = arr[left];	//【此时left的位置是空出来的】
		}
		//退出了循环,说明left==right,此时left\right就是基准数temp应该放的位置
		arr[left] = temp;	//【填补空出来的位置】
		return left;
	}

(1)在 [left, right] 区域内,定义基准数temp = arr[left](也就是区域的第一个数)。

[ {3},5,1,2,[4] ], left = 0,right = 4,temp = 3;

(2)先从该区域的末尾开始扫描,如果有小于3的数,把它和 left 位置交换(注意:可以直接忽视3这个元素,因为它已经存到了temp 变量里了)。

[ {3},5,1,2,[4] ], left = 0,right = 4,temp = 3,4 > 3成立,right减1
[ {3},5,1,[2],4 ], left = 0,right = 3,temp = 3,2 > 3不成立, 交换:
[ {2},5,1,[3],4 ], left = 0,right = 3,temp = 3

(3)然后从该区域的起点开始扫描,如果有大于3的数,把它和right 位置交换

[ {2},5,1,[3],4 ], left = 0,right = 3,temp = 3,2 < 3成立,left加1
[ 2,{5},1,[3],4 ], left = 1,right = 3,temp = 3,5 < 3不成立,交换:
[ 2,{3},1,[5],4 ], left = 1,right = 3,temp = 3

(4)重复第(2)步。

[ 2,{3},1,[5],4 ], left = 1,right = 3,temp = 3,5>3成立,right减1
[ 2,{3},[1],5,4 ], left = 1,right = 2,temp = 3,1>3不成立,交换:
[ 2,{1},[3],5,4 ], left = 1,right = 2,temp = 3

(5)重复第(3)步。

[ 2,{1},[3],5,4 ], left = 1,right = 2,temp = 3,1<3成立,left加1
[ 2,1,{[3]},5,4 ], left = 2,right = 2,temp = 3

(6)当left = right时,退出以上循环,left \ right 的位置就是基准数temp应该放的位置。返回这个位置的值。

arr[left] = temp;
return left;

2、quickSort(int[] arr, int left, int right) 方法:

	public static void quickSort(int[] arr, int left, int right)
	{
		if(left < right)
		{
			int mid = getIndex(arr, left, right);
			//左侧区域递归
			quickSort(arr, left, mid - 1);
			//右侧区域递归
			quickSort(arr, mid + 1, right);
		}
	}

完整代码


public class ALGO_234
{

	public static int getIndex(int[] arr, int left, int right)
	{
		//基准数是该区域[left, right]的第一个数
		int temp = arr[left];	//【此时left的位置是空出来的】
		while(left < right)
		{
			//先从right开始判断, 如果大于等于temp就不管他,right自减;如果小于temp就(跳出循环)和left位置交换
			while(left < right && arr[right] >= temp)
			{
				right --;
			}
			arr[left] = arr[right];	//【此时right的位置是空出来的】
			
			//随后从left开始判断,如果小于temp就不管他,如果大于temp就和right位置交换
			while(left < right && arr[left] <= temp)
			{
				left ++;
			}
			arr[right] = arr[left];	//【此时left的位置是空出来的】
		}
		//退出了循环,说明left==right,此时left\right就是基准数temp应该放的位置
		arr[left] = temp;	//【填补空出来的位置】
		return left;
	}
	
	public static void quickSort(int[] arr, int left, int right)
	{
		if(left < right)
		{
			int mid = getIndex(arr, left, right);
			//左侧递归
			quickSort(arr, left, mid - 1);
			//右侧递归
			quickSort(arr, mid + 1, right);
		}
	}
	
	public static void main(String[] args)
	{
//		Scanner sc = new Scanner(System.in);
//		String s = sc.nextLine();
//		char[] str = s.toCharArray();
		
		int[] arr = {3, 4, 1, 2, 5};
		quickSort(arr, 0, arr.length - 1);
		for(int i = 0; i < arr.length; i++)
			System.out.print(arr[i] + " ");
		
	}

}

输出结果:

1 2 3 4 5
原创文章 9 获赞 2 访问量 857

猜你喜欢

转载自blog.csdn.net/cxrshiz7890/article/details/104581286