算法入门(快排,归并,二分详解!)

编码之路,道阻且艰


目录

一、快速排序

 二、归并排序

 三、整数二分

 四、浮点数二分

总结


一、快速排序

思路:分治思想,先随机从数组中取一个数x,然后通过数组中的数与x比较划分左右两个区间,然后递归处理左右两个区间,完成快排。时间复杂度o(n*logn)

算法入门(快排,归并,二分详解!)_第1张图片

 暴力求解做法:用a,b数组分别存小于等于x和大于x的数,然后在各自数组里排序,然后依次将a,b数组的内容存入q中。

算法入门(快排,归并,二分详解!)_第2张图片

题目:

算法入门(快排,归并,二分详解!)_第3张图片

代码:

#include

void my_qsort(int a[] , int l , int r)
{
    if(l>=r)//如果数组中只有一位或者0位数直接返回,不需要排序
    {return;}
    int lc=l-1,rc=r+1;//取左边界左边一个,取右边界右边一个
    int x=a[l + r >>1];//取中间值,防止超时。
    while(lcx);//从右边界开始遍历,如果找到小于等于x的就停止循环。
        if(lc

 二、归并排序

思路:分治思想,先确定分界点mid=(left+right)/2,然后递归排序left,right,最后归并,合二为一。主要通过双指针实现,两个指针分别执行分组后的最前面。时间复杂度o(n*logn),每层n次,有logn层。

算法入门(快排,归并,二分详解!)_第4张图片

 题目:

算法入门(快排,归并,二分详解!)_第5张图片

 代码:

#include

void merge_sort(int a[],int l,int r)
{
    if(l>=r) return;
    int mid=(l+r)>>1;//定义一个中间值
    int lc=l,rc=mid+1;//第一个序列从l开始,第二个序列从mid+1开始
    merge_sort(a,l,mid);//递归排序左边的数(第一序列)
    merge_sort(a,mid+1,r);//递归排序右边的数(第二序列)
    int tmp[100010];//定义一个数组存放排序好的数
    int k=0;//数组下标
    while(lc<=mid&&rc<=r)//判断第一序列和第二序列是否全部遍历,是的话退出循环
    {
        if(a[lc]<=a[rc]) tmp[k++]=a[lc++];//如果第一序列的数小就先放入数组
        else tmp[k++]=a[rc++];//否则第二序列的数放入数组
    }
    //上面循环介绍可能没有放完两个序列中一个序列的数。(不相同长度的序列)
    while(lc<=mid) tmp[k++]=a[lc++];//检查第一序列有没有放完,没有就在尾部接着放
    while(rc<=r) tmp[k++]=a[rc++];//同上检查第二序列
    for(int i=l,j=0;i<=r;i++,j++)//最后循环把tmp数组给回a数组,为了上面的递归计算。
    a[i]=tmp[j];
}

int main()
{
    int n;
    scanf("%d",&n);
    int a[100010];
    for(int i=0;i

 三、整数二分

思路:

情况一(二分红色边界):判断a[mid]>1,如果不加1的话,可能出现数组两个数(1,2),一直向下取整,l=mid=1,陷入死循环。

情况二(二分绿色边界):判断a[mid]>=x是否在绿色里面,如果是true就证明那个数的位置小于mid,则在红色里面,所以让r=mid;如果是false,则证明那个数在绿色,那个数的位置大于mid的位置,就应该让l=mid+1。

算法入门(快排,归并,二分详解!)_第6张图片

算法入门(快排,归并,二分详解!)_第7张图片 题目:

算法入门(快排,归并,二分详解!)_第8张图片

代码:

#include
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    int a[100010];
    for(int i=0;i>1;
            if(a[mid]>=x) r=mid;//如果a[mid]>=x ,就证明那个数在左边,就缩小右边的距离
            else l=mid+1;//否则缩小左边距离,因为判断过mid了,所以直接从mid+1判断。
        }
        if(a[l]!=x) printf("-1 -1\n");//如果第一次判断了没发现这个数,就证明这个数不在这里面。
        else //发现了这个数再去寻找他的下一个位置
        {
            printf("%d ",l);
            int l=0,r=n-1;
            while(l>1;
                if(a[mid]<=x) l=mid;//上面已经发现mid左边是小于x的了,所以我们判断是否小于x,是就让左边缩小。
                else r=mid-1;//否则让右边缩小,因为已经判断过mid了,直接从mid-1开始判断。
            }
            printf("%d\n",l);
        }
    }
}

 四、浮点数二分

思路:浮点数二分没有整数二分那么麻烦,不需要判断边界条件,所以直接判断大于小于就好了。

题目:

算法入门(快排,归并,二分详解!)_第9张图片

代码:

#include
int main()
{
    double n;
    scanf("%lf",&n);
    double l=-100,r=100;
    while(r-l > 1e-8)//如果他足够小就退出循环,10的-8次方
    {
        double mid=(l+r)/2;
        if(mid*mid*mid>=n) r=mid;//如果是他的立方大于这个数n,就证明这个位置的数大了,应该在这个数左边,就让r=mid
        else l=mid;//否则在右边,让l=mid
    }
    printf("%lf",l);
    return 0;
}

 

总结

这是博主算法入门的第一课,关于三种基础排序算法的学习,快速排序和归并排序时间复杂度较低,使用起来更快捷,二分查找也对很多题目适用,可以提高我们的编码效率。以上代码和题目均来源于acwing,是博主学习过程中的小笔记,如有侵权,立刻删除。

你可能感兴趣的:(基础算法,算法,数据结构,排序算法,c语言)