18、插入排序,快速排序

来源:互联网 发布:淘宝 比较好的手机店 编辑:程序博客网 时间:2024/05/22 05:14

1、插入排序:每次从无序数据集中取出一个元素,扫描已排好的数据集,把这个元素插入有序集的合适位置。
特点:简单,但不适合处理大型数据集,不需要额外空间,最坏O(n2),在增量排序中非常高效。
这里写图片描述

int issort(void *data, int size, int esize, int (*compare)(const void *key1, const void *key2)){    int i, j;    void *key;    char *a = data;    if((key = (char *)malloc(esize)) == NULL)        return -1;    for(j = 1; j < size; j++)    {        //key暂存当前需要移动的数据         memcpy(key, a[i * esize], esize);        i = j - 1;        //如果key小,向左和下一个比较         while((i >= 0) && (compare(&a[i * esize], key) > 0))        {            memcpy(&a[(i + 1) * esize], &a[i * esize], esize);            i--;        }        //把该数插入比左边较小数的右边         memcpy(&a[(i + 1) * esize], key, esize);    }    free(key);    return 0;}

2、快速排序:一种分治排序算法。
分:将未排序的支票分为两堆,其中一堆小于等于某个数,另一堆大于某个数。
治:重复划分,递归快速排序直到每堆只有一个。
合:对分割部分排序直至完成。
特点:适合大数据,不需要额外空间,最坏O(n2),平均O(nlgn)。如果分割值选的不好,性能会很差。一个有效方法为随机选择法。还可以改进随机选择法:随机选取3个数,取3个元素的中间值。
这里写图片描述

//i, k 初始值为 0 和 size - 1, 返回分好的边界点位置 //partition完成分割值的选取,把一堆分成以分割值为边界的两堆。 static int partition(void *data, int size, int esize, int i, int k, int (*compare)(const void *key1, const void *key2)){    char *a = data;    void *pval, *temp;//pval存放边界值,temp交换中介     int r[3];    if((pval = malloc(esize)) == NULL)        return -1;    if((temp = malloc(esize)) == NULL)    {        free(pval);        return -1;    }    r[0] = (rand() % (k - i + i)) + i;    r[1] = (rand() % (k - i + i)) + i;    r[2] = (rand() % (k - i + i)) + i;    issort(r, 3, sizeof(int), compare);    memcpy(pval, &a[r[1] * size], esize);    i--;    k--;    while(1)    {        do        {            k--;        }while(compare(&a[k * esize], pval) > 0);        do        {            i++;        }while(compare(&a[i * esize], pval) < 0);        //找完         if(i >= k)        {            break;        }        //大于边界值的放右边,小于边界值的放左边         else        {            memcpy(temp, &a[i * esize], esize);            memcpy(&a[i * esize], &a[k * esize], esize);            memcpy(&a[k * esize], temp, esize);        }    }    free(pval);    free(temp);    return k; } //划分即排序 int  qksort(void *data, int size, int esize, int i, int k, int (*compare)(const void *key1, const void *key2)){    int j;    while(i < k)    {        if((j = partition(data, esize, i, k, compare)) < 0)            return -1;        if(qksort(data, size, esize, i, j,compare))            return -1;        i = j + 1;    }    return 0;}

3、快速排序的例子-目录列表

int directls(const char *path, Directory **dir){    DIR *dirptr;    Directory *temp;    struct dirent *curdir;    int count, i;    //先打开路径     if((dirptr = opendir(path)) == NULL)        return -1;    *dir = NULL;    count = 0;    //先把每个文件的名字读到字符串数组dir中     while((curdir = readdir(dirptr)) != NULL)    {        count++;        if((temp = (Directory *)realloc(*dir, count * sizeof(Directory))) == NULL)        {            free(*dir);            return -1;        }        else        {            *dir = temp;        }        strcpy( ((*dir)[count - 1]).name, curdir->d_name );    }     closedir(dirptr);    if(qksort(*dir, count, sizeof(Directory), 0, count - 1, compare_dir) != 0)        return -1;    return count;}
原创粉丝点击