排序算法的C语言实现(上 比较类排序:插入排序(2)

/*issort 插入排序*/
int issort(void *data, int size, int esize, int (*compare)(const void *key1, const void *key2))
{
    char *a = data;
    void *key;
    int  i,j;

/*为key元素分配一块空间*/
    if((key =(char *)malloc(esize)) == NULL)
        return -1;

/*将元素循环插入到已排序的数据集中*/
    for(j=1; j < size; j++)
    {
        /*取无序数据集中的第j个元素,复制到key中*/
        memcpy(key, &a[j*esize], esize);
        /*设i为j紧邻的前一个元素*/
        i = j - 1;

/*从i开始循环查找可以插入key的正确位置*/
        /*key和第i个元素对比,如果小于第i个元素就复制i元素到i+1的位置;i递减循环对比*/
        while(i >= 0 && compare(&a[i*esize],key)>0)
        {
            memcpy(&a[(i+1)*esize],&a[i*esize],esize);
            i--;
        }
        /*将key元素的值(也就是要插入的值)复制到while循环后i+1的位置,也就是要插入的位置*/
        memcpy(&a[(i+1)*esize],key,esize);
    }
    /*释放key的空间*/
    free(key);

return 0;
}

二、快速排序

快速排序是一种分治算法

广泛地认为它是解决一般问题的最佳算法。同插入排序一样,快速排序也属于比较排序的一种,而且不需要额外的存储空间在处理中到大型数据集时,快速排序是一个比较好的选择

我们来看一个人工对一堆作废的支票进行排序的例子,可以将未排序的支票分为两堆。其中一堆专门用来放小于或等于某个编号的支票,而另一堆用来放大于这个编号的支票(假设这个支票大概是所有支票编号的中间值)。当以这种方式得到两堆支票后,又可以以同样的方式将它们分为四堆,不断的重复这个过程直到每个堆中只放有一张支票。这时,所有的支票就已经排好序了。

由于快速排序属于分治算法的一种,我们用分治的思想将排序分为三个步骤

1、分:设定一个分割值,将数据分为两部分;

2、治:分别在两个部分用递归的方式继续使用快速排序法;

3、合:对分割部分排序直至完成。

快速排序最坏情况下的性能不会比插入排序的最坏情况好。通过一点点修改可以大大改善快速排序最怀情况的效率,使其表现得与其平均情况相当。如何做到这一点,关键在于如何选择分割值。

所选的分割值需要尽可能的将元素平均分开。如果分割值会将大部分的元素放到其中一堆中,那么此时快速排序的性能会非常差。例如:如果用10作为数据值{15,20,18,51,36,10,77,43}的分割值,其结果为{10}和{15,20,18,51,36,77,43},明显不平衡。如果将分割值选为36,其结果为{36,51,77,43}和{15,20,18,10},就比较平衡。

选择分割值的一种有效的方法是通过 随机选择法 来选取。随机选择法能够有效的防止被分割的数据极度不平衡。同时,还可以改进这种随机选择法,方法是:首先随机选择三个元素,然后选择三个元素中的中间值。这就是所谓的中位数方法,可以保证平均情况下的性能。由于这种分割方法依赖随机数的统计特性,从而保证快速排序的整体性能,因此快速排序也是随机算法的一个好例子。

快速排序的接口定义 qksort

int qksort(void *data, int size, int esize, int i, int k, int (*compare)(const void *key1, const void *key2);

返回值:如果排序成功,返回0;否则返回-1。

描述:  利用快速排序将数组data中的元素进行排序。数组中的元素个数由size决定。而每个元素的大小由esize决定。参数i和k定义当前进行排序的两个部分,其值分别初始为0和size-1。函数指针compare会指向���个用户定义的函数来比较元素大小,其函数功能与issort中描述的一样。当qksort返回时,data包含已经排好序的元素。

复杂度: O(n lg n),n为要被排序的元素的个数。

快速排序的实现与分析

快速排序本质上就是不断地将无序元素集递归分割,直到所有的分区都只包含单个元素

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/4c44cb3108d7558c7fdff59fb643a7ba.html