快速排序(分而治之策略及C语言实现)

本文探讨了快速排序算法,重点介绍了分而治之的策略,并详细解析了如何在C语言中实现这一算法。文章涵盖了如何处理未知大小的数组、传递数组、返回数组以及连接两个整型数组的方法,最终提供了完整的快速排序实现。

提出的问题

分而治之的策略

重要的分而治之算法

快速排序

问题

要在一个长为x,宽为y的长方形中画出均匀且大小相等的正方形
    那么正方形的边长为多少
(1)可以看出正方形的边长需要是x和y的最大公约数
    如何求最大公约数?
        找查约数法:
            分别找出两个数的所有约数,再找出两个数的所有公约数,最大的那个就是最大公约数(最好别用,太烦人,容易出错)
        更相减损法:
            任意两个数,判定是否为偶数,是就用2约简,不是就用较大的数减较小的数,所得的差和较小的数比较,再用大的减小的,直到所得的减数和差相等,再用约掉的每个2相乘(如果约掉3个2,就是2^3)z再与所得的相等的数的乘积就是最大公约数【内部原理需要再想想。。。】
        辗转相除法:
            以小的数除大数,所得的是整数,那这个数就是最大公约数,不然就用余数来除刚才的除数,直到得到整数,这时作为除数的就是最大公约数【思想:处理余数】
            算法实现(递归和循环):
                #include <bits/stdc++.h>
                using namespace std;
                int Division(int a,int b)
                {
                    if(b == 0)
                    {
                        return a;
                    }
                    else
                    {
                        return Division(b,a%b);
                    }
                }
                int Division_while(int c,int d)
                {
                    while(d!=0)
                    {
                        int r = d;
                        d = c%d;
                        c = r;
                    }
                    return c;
                }

                int main()
                {
                    int ac ,bc;
                    scanf("%d %d",&ac,&bc);
                    if(ac >bc)
                    {
                         cout<<"Division:\n"<<Division(ac,bc)<<endl;
                         cout<<"Division_while\n"<<Division_while(ac,bc)<<endl;
                    }
                    else
                    {
                        cout<<"Division:\n"<<Division(bc,ac)<<endl;
                        cout<<"Division_while\n"<<Division_while(bc,ac)<<endl;
                    }
                    return 0;


                }

(2)如果长不是宽的整数倍,那么假如x = 2*y +m;那么可以画两个边长为y的正方形,还剩下一部分面积,然后再看看可以在剩下的这片区域中画几个最大的正方形(边长等于宽),不断缩小剩余的面积,直到没有剩余为止。【其实类似上面的辗转相除法,都是出来余下的部分,而且在不断缩小问题的规模】
    不过问题是,为什么剩余部分的最大正方形就是整个长方形区域的最大正方形呢?
        课本上说欧几里得算法已经证明完了
        那就看看欧几里得算法
            欧几里得算法好像就是辗转相除法(lll¬ω¬),这个算法的实现好像不算是问题(lll¬ω¬)

分而治之的原理

由上面的可以看出,分而治之其实是缩小问题规模再解决

快速排序的实现

先分而治之再归纳证明
    分而治之是指如果有一个大规模的数组需要排序,那么可以分成多个小数组排序再组合成大数组,而归纳证明是指我们可以将只有两个元素的数组通过比较进行排序,也可以使用比较对有三个元素的数组进行排序,那么以此类推,我们可以对一个大规模的数组进行排序,通过分而治之可以转变为对两个或三个元素的

问题

如何创建未知大小的数组?

        在C中如果创建数组而没有指定大小会报错
            int e[];
            ||=== Build file: "no target" in "no project" (compiler: unknown) ===|
            E:\C_code\kuaisupaixu.cpp|11|error: storage size of 'e' isn't known|
        要实现元素动态添加有什么方法?
            使用STL,vector
                这个效率怎么样,消耗资源多么
            使用链表
                如果需要数组的话,可以再转为数组
                使用链表的话,可以很容易的将多个片段连接起来,但是使用连接时需要找到这一段链表的最后一个元素将他的指针指向要连接的元素,仅仅找片段中的最后一个元素就会消耗不少时间及资源
                而且这种排序操作几乎打乱了所有指针的指向可能会出现问题,导致指针指向错误
                如果是大规模的数组使用快速排序,由于链表的创建,销毁,指针的重新分配以及链表不可随机访问只能一个个访问的原因,也可能会抵消掉快速排序的效率
            还是使用数组
                (1)    一开始使用malloc,如果元素增加使用realloc,这个方法使用的是堆内存,而堆内存一般受限于虚拟内存,所以一般堆内存比较大,有比较多的空间,这种方法可以实现认为上的动态增加,的确通过再申请空间让人以为空间在增加,好像有更多的空间可以用,实际上也是,
                    不过问题一是在递归时,保存的映像中使用此操作是所有映像改变还是只影响当前状态
                    而且如果会有很多元素需要添加那么需要很多次realloc那么会不会消耗很多的资源,让数组在内存中移来移去
                (2)   直接创建一个足够大的数组,使用一个位置指针用来代表这个数组用了多少空间,这样不用使用新的方法,还是使用数组,虽然使用了几个大数组,但是不需要再对数组进行什么改变,只需要在数组的不同位置变换元素数值即可

