快速排序的实现及优化

1、分割操作单向扫描

public class QuickSort {
    public int partition(int[] a, int left, int right) {
        int temp, pivot;//pivot存放主元
        int i, j;
        pivot = a[right];
        i = left;
        for (j = left; j < right; j++) {
            if (a[j] < pivot) {
                //交换值
               temp = a[i];
               a[i] = a[j];
               a[j] = temp;
               i++;
            }
        }
        a[right] = a[i];
        a[i] = pivot;
        return i;//把主元的下标返回
    }

    public void quickSort(int[] a, int left, int right) {
        int center;
        if (left < right) {
            center = partition(a, left, right);
            quickSort(a, left, center - 1);//左半部分
            quickSort(a, center + 1, right);//右半部分
        }
    }
}

2、分割操作双向扫描

 private int partition2(int[] a, int left, int right) {
        int i, j;
        int pivot = a[left];
        i = left + 1;
        j = right;
        while (true) {
            //向右扫描
            while (i <= j && a[i] <= pivot)
                i++;
            //向左扫描
            while (i <= j && a[j] >= pivot)
                j--;
            if (i >= j)
                break;
            //交换
            int temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
        //把a[j]和主元交换
        a[left] = a[j];
        a[j] = pivot;
        return j;
    }

3、因为快速排序的最坏时间复杂度是O(n2)。例如有可能会出现一种极端的情况,每次分割的时候,主元左边的元素个数都为0,而右边都为n-1个。这个时候,就需要分割n次了。而每次分割整理的时间复杂度为O(n),所以最坏的时间复杂度为O(n2)。而最好的情况就是每次分割都能够从数组的中间分割了,这样分割logn次就行了,此时的时间复杂度为O(nlogn)。而平均时间复杂度,则是假设每次主元等概率着落在数组的任意位置,最后算出来的时间复杂度为O(nlogn),至于具体的计算过程,我就不展开了。

//随机选取主元的方法,为了降低极端情况出现的可能性,我们可以随机选取主元,而不是固定一个位置选取。
int random_partition(int[] arr, int left, int right)
{
 i = random(left, right);//随机选取一个位置
 //在把这个位置的元素与ar[left]交换
 swap(arr[i], arr[left]);
 
 return partition(arr, left, right);
}

猜你喜欢

转载自blog.csdn.net/weixin_41699562/article/details/104046268
今日推荐