快排算法quickSort

来源:互联网 发布:jackson json 官网 编辑:程序博客网 时间:2024/03/29 03:51

感觉在网上查找到的有关quickSort的资料都不是很详细或简洁,特把自己的理解做个总结,记录,以待分享。

1、时间复杂度及推导思想:

快排的平均时间复杂度为O(nlog(n)),最差为O(n*n)。

其时间复杂度的推到可利用二叉树的思想:切分的次数是树高n,查找的次数为logn,总的时间复杂度为nlog(n)。

数学推导思想:首先我们请注意到,所有实际的排序操作都在partition中做完的,因为排序从根本上来讲还是元素的交换,那么在partition函数中进行了多少次比较就是整个算法复杂度的关键。

如果将A中的元素排列成S (z1,z2,…,zn),zi表示第i小元素。在整个排序过程中,任意两个元素最多比较一次。如果我们定义一个变量Xij,当zi和zj发生比较时为1,否则为0。那么

把对所有可ij求和Xij就得到全部的比较次数。我们对这个和求期望,根据期望的线性性,也就是zi和zj发生比较的概率的总和。

那么zi和zj发生比较的概率是多少呢?在Sij这个子集合里,只有zi或zj被选为pivot的时候他们才会有比较,而平均来讲,这个概率是2/(j-i+1)。这就是S中任意两个元素发生比较的概

率。如果不在这个集合里呢?

因此所有比较次数的表达式是Sum(2/(j-i+1)), i从1到n-1,j从i+1到n。

他可以变形为n个Sum(2/k)k从1到n。

最终得到n*lg(n)。

2、实现的原理及思路

快排的整体思想是随机挑选一个元素,对数组进行分割,以将所有比它小的元素排在前面,比它大的元素排在后面。分割反复执行,直到有序。

1)给定一个数组arr[ ],定义数组首元素的索引和尾元素的索引分别为left和right。

2)以中间位置arr[(left+right)/2]为基准点pivot。

3)从左面第一个元素开始向右搜索,即由左向右(left++),找到第一个大于pivot的值arr[left],则停止,与同样停止的arr[right]进行交换,swap(arr,left,right)。

4)从右面第一个元素开始向左搜索,即由右向左(right--),找到第一个小于pivot的值arr[right],则停止,与同样停止的arr[left]进行交换,swap(arr,left,right)。

5)重复3)、4)步操作,直到满足left==right,这时arr[left]=arr[right]=pivot,而pivot的位置就是在数组中的正确位置。

6)递归调用,对pivot的左右部分分别进行2)~ 5)的操作,最后解出问题。

核心思想代码:

    void quickSort(int arr[],int left, int right){        int index = partition(arr, left, right);        if (left < index-1){//对左半部分进行切分,递归排序            quickSort(arr, left, index-1);        }        if (right > index){//对右半部分进行切分,递归排序            quickSort(arr, index, right);        }    }    int partition(int arr[],int left, int right){        int pivot = arr[(left+right)/2];//选取一个基准点        while(left <= right){            while (arr[left] < pivot) left++;//指针从左面开始向基准点移动,直到不满足条件停止            while (arr[right] > pivot) right--;//指针从右面开始向基准点移动,直到不满足条件停止            //对停止的左右两个元素进行换位,调整左右索引值,然后继续循环            if(left <= right){                swap(arr, left, right);                left++;                right--;            }        }        return left;//返回的位置满足arr[left]=arr[right]=pivot    }    void swap(int arr[],int left,int right){        int temp;        temp = arr[left];        arr[left] = arr[right];        arr[right] = temp;    }


java可测试执行代码:

package com.company;/** * Created by zu on 14-10-4. */public class QuickSortTest {    public static void quickSort(int arr[],int left, int right){        int index = partition(arr, left, right);        if (left < index-1){//对左半部分进行切分,递归排序            quickSort(arr, left, index-1);        }        if (right > index){//对右半部分进行切分,递归排序            quickSort(arr, index, right);        }    }    public static int partition(int arr[],int left, int right){        int pivot = arr[(left+right)/2];//选取一个基准点        while(left <= right){            while (arr[left] < pivot) left++;//指针从左面开始向基准点移动,直到不满足条件停止            while (arr[right] > pivot) right--;//指针从右面开始向基准点移动,直到不满足条件停止            //对停止的左右两个元素进行换位,调整左右索引值,然后继续循环            if(left <= right){                swap(arr, left, right);                left++;                right--;            }        }        return left;//返回的位置满足arr[left]=arr[right]=pivot    }    public static void swap(int arr[],int left,int right){        int temp;        temp = arr[left];        arr[left] = arr[right];        arr[right] = temp;    }    //打印数组    public static void print(int arry[])    {        for(int i:arry)        {            System.out.print(i+" ");        }        System.out.println();    }    public static void main(String args[]){        int arr[] = {1,43,5454,33,4,33,6,66,23,22,45,2,3,35};        int len = arr.length;        System.out.print("快速排序前数组元素为:");        print(arr);        quickSort(arr,0,len-1);        System.out.print("快速排序后数组元素为:");        print(arr);    }}
执行结果输出:

快速排序前数组元素为:1 43 5454 33 4 33 6 66 23 22 45 2 3 35 快速排序后数组元素为:1 2 3 4 6 22 23 33 33 35 43 45 66 5454



0 0
原创粉丝点击