排序算法---快速排序

  目前,最常见的排序算法大概有七八种,其中“快速排序”(Quicksort)使用得最广泛,速度也较快。

  "快速排序"的思想很简单,整个排序过程只需要三步:

  (1)在数据集之中,选择一个元素作为"基准"(v)。

  (2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。

  (3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

如果 e>v,向i后移位,纳入>v的范畴。

如果e<v, 将e和j+1元素互换位置

 

 

 全部元素放好位置之后,处理基准元素v。

交换l和j的位置,这样就使得左侧值均小于v,右侧值均大于v,而v就是它排序后应该放的位置。

代码实现如下。

template<typename T>
int __Partition(T arr[], int l, int r){    
    int v = arr[l];
    int j = l; //j保存分界位置
    for (int i = l; i <= r; i++){
        if (arr[i] < v){
            swap(arr[i], arr[j + 1]);
            j++;
        }
    }
    swap(arr[l], arr[j]);
    return j;
}
//对arr[l .... r]进行partition排序
//返回p 使得arr[l...p-1] < arr[p],arr[p+1 ... r] >arr[p]
template<typename T>
void __QuickSort(T arr[], int l,int r){
    if (l <= r){ return; }

    //当递归到一定数量时,采用插入排序 会提高速度
    //if (r - l <= 15){
    //    insertionSort(arr,l,r);
    //    return;
    //}

    int p = __Partition(arr, l, r);    

    __QuickSort(arr, l, p - 1);
    __QuickSort(arr, p + 1, r);

}
template<typename T>
void QuickSort(T arr[], int n){
    __quickSort(arr, 0, n - 1);
}

然而,在数组近乎有序的情况下,如果选取第一个元素作为基准值,快速排序耗时较长,其复杂度接近O(n^2)。 解决办法是随机选择数组中的一个元素作为基准值

代码变动地方如下。

template<typename T>
void QuickSort(T arr[], int n){
    srand(time(null)); //设置随机种子
    __quickSort(arr, 0, n - 1);
}
template<typename T>
int __Partition(T arr[], int l, int r){    
        swap(arr[l],arr[rand()%(r-l+1) + l]);  //选择一个随机元素和l交换
    int v = arr[l];
    int j = l; //j保存分界位置
    for (int i = l; i <= r; i++){
        if (arr[i] < v){
            swap(arr[i], arr[j + 1]);
            j++;
        }
    }
    swap(arr[l], arr[j]);
    return j;
}

此外,对于数组中有大量重复的数组元素时,可以采用以下办法。小于v的元素放在左侧,大于v的元素放在右侧

//方法2,对于有大量重复的数组元素采用的方法
template<typename T>
int __partition2(T arr[], int l, int r){
    swap(arr[l], arr[rand() % (r - l + 1) + l]);      //选择一个随机元素和l交换 对于有序数组将极大提高计算速度
    T v = arr[l];
    int i = l + 1, j = r;
    while (true){
        while (i <=r && arr[i] < v) i++;
        while (j >=l+1 && arr[j]>v) j--;
        if (i >= j) break;
        swap(arr[i], arr[j]);
        i++;
        j--;
    }
    swap(arr[l], arr[j]);
    return j;
}
原文地址:https://www.cnblogs.com/morongwendao/p/6902619.html