如何在C语言中实现传递数组?

                    方法有两种:值传递和地址传递(额 一看就差不多了)
                    值传递
                        说明和定义函数时,要在数组参数的尾部加上一对方括号([]),调用函数时只需将数组的地址(即数组名)传递给函数
                        在值传递方式中,数组将被复制一份,复制所得的数组将被存放在栈中
                        值传递方式的开销是非常大的,
                            因为首先复制原来数组就会占用额外的内存,
                            还会有代码去执行复制的操作,
                            这种操作又会需要比较多的时间,
                            资源,额外指令,时间都会有消耗,所以效率会比较低
                    地址传递
                        地址传递只需要传递个地址就行了,也就是个指针,
                    #在C/C++不能直接返回一个数组。这是由于在C/C++中,数组不是一种类型,因此不能被直接返回。
                    #定义了一个数组名之后,他就是常量了,不能再给数组赋值
                    Python实现
                        def quicksort(array):
                            if len(array) < 2:
                                return array
                        else:
                            pivot = array[0]
                            less = [i for i in array[1:] if i <= pivot]
                            greater = [i for i in array[1:] if i > pivot]
                            return quicksort(less) + [pivot] + quicksort(greater)
                    C/C++实现(有问题,再改)
                        #include <bits/stdc++.h>
                        using namespace std;
                        int* QuicklySort(int* a,int size_n)
                        {
                            if(size_n<2)
                            {
                                return a;
                            }
                            else{
                                int b = a[0];
                                int e[70];
                                int small[70],big[70];
                                int k=0;
                                int s_num=0,b_num=0;
                                for(int j =0;j<size_n;j++)
                                {
                                    if(a[j]<b)
                                    {
                                        small[s_num] = a[j];
                                        s_num++;
                                    }
                                    if(a[j]>=b)
                                    {
                                        big[b_num] = a[j];
                                        b_num++;
                                    }
                                }
                                int *s_1;
                                s_1= QuicklySort(small,s_num);
                                int *b_1;
                                b_1 = QuicklySort(big,b_num);

                                for( k;k<s_num;k++)
                                {
                                    e[k] = s_1[k];
                                }
                                e[k] = a[0];
                                k++;
                                int temp = 0;
                                for(k;k<size_n;k++)
                                {
                                    if(temp<=b_num)
                                    {
                                        e[k] = b_1[temp++];
                                    }
                                }
                                return e;
                            }


                        }
                        int main()
                        {
                            int a[70];
                            int ll = 0;
                            for(int i=99;i>30;i--)
                            {
                                a[ll] = i;
                                ll++;
                            }
                            QuicklySort(a,70);
                            cout<<"finished"<<endl;
                            return 0;
                        }
                    数组传递问题
                        如果在函数A将数组x作为参数传递给函数B
                        地址传递 int *b
                        值传递   int b[]
                        #include <bits/stdc++.h>
                        using namespace std;
                        int ss(int b[])
                        {
                            //printf("%d\n",*b);
                            cout<<"(sizeof(b)/sizeof(b[0]))"<<(sizeof(b)/sizeof(b[0]))<<endl;
                            for(int j=0;j<(sizeof(b)/sizeof(b[0]));j++)
                            {
                                cout<<b[j]<<endl;
                            }
                        }
                        int main()
                        {
                            int a[9];
                            int num =0;
                            for(int i =11;i<20;i++)
                            {
                                a[num++] = i;
                            }
                            for(int l=0;l<num;l++)
                            {
                                cout<<"a[]"<<a[l]<<endl;
                            }
                            ss(a);
                            return 0;
                        }
                        如果使用 for(int j=0;j<(sizeof(b)/sizeof(b[0]));j++),那么计算出的是j<1,所以显示出的是数组的第一个元素,【数组名传递进函数作为参数会退化为指针,使用sizeof是得不到数组的长度的】
                        如果使用for(int j=0;j<9;j++),那么就可以显示出所有值了

