快速排序算法的优化总结

快速排序

    快速排序是一种交换类排序,它是对冒泡排序的一种改进,基本思想是:通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

    快速排序最好情况下的时间复杂度为O(nlogn),待排序列越接近无序,本算法的效率越高。最坏情况下的时间复杂度为O(n2),待排序列越接近有序,本算法的效率越低。平均时间复杂度为O(nlogn)。就平均时间而言,快速排序是所有排序算法中最好的。空间复杂度为O(logn),因为需要栈空间。

    快速排序的主要思想有分治与递归。

    下面是一个标准的快速排序算法C代码:

void swap(int a[], int i, int j)
{
    int tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

int partition(int a[], int low, int high)
{
    int pivot = a[low];
    while (low < high) {
        while (low < high && a[high] >= pivot)
            high--;
        swap(a, low, high);
        while (low < high && a[low] <= pivot)
            low++;
        swap(a, low, high);
    }
    return low;
}

void quick_sort(int a[], int low, int high)
{
    int pivot;
    if (low < high) {
        pivot = partition(a, low, high);
        quick_sort(a, low, pivot - 1);
        quick_sort(a, pivot + 1, high);
    }
}
  1. 后++改为前++,因为前++比后++效率上高那么一点,所以可以优化一丢丢;
  2. 我们可以注意到partition函数中调用swap函数的部分,当low=high时,仍然要进行交换,那么加一个if判断?no,这个部分频繁地调用swap函数,因为调用函数意味着推栈和出栈,性能损失极大,我们注意到partition实际是将一个“枢纽”元素想办法放到中间,使得左边的比它小,右边的比它大,那么我们可以考虑将枢纽元素保存下来,用赋值替代交换;
  3. 排序划分后在各个子部分分别递归再进行排序,递归层数越多性能影响越大,所以可以考虑使用迭代替换部分递归(尾递归);
  4. 快速排序通常会选第一个作为枢纽元素,当这个元素比较大或者比较小时会很大地影响性能,所以可以选取左端、中间和右端的三个数,取它们的中间值作为枢纽,这样可以极大概率地避免上述情况。 

优化后的快排如下:

void swap(int a[], int i, int j)
{
    int tmp = a[i];
    a[i] = a[j];
    a[j] = tmp;
}

int partition(int a[], int low, int high)
{
    int mid = low+(high-low)/2;
    if(a[low]>a[high]) swap(a, low, high);
    if(a[mid]>a[high]) swap(a, mid, high);
    if(a[mid]>a[low])  swap(a, low, mid);

    int pivot = a[low];
    int tmp = pivot;

    while (low < high) {
        while (low < high && a[high] >= pivot)
            --high;
        a[low] = a[high];
        while (low < high && a[low] <= pivot)
            ++low;
        a[high] = a[low];
    }
    a[low] = tmp;
    return low;
}

void quick_sort(int a[], int low, int high)
{
    int pivot;
    while (low < high) {
        pivot = partition(a, low, high);
        quick_sort(a, low, pivot - 1);
        low = pivot + 1;
    }
}
总之记住能量守恒定律,要么牺牲时间换空间,要么牺牲空间换时间,在现在计算机存储能力普遍提高的情况下,通常人们优化的方向都是后者。

猜你喜欢

转载自blog.csdn.net/lovego123/article/details/80078372