我的算法笔记(5)分治(1)

排序

这里先介绍俩种排序方法----归并排序和快速排序

1.归并排序

引例 归并排序的图片描述

图片来源:菜鸟教程
菜鸟教程的归并排序演示

引例 对十个数的归并排序

// merge sort
#include<stdio.h>




int a[10]={5,3,13,25,84,64,70,20,90,100};
int b[10];//一个临时数组
int min(int x,int y)
{//先写一个min函数用来比较数字的大小
    return x<y?x:y;
}
void Merge(int a[],int s,int m,int e,int b[])
{   int i=0;
    int x=0;//负责指向b
    int x1=s,x2=m+1;//分别负责指向需要归并的俩个数组
    while (x1<=m && x2<=e){
        if (a[x1] < a[x2])//开始比较待归并的俩格数组,比较元素的大小,小的就放在前面
            b[x++]=a[x1++];
        else
            b[x++]=a[x2++];
    }
    //只要有一个数组的数全部都排完了,那么我就可以吧另一个数组剩下的全部数就都放在临时数组里了
    while (x1 <=m)
        b[x++] = a[x1++];
    while (x2<=e)
        b[x++] = a[x2++];
    for (i=0;i<e-s+1;i++)  //这里e-s+1是因为e是从len-1开始的,所以+1
        a[s+i] = b[i];//把b中已经排好的数组重新赋值给a
}
void MergeSort(int a[],int s,int e,int b[])//一个参数是要排序的数组,另一个是数组的开始,结尾,b临时存放
{
    if(s<e){
        int m = s + (e-s)/2; //找到中间的位置
        MergeSort(a,s,m,b);//对前一半排序

        MergeSort(a,m+1,e,b);//对后一半排序

        Merge(a,s,m,e,b);//进行并的操作
    }
}

//写一个演义的函数
void Display(int a[],int s,int e){
    int i;
    for (i=s;i<e+1;i++)
        printf("%d,",a[i]);
    printf("\n");
    return ;

}


int main()
{   int i;
    int len = sizeof(a)/sizeof(int);//得到a的长度
    Display(a,0,len-1);
    MergeSort(a,0,len-1,b);//进行排序操作
    Display(a,0,len-1);
}

结果如图所示:
程序结果演示
从代码中我们可以看出,我们使用了递归的思想完成了归并排序的操作,其中比较重要的俩格步骤,就是“分(Mergesort)”和“和(Merge)”俩个函数
在Mergesort函数中:

void MergeSort(int a[],int s,int e,int b[])//一个参数是要排序的数组,另一个是数组的开始,结尾,b临时存放
{
    if(s<e){
        int m = s + (e-s)/2; //找到中间的位置
        MergeSort(a,s,m,b);

        MergeSort(a,m+1,e,b);//对后一半排序

        Merge(a,s,m,e,b);//进行并的操作
    }
}

主要是进行了分半的操作,通过二分的过程,把一个大的数组变成一个个小的局部的数组,然后再通过Merge函数,分别对每一小片的数组再次整理组合在了一起.

void Merge(int a[],int s,int m,int e,int b[])
{   int i=0;
    int x=0;//负责指向b
    int x1=s,x2=m+1;//分别负责指向需要归并的俩个数组
    while (x1<=m && x2<=e){
        if (a[x1] < a[x2])//开始比较待归并的俩格数组,比较元素的大小,小的就放在前面
            b[x++]=a[x1++];
        else
            b[x++]=a[x2++];
    }
    //只要有一个数组的数全部都排完了,那么我就可以吧另一个数组剩下的全部数就都放在临时数组里了
    while (x1 <=m)
        b[x++] = a[x1++];
    while (x2<=e)
        b[x++] = a[x2++];
    for (i=0;i<e-s+1;i++)  //这里e-s+1是因为e是从len-1开始的,所以+1
        a[s+i] = b[i];//把b中已经排好的数组重新赋值给a
}

快速排序

图片描述

快速排序的图片
此处图片出处:五分钟学算法

引例:对十个数字进行排序

//QuickSort

#include<stdio.h>
#define BUF_SIZE 10

void display(int array[],int maxlen)
{
    int i;
    for (i=0;i<maxlen;i++)
    {
        printf("%d,",array[i]);

    }
    printf("\n");
}
void swap(int *a,int *b)
{
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}
// the implementation of quicksort

void quicksort(int array[],int begin,int end)
{
    int i,j;
    int k = array[begin];
    if (begin >= end )
        return;
        i = begin;  // 把array[begin]作为基准数,因此array[begin+1]开始与基准数吧比较
        j = end;
    while (i!=j)
    {   while (j>i && array[j] >=k) // 保证k右边的数都比K 大
        --j;    //这个循环的意思就是说,如果满足这个条件,那么我的指针就向下一个元素指去;
        swap(&array[i],&array[j]);//自然,不满足循环的条件的话,就会互换位置。
        while (j >i && array[i]<=k) //保证k左边的数,都比K 小
        ++i;
        swap(&array[i],&array[j]);

    }//此时就已经处理完成了数组,
    //进行k左右俩边数组的分别排序
    quicksort(array,begin,i-1);
    quicksort(array,i+1,end);
}

main()
{
    int n;
    int array[BUF_SIZE] = {12,85,25,16,34,23,49,95,17,61};
    int maxlen = BUF_SIZE;
    printf("排序前的数组:\n");
    display(array,maxlen);

    quicksort(array,0,maxlen-1); // 快速排序
    printf("排序后的数组:\n");
    display(array,maxlen);
}

结果如图所示:
在这里插入图片描述
在给出的快排代码中,我是让a[0]先作为k,然后开始比较。
代码解读:

void quicksort(int array[],int begin,int end)
{
    int i,j;
    int k = array[begin];
    if (begin >= end )
        return;
        i = begin;  // 把array[begin]作为基准数,因此array[begin+1]开始与基准数吧比较
        j = end;
    while (i!=j)
    {   while (j>i && array[j] >=k) // 保证k右边的数都比K 大
        --j;    //这个循环的意思就是说,如果满足这个条件,那么我的指针就向下一个元素指去;
        swap(&array[i],&array[j]);//自然,不满足循环的条件的话,就会互换位置。
        while (j >i && array[i]<=k) //保证k左边的数,都比K 小
        ++i;
        swap(&array[i],&array[j]);

    }//此时就已经处理完成了数组,
    //进行k左右俩边数组的分别排序
    quicksort(array,begin,i-1);
    quicksort(array,i+1,end);
}

在快排实现的代码中,我们可以看到,我设置了俩个变量i,j然后通过与k的比较,不断地进行交换位置还有指针向中间的移动,到最后使得i,j指向中间的位置,然后,再次递归调用quicksort函数,分别对中间左右的数组元素再次进行排序。
上一篇:我的算法笔记(4)二分查找1
下一篇:我的算法笔记(6)动态规划1

猜你喜欢

转载自blog.csdn.net/qq_33950926/article/details/89890584