如何实现return 一个数组?

                    C编程语言不允许返回整个数组作为函数的参数。但是可以返回一个指针
                        #include <bits/stdc++.h>
                        using namespace std;
                        int* ss(int *b,int size_n)
                        {
                            //printf("%d\n",*b);
                            cout<<"(sizeof(b)/sizeof(b[0]))"<<(sizeof(b)/sizeof(b[0]))<<endl;
                            for(int j=0;j<size_n;j++)
                            {
                                b[j]=b[j]+100;
                                cout<<b[j]<<endl;
                            }
                            return b;

                        }
                        int main()
                        {
                            int a[9];
                            int num =0;
                            for(int i =11;i<20;i++)
                            {
                                a[num++] = i;
                            }
                            for(int l=0;l<num;l++)
                            {
                                cout<<"a[]"<<a[l]<<endl;
                            }
                            int *y;
                            y = ss(a,9);
                            cout<<"y:"<<y[6]<<endl;
                            return 0;
                        }
                        将这个方法用在递归中【这是一个没有结束条件的递归程序,会一直运行下去】
                            #include <bits/stdc++.h>
                            using namespace std;
                            int* ss(int *b,int size_n)
                            {
                                //printf("%d\n",*b);
                                //cout<<"(sizeof(b)/sizeof(b[0]))"<<(sizeof(b)/sizeof(b[0]))<<endl;
                                for(int j=0;j<size_n;j++)
                                {
                                    b[j]=b[j]+100;
                                    cout<<b[j]<<endl;
                                }
                                return ss(b,size_n);

                            }
                            int main()
                            {
                                int a[9];
                                int num =0;
                                for(int i =11;i<20;i++)
                                {
                                    a[num++] = i;
                                }
                                for(int l=0;l<num;l++)
                                {
                                    cout<<"a[]"<<a[l]<<endl;
                                }
                                int *y;
                                y = ss(a,9);
                                cout<<"y:"<<y[6]<<endl;
                                return 0;
                            }
                        如果return的数组比较大的话,在函数B中返回由main函数接收的话,只剩数组首地址处(即第一个元素)可以访问了,其他位置的元素都变了,这可能是因为main函数调用函数B完成后,函数B中的连接好的数组被销毁,虽然一个数组的首地址被传到了main函数,但是也只有一个元素了,所以要保证调用完函数B后还得让数组存在,可以尝试结构体或者全局变量
                            下面是使用全局变量后的情况,完全可以在main函数中访问已经处理过的数组,不过有个限制,就是全局变量声明时,声明的数组范围需要比较大,
                                #include <bits/stdc++.h>
                                #include <stdlib.h>
                                using namespace std;
                                int z[100];
                                int* ss(int *b,int size_n)
                                {
                                    int num = 0;
                                    int num_2=0;
                                    //printf("%d\n",*b);
                                    //cout<<"(sizeof(b)/sizeof(b[0]))"<<(sizeof(b)/sizeof(b[0]))<<endl;
                                    for(int j=0; j<size_n; j++)
                                    {
                                        b[j]=b[j]+100;
                                        cout<<b[j]<<endl;
                                    }
                                    int a[size_n];
                                    int x[size_n];
                                    for(int k =0; k<size_n; k++)
                                    {
                                        if(b[k]%2==0)
                                        {
                                            a[num]=b[k];
                                            num++;
                                        }
                                    }
                                    cout<<"num:"<<num<<endl;
                                    for(int nn=0; nn<num; nn++)
                                    {

                                        cout<<"a[num]:"<<a[nn]<<endl;
                                    }
                                    for(int k =0; k<size_n; k++)
                                    {
                                        if(b[k]%5==0)
                                        {
                                            x[num_2]=b[k];
                                            num_2++;
                                        }
                                    }
                                    cout<<"num_2:"<<num_2<<endl;
                                    for(int nn=0; nn<num_2; nn++)
                                    {

                                        cout<<"x[num_2]:"<<x[nn]<<endl;
                                    }

                                    int f = num+num_2;


                                    ///连接两个数组
                                    for(int d =0;d<f;d++)
                                    {
                                        if(d<num)
                                        {
                                            z[d]=a[d];
                                        }
                                        if(d>=num)
                                        {
                                            z[d] = x[d-num];
                                        }
                                    }
                                    for(int nn=0; nn<f; nn++)
                                    {

                                        cout<<"z[nn]:"<<z[nn]<<endl;
                                    }
                                    return z;
                                }
                                int main()
                                {
                                    int a[9];
                                    int num =0;
                                    for(int i =11; i<20; i++)
                                    {
                                        a[num++] = i;
                                    }
                                    for(int l=0; l<num; l++)
                                    {
                                        cout<<"a[]"<<a[l]<<endl;
                                    }
                                    int *y;
                                    y = ss(a,9);
                                    cout<<"y0:"<<y[0]<<endl;
                                    cout<<"y1:"<<y[1]<<endl;
                                    cout<<"y2:"<<y[2]<<endl;
                                    cout<<"y3:"<<y[3]<<endl;
                                    cout<<"y4:"<<y[4]<<endl;
                                    int yy =0;
                                    for(int g =0;g<9;g++)
                                    {
                                        if(y[g])
                                        {
                                                    cout<<"y:"<<y[g]<<endl;
                                        }

                                    }

                                    return 0;
                                }

