快速排序

算法学习的第一天


算法学习之快速排序

快速排序采用分治的思想。

它的基本思想是:选择一个分界点,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

一般快速排序的使用有以下几个步骤:

①确定分界点。一般分界点的确定方式为:左边界 l; 右边界 r ; 中间值。 常采取左边界确定分界点的方法;

②调整区间。将整个数组调整成为两个区间。第一个区间中所包含的元素都小于等于分界点;另一个区间中所包含的元素都大于等于分界点;退出之后,该基准就处于数列的中间位置。

③递归处理左右两个区间,使其成为一个有序序列。

在调整区间这一步中,通用的方法为

①开两个数组a[ ],b[ ];

②原数组中的元素进行遍历。元素小于等于分界点的,就存在a[ ]数组中;元素大于分界点的,就存在b[ ] 数组中;

③遍历结束,分别对a[ ],b[ ]数组排序,排序结束后进行合并。

 

笔者学习的快速排序则是引用两个指针 i ,j 处理步骤②。

函数代码

void quick_sort(int q[] , int l ,int r) //定义一个函数quick_sort 其中q[]为原数组,l为q[]的左边界,r为q[]的边界
{    if(l >= r) return ; //如果左边界大于等于右边界,跳出函数
    
    int x = q[l],i = l - 1 , j = r +1; //定义x为分界点(左边界),定义两个指针i,j i指针为左指针,j指针为右指针
    while(i < j) //当i的值小于j的值时
    {
        do i++ ; while(q[i] < x); //如果当前i所代表的元素小于分界点,那么i则向右前进一位,否则停止
        do j-- ; while(q[j] > x);//如果当前j所代表的元素大于分界点,那么j则向左前进一位,否则停止
        if(i < j) swap(q[i],q[j]); //当i,j最终停下时,i代表的元素小于j代表的元素,那么i,j两个元素交换位置
    } //最终,分界点左边的元素都小于分界点;分界点右边的元素都大于分界点。
    
    quick_sort(q ,l ,j); //第一次排序的是分界点左边的元素
    quick_sort(q , j + 1 , r);//第二次排序的是分界点右边的元素
}

 

快速排序是不稳定的算法,它不满足稳定算法的定义。
算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

 

快速排序平均时间复杂度O(N*lgN)  

 

例题:

P1177 【模板】快速排序 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

查看代码
 #include <cstdio>
#include <iostream>

using namespace std;

int n; 
const int N = 1e5;
int q[N];

void quick_sort(int q[],int l ,int r)
{
    if(l >= r) return ;
    int x = q[l], i = l -1 , j = r + 1;
    while(i < j)
    {
        do i++ ; while(q[i] < x);
        do j-- ; while(q[j] > x);
        if(i < j) swap(q[i],q[j]);
    }
    
    quick_sort(q,l,j);
    quick_sort(q,j+1,r);
}

int main()
{
    scanf("%d",&n);
    for(int i = 0 ; i < n ; i++) scanf("%d",&q[i]);
    quick_sort(q,0,n-1);
    for(int i = 0 ; i < n ;i++) printf("%d ",q[i]);
    return 0;
}
posted @ 2022-12-27 21:53  litershry  阅读(47)  评论(0)    收藏  举报