本帖最后由 我是隔壁老王呀 于 2015-6-16 12:04 编辑
在学习编程过程中,会接触很多的排序算法,其中关键字搜索的排序算法中,效率较高是快速排序算法。在参考了很多老师的讲解,查阅了相关的博客后,我对快速排序算法有一些理解,整理后在这里分享给大家,也希望大家能指出不足,给出更为优秀的思想。
=========================分割线===============================
一、基本思想
一个元素自然有序;局部有序,全局有序。
快速排序算法采用的是分治策略[sup]1[/sup],与递归结合,减少了排序过程中的比较次数。
通过一趟排序,按照某一参考值,将要排序的数据分割为独立的两部分,其中一部分数据比另一部分数据都要小,左边序列数据都要小于右边序列数据。然后再用此方法对两部分数据进行排序,整个过程可以递归进行,直到剩下单个元素,将无序变为有序。[sup]2[/sup]
注1 分治法基本思想
(1)分解(划分):将原问题分解为若干个与原问题相似的子问题。
(2)求解:递归的求解子问题。若子问题的规模足够小,直接求解。
(3)组合:将每个子问题的解组合成原问题的解。
二、 算法的实现步骤
设需排序的无序区为: A......A[j]
1、基准值的选取
选择其中的一个值作为基准值pivot。(怎么选择)
2、划分
通过基准值pivot,将无序区A......A[j]划分为左右两个部分,使左边各元素的值小于pivot,右边各元素的值大于等于pivot。
3、递归求解
重复(1)、(2)的步骤,分别岁左右两边元素递归的进行快速排序
4、组合
左右两边分别有序,则整个序列有序。
三、快速算法过程
在这里有一篇文章关于快速算法具体的步骤,讲解的通俗易懂,在这里给出链接:http://blog.csdn.net/morewindows/article/details/6684558 《白话经典算法之六 快速算法,快速搞定》
四、基准值的选取
1、基准值是从序列中选取的,但是不同的选择方法对序列的排序效率影响很大
2、设函数:FindPivot() 是求Ai......A[j]的基准值pivot = A[k]的函数,其返回基准元素的下标k.- int FindPivot(int i, int j)
- {
- ......
- return k ;
- }
复制代码 五、无序区的划分
- <span style="font-style: normal;"><span style="font-style: normal;">/**
- * 无序区域的划分,找到划分后区域中基准值所在的位置
- * @param i 无序区域的最左边下标
- * @param j 无序区域最右边下标
- * @param pivot 基准值
- * @return 划分后基准值所在的位置
- */
- private int Partition(int i, int j, int pivot)
- {
- int l; // 左游标
- int r; // 右游标
- do{
- for(l = i; arr[l] < pivot; l++); // 基准值左侧元素均比其小
- for(r = j; arr[r] >= pivot; r--); // 基准值右侧元素均大于等于其
- if(l < r)
- swap(arr,l,r); // 交换左右两侧不满足大小的值
- }while(l <= r); // 当左右游标交叉时,退出
-
- return l; // 返回分界点处位置
- }
复制代码 六、快速排序的递归求解- /**
- * 快速排序的递归实现
- * @param i 需排序区域最左侧位置
- * @param j 需排序区域最右侧位置
- */
- public void QuickSort( int i, int j)
- {
- int pivot; // 存放基准值
- int selectIndex; // 选择排序前基准值所在位置
- int sortIndex; // 排序后基准值应在位置
- selectIndex = FindPivot(i,j);
-
- if(selectIndex != -1)
- {
- pivot = arr[selectIndex];
- //sortIndex = Partition(i,j,pivot);
- sortIndex = Partition(selectIndex,j,pivot); // pivotIndex之前的元素在选择时已经排好序
- QuickSort(i, sortIndex-1);
- QuickSort(sortIndex, j);
- }
-
- return;
- }
复制代码 七、快速排序的完整代码
基准值选取:无序序列中最先找到两个不同元素中较大值
- package com.itheima;
- /**
- * 快速排序法对数组进行排序
- * @author Fourier
- */
- public class QuickSortDemo {
-
- private int[] arr;
-
- public QuickSortDemo(int[] arr)
- {
- this.arr = arr;
- }
-
- /**
- * 基准值的选取。从序列中最先找到两个不同元素中的较大者.
- * @param arr 待查找数组
- * @param i 待查找数组开始位置
- * @param j 待查找数组末尾位置
- * @return 两个不同元素中的最大者的下标;如果所有元素值相同,则返回-1
- */
- private int FindPivot(int i, int j)
- {
- int firstValue = arr[i];
- int k = 0;
- // 从第i+1个元素开始,向右寻找最近的两个不相等的元素,返回较大值的下标
- for(k = i+1; k<= j ; k++)
- {
- if(arr[k] > firstValue)
- {
- return k;
- }else if(arr[k] < firstValue)
- return i;
- }
- // 当序列中所有元素值相同时,返回-1
- return -1;
- }
-
- /**
- * 交换两个元素的值
- * @param arr
- * @param i
- * @param j
- */
- private void swap(int[] arr, int i, int j)
- {
- int temp;
- temp = arr[i];
- arr[i] = arr[j];
- arr[j] = temp;
-
- return;
- }
-
- /**
- * 无序区域的划分,找到划分后区域中基准值所在的位置
- * @param i 无序区域的最左边下标
- * @param j 无序区域最右边下标
- * @param pivot 基准值
- * @return 划分后基准值所在的位置
- */
- private int Partition(int i, int j, int pivot)
- {
- int l; // 左游标
- int r; // 右游标
- do{
- for(l = i; arr[l] < pivot; l++); // 基准值左侧元素均比其小
- for(r = j; arr[r] >= pivot; r--); // 基准值右侧元素均大于等于其
- if(l < r)
- swap(arr,l,r); // 交换左右两侧不满足大小的值
- }while(l <= r); // 当左右游标交叉时,退出
-
- return l; // 返回分界点处位置
- }
-
- /**
- * 快速排序的递归实现
- * @param i 需排序区域最左侧位置
- * @param j 需排序区域最右侧位置
- */
- public void QuickSort( int i, int j)
- {
- int pivot; // 存放基准值
- int selectIndex; // 选择排序前基准值所在位置
- int sortIndex; // 排序后基准值应在位置
- selectIndex = FindPivot(i,j);
-
- if(selectIndex != -1)
- {
- pivot = arr[selectIndex];
- //sortIndex = Partition(i,j,pivot);
- sortIndex = Partition(selectIndex,j,pivot); // pivotIndex之前的元素在选择时已经排好序
- QuickSort(i, sortIndex-1);
- QuickSort(sortIndex, j);
- }
-
- return;
- }
-
- /**
- * 显示数组中元素
- */
- public void show()
- {
- System.out.print("[");
- for(int i = 0; i < arr.length-1; i++)
- {
- System.out.print(arr[i]+",");
- }
- System.out.println(arr[arr.length-1]+"]");
-
- return;
- }
-
- public static void main(String[] args) {
-
- int [] arr = {4,4,4,1,7,3,6,9,2,8,6,9,2,3,4,7,2,8};
-
- QuickSortDemo qsd = new QuickSortDemo(arr);
- System.out.println("==============快速排序前===============");
- qsd.show();
- qsd.QuickSort(0, arr.length-1);
- System.out.println("==============快速排序后===============");
- qsd.show();
-
- return;
- }
- }
-
复制代码
八。参考资料
《白话经典算法之六 快速排序 快速搞定》 http://blog.csdn.net/morewindows/article/details/6684558
注2《数据结构与算法》 张岩 哈尔滨工业大学
《数据结构:思想与实现》 俞勇 上海交通大学
《快速排序算法 C语言实现》 http://blog.chinaunix.net/uid-26404477-id-3329885.html
|
|