快排简单介绍
快速排序作为经典的排序算法之一,其实也用到了冒泡排序的思想,冒泡排序是每一轮将最大(最小)的元素放到一端,而快速排序是每一轮找出比基准元素大、小的所有元素,然后放在基准元素的两边。是分治法体现之一。
单边循环法
只从数组的一边对元素进行遍历和交换。首先选定基准元素pivot,同时,设置一个mark指针指向数列起始位置,这个mark指针代表 小于基准元素的区域边界
- 从基准元素的下一个位置开始遍历数组
- 如果遍历到元素大于基准元素,就继续往后遍历
- 如果遍历到元素小于基准元素,则需要做两件事:第一mark++,增加区域边界;第二 交换最新遍历到元素和mark指针所在位置的元素进行交换。
代码演示
/** * * 单边循环法 * */ public static void quickSort(int [] arr,int startIndex,int endIndex){ //递归结束条件:startIndex>=endIndex if(startIndex>=endIndex){ return; } //得到基准元素位置 int pivotIndex=partition(arr,startIndex,endIndex); quickSort(arr,startIndex,pivotIndex-1); //根据基准元素,分成两部分进行递归排序 quickSort(arr,pivotIndex+1,endIndex); } /** * 分治(单边循环法) * @param arr 待交换的数组 * @param startIndex 起始下标 * @param endIndex 结束下标 * @return */ private static int partition(int [] arr,int startIndex,int endIndex){ //取第一个位置(也可以选择随机位置)的元素作为基准元素 int pivot=arr[startIndex]; int mark=startIndex; for (int i=startIndex+1;i<=endIndex;i++){ if (arr[i]<pivot){ mark++; int p=arr[mark]; arr[mark]=arr[i]; arr[i]=p; } } //元素1和mark指针所在的位置的元素交换,因为元素1归属于小于pivot区域 arr[startIndex]=arr[mark]; //最后把pivot元素交换到mark指针所在位置,这一轮宣告结束 arr[mark]=pivot; //返回 return mark; } public static void main(String[] args) { int arr[]={4,4,6,5,3,2,8,1}; quickSort(arr,0,arr.length-1); System.out.println(Arrays.toString(arr)); } }
双边循环法
双边循环法的思路是:先从right指针开始,right指向的元素如果大于或等于基准元素,则该元素不动(right指针的作用是保证它指向的元素以及它右边的元素都是大于基准元素的),然后right指针向左移动一位(进行比较下一个);如果right指针指向的元素比基准元素小,则right指针停止移动(right指针一直指向这个元素,做一个标识,直到left指针移动到比基准元素大的数字位置,然后和right指针进行交换),然后切换到left指针,如果left指向的元素小于或等于基准元素,则该元素不动,left指针继续向右移动,寻找下一个元素,如果指向的元素比基准元素大,则和right指针指向的元素进行元素交换(实现比基准元素小的数字放在它的左边,大的数字放在它的右边),然后right指针向左移动一位(之所以left指针不向右移动,是因为如果left和right指针相邻,二者同时移动,会出现right指针在left指针左边的情况),之后再从right指针开始新的一轮比较。
/** * 分治(双边循环法) * @param arr 待交换的数组 * @param startIndex 起始下标 * @param endIndex 结束下标 * @return */ public static void quickSort(int [] arr,int startIndex,int endIndex){ if (startIndex >= endIndex) { return; } int pivotIndex=partition(arr,startIndex,endIndex); quickSort(arr,startIndex,pivotIndex-1); quickSort(arr,pivotIndex+1,endIndex); } public static int partition(int [] arr,int startIndex,int endIndex){ //取第一个位置(也可以选择随机位置)的元素作为基准元素 int pivot =arr[startIndex]; int left=startIndex; int right=endIndex; while(left!=right){ //控制right指针比较并左移 while(left<right && arr[right]>pivot) right--; //控制left指针并右移 while(left<right && arr[left]<=pivot) left++; //交换left和right指针所指的元素 if (left<right){ int temp=arr[left]; arr[left] =arr[right]; arr[right]=temp; } } //pivot 和指针重合点交换 arr[startIndex] =arr[left]; arr[left]=pivot; return left; } public static void main(String[] args) { int arr[]={4,4,6,5,3,2,8,1}; quickSort(arr,0,arr.length-1); System.out.println(Arrays.toString(arr)); }
非递归实现
public static void stackQuickSort(int[] arr,int startIndex,int endIndex){ //声明一个栈,用来存放每一个数组的起始值和结尾值 Stack<Map<String,Integer>> mapStack=new Stack<>(); //第一轮数组的起始,终止下标,以hash的形式入栈 Map<String,Integer> map=new HashMap<>(); map.put("startIndex",startIndex); map.put("endIndex",endIndex); mapStack.push(map); //当栈中有元素的时候 while(!mapStack.isEmpty()){ //每一次都是取最后一次入栈的元素,是基准元素的右半部分的数组 Map<String,Integer> popParam=mapStack.pop(); //获取每一轮排好序之后基准元素的位置 int pivotIndex=partition(arr,popParam.get("startIndex"),popParam.get("endIndex")); //当基准元素左边有元素的时候放在栈里面 if (popParam.get("startIndex")<pivotIndex) { Map<String,Integer> leftParamMap=new HashMap<>(); leftParamMap.put("startIndex",popParam.get("startIndex")); leftParamMap.put("endIndex",pivotIndex-1); // 把基准元素左半部分的起止下标放在栈中 mapStack.push(leftParamMap); } //当基准元素右边有元素的时候就放在栈里面 if (popParam.get("endIndex")>pivotIndex) { Map<String,Integer> rightParamMap=new HashMap<>(); rightParamMap.put("startIndex",pivotIndex+1); rightParamMap.put("endIndex",popParam.get("endIndex")); //把基准元素右半部分的起止下标放在栈中 mapStack.push(rightParamMap); } } } private static int partition(int [] arr,int startIndex,int endIndex){ int pivot=arr[startIndex]; int mark=startIndex; for (int i=startIndex;i<=endIndex;i++){ if (arr[i]<pivot){ mark++; int p=arr[mark]; arr[mark]=arr[i]; arr[i]=p; } } arr[startIndex]=arr[mark]; arr[mark]=pivot; return mark; } public static void main(String[] args) { int arr[]={4,4,6,5,3,2,8,1}; stackQuickSort(arr,0,arr.length-1); System.out.println(Arrays.toString(arr)); }