如何实现连接两个数组(int类型数组)

                        方法一:据说linux kernel中有一个flex_array的实现
                        方法二:新建一个数组,将需要连接的数组内元素的值放到新数组中
                            #include <bits/stdc++.h>
                            #include <stdlib.h>
                            using namespace std;
                            int* ss(int *b,int size_n)
                            {
                                int num = 0;
                                int num_2=0;
                                //printf("%d\n",*b);
                                //cout<<"(sizeof(b)/sizeof(b[0]))"<<(sizeof(b)/sizeof(b[0]))<<endl;
                                for(int j=0; j<size_n; j++)
                                {
                                    b[j]=b[j]+100;
                                    cout<<b[j]<<endl;
                                }
                                int a[size_n];
                                int x[size_n];
                                for(int k =0; k<size_n; k++)
                                {
                                    if(b[k]%2==0)
                                    {
                                        a[num]=b[k];
                                        num++;
                                    }
                                }
                                cout<<"num:"<<num<<endl;
                                for(int nn=0; nn<num; nn++)
                                {

                                    cout<<"a[num]:"<<a[nn]<<endl;
                                }
                                for(int k =0; k<size_n; k++)
                                {
                                    if(b[k]%5==0)
                                    {
                                        x[num_2]=b[k];
                                        num_2++;
                                    }
                                }
                                cout<<"num_2:"<<num_2<<endl;
                                for(int nn=0; nn<num_2; nn++)
                                {

                                    cout<<"x[num_2]:"<<x[nn]<<endl;
                                }

                                int f = num+num_2;
                                int z[f];

                                ///连接两个数组
                                for(int d =0;d<f;d++)
                                {
                                    if(d<num)
                                    {
                                        z[d]=a[d];
                                    }
                                    if(d>=num)
                                    {
                                        z[d] = x[d-num];
                                    }
                                }
                                for(int nn=0; nn<f; nn++)
                                {

                                    cout<<"z[nn]:"<<z[nn]<<endl;
                                }
                                return z;
                            }
                            int main()
                            {
                                int a[9];
                                int num =0;
                                for(int i =11; i<20; i++)
                                {
                                    a[num++] = i;
                                }
                                for(int l=0; l<num; l++)
                                {
                                    cout<<"a[]"<<a[l]<<endl;
                                }
                                int *y;
                                y = ss(a,9);
                                int yy =0;
                                while(*y)
                                {
                                    cout<<"y:"<<y[yy++]<<endl;
                                    y+=sizeof(int);

                                }

                                return 0;
                            }

快速排序最终实现

                            数组比较多的话,递归也比较慢
                            #include <bits/stdc++.h>
                            using namespace std;
                            int z[100];
                            int a[70];
                            int* QuicklySort(int* a,int size_n)
                            {
                                if(size_n<2)
                                {
                                    return a;
                                }
                                else
                                {
                                    int b = a[0];
                                    int small[70],big[70];
                                    int s_num=0,b_num=0;
                                    for(int j =0; j<size_n; j++)
                                    {
                                        if(a[j]<b)
                                        {
                                            small[s_num] = a[j];
                                            s_num++;
                                        }
                                        if(a[j]>=b)
                                        {
                                            big[b_num] = a[j];
                                            b_num++;
                                        }
                                    }
                                    int *s_1;
                                    s_1= QuicklySort(small,s_num);
                                    int *b_1;
                                    b_1 = QuicklySort(big,b_num);

                                    for(int d =0; d<size_n; d++)
                                    {
                                        if(d<s_num)
                                        {
                                            z[d]=s_1[d];
                                        }
                                        if(d==s_num)
                                        {
                                            z[d] = b;
                                        }
                                        if(d>s_num)
                                        {
                                            z[d]= b_1[d-1-s_num];
                                        }
                                    }
                                       return z;


                                }



                            }
                            int main()
                            {
                                //int a[70];
                                int ll = 0;
                                for(int i=99; i>30; i--)
                                {
                                    a[ll] = i;
                                    ll++;
                                }
                                int *u;

                                u = QuicklySort(a,70);
                                for(int yy =0;yy<70;yy++)
                                {
                                    cout<<"z[]"<<u[yy]<<endl;
                                }
                                cout<<"finished"<<endl;
                                return 0;
                            }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值