快速与归并排序

快速、归并与堆排序的平均时间复杂度为O(nlog2n),其中归并排序和堆排序的平均、最坏和最好的时间复杂度三者相同都是O(nlog2n),快速排序的最好情况是O(nlog2n),在数组为有序的情况下快速排序达到最坏的情况为O(n2)。其中快速排序和堆排序都是不稳定的,归并排序是稳定的。

排序算法稳定,是指能保证排序前2个相等的数在序列的前后位置顺序和排序后他们两个的前后位置顺序相同。即:a=b,排序前a在b之前,排序后a还应该在b之前。

一、快速排序

思想:

1、i = L, j = R;将基准数挖出形成一个坑

2、j--由后向前找比它小的数,找到后挖出填补第一坑a[i]

3、i++由前向后找比它大的数,找到后也挖出填补前一个坑a[j]

4、重复执行2与3的步骤,知道i==j,将基准数填入a[i]

/*参数说明:
l:表示左边起始的位置
r:表示右边起始的位置*/
void quickSort(vector<int> &a, int l, int r)
{
    if (l < r)
    {
        int i = l, j = r, tmp = a[i];
        while (i < j)
        {
            /*找到右边第一个小于tmp的数*/
            while (i<j && a[j]>=tmp)
                j--;
            a[i++] = a[j];
            /*找到左边第一个大于tmp的数*/
            while (i<j && a[i]<tmp)
                i++;
            a[j--] = a[i];
        }
        a[i] = tmp;                //当i==j时将基准数赋值给a[i]
        quickSort(a, l, i-1);      //递归调用,对分好的两侧进行再排序
        quickSort(a, i+1, r);
    }
}

二、归并排序

思想:二分法;将数组不断递归地分为A、B两组,直至两组内的元素都是有序的,那么就开始将这两组进行合并。即,当A,B两组内的元素个数为1时,便开始合并。

/*合并数组
参数说明:
a:需要合并的数组
first:起始位置
mid:中间位置
last:结束位置
tmp:临时数组
*/
void mergeArray(vector<int> &a, int first, int mid, int last, vector<int> &tmp)
{
    int i = first, j = mid+1;
    int k = 0;
    while (i<=mid && j <=last)
    {
        if (a[i] <= a[j])
            tmp[k++] = a[i++];
        else
            tmp[k++] = a[j++];
    }
    /*另一个数组完全遍历完成*/
    while (i <= mid)
        tmp[k++] = a[i++];
    while (j <= last)
        tmp[k++] = a[j++];
    for (int i = 0; i < k; i++)
        a[first+i] = tmp[i];
}

/*归并排序*/
void mergeSort(vector<int> &a, int first, int last, int &tmp)
{
    if (first < last)
    {
        int mid = (first+last)/2;
        mergeSort(a, first, mid, tmp);
        mergeSort(a, mid, last, tmp);
        mergeArray(a, first, mid, last, tmp);
    }
}

猜你喜欢

转载自blog.csdn.net/zishengzheng/article/details/81783148