算法(二):快速排序

(1)选择中值,根据坐标,三者取其中

(2)分别与中值比较,将数据分成两部分

(3)两部分中分别再使用同样的方法,分成更小的两部分,直到不可再分

(4)qksort中的递归,可以保证a[0]~a[j]完全排序,所以i = j+1;

代码:

[email protected]:/mnt/shared/appbox/qksort# cat qksort.c
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

static int compare_int(const void *int1, const void *int2)
{
        if(*(const int *)int1 == *(const int *)int2)
                return 0;

        return *(const int *)int1 > *(const int *)int2 ? 1 : -1;
}
static int get_mid_value(int *data)
{
        if(compare_int(&data[0], &data[1])>0)//d[0]>d[1]
        {
                if(compare_int(&data[0], &data[2]) > 0)
                        return compare_int(&data[1], &data[2]) > 0 ? data[1] : data[2];
                else
                        return data[0];
        }
        else // d[0] < d[1]
        {
                if(compare_int(&data[0], &data[2]) > 0)//d[0] > d[2]
                        return data[0]; // d[2]<d[0]<d[1], return d[0]
                else//d[0] < d[2]
                        return compare_int(&data[1] ,&data[2]) > 0? data[2]:data[1];
        }

        return -1;
}

static int partition(int *a, int esize, int i, int k, int (*compare)(const void *key1, const void *key2))
{
        int m;
        int mid, middle;
        int r[3];
        int temp;

        r[0] = (rand()%(k-i+1) + i);
        r[1] = (rand()%(k-i+1) + i);
        r[2] = (rand()%(k-i+1) + i);

        mid = get_mid_value(r);
        middle = a[mid];
        printf("r[0]:%d, r[1]:%d, r[2]:%d, mid:%d,middle:%d\n", r[0],r[1],r[2],mid, middle);

        i--;
        k++;

        while(1)
        {
                do
                {
                        k--;
                }while(compare(&a[k], &middle) > 0);

                do
                {
                        i++;
                }while(compare(&a[i], &middle) < 0);

                if(i>=k)
                        break;
                else
                {
                        temp = a[i];
                        a[i] = a[k];
                        a[k] = 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;
        int m;

        while(i < k)
        {
                if((j = partition(data, esize, i, k, compare)) < 0)
                        return -1;

                if(qksort(data, size, esize, i, j, compare) < 0)
                        return -1;

                i = j + 1;
        }
        return 0;
}

int main(int argc, char *argv[])
{
        int ret;
        int i, j, k;
        i = 11;
        j = 12;
        int array[10]= {1,4,7,2,5,8,3,6,9,10};

        printf("\n******************compare_init test**********************\n");
        printf("compare_int(&i, &j)=%d\n", compare_int(&i, &j));
        printf("compare_int(&j, &i)=%d\n", compare_int(&j, &i));
        printf("compare_int(&i, &i)=%d\n", compare_int(&i, &i));
        printf("\n******************partition    test**********************\n");

        qksort(array, 10, 4, 0, 9, compare_int);

        for(i=0; i<10; i++)
                printf("%d ", array[i]);
        printf("\n");

        return 0;
}

执行结果:

[email protected]:/mnt/shared/appbox/qksort# ./qksort

******************compare_init test**********************

compare_int(&i, &j)=-1

compare_int(&j, &i)=1

compare_int(&i, &i)=0

******************partition    test**********************

r[0]:3, r[1]:6, r[2]:7, mid:6,middle:3

r[0]:1, r[1]:2, r[2]:1, mid:1,middle:3

r[0]:0, r[1]:0, r[2]:1, mid:0,middle:1

r[0]:6, r[1]:5, r[2]:8, mid:6,middle:4

r[0]:6, r[1]:5, r[2]:9, mid:6,middle:7

r[0]:5, r[1]:4, r[2]:4, mid:4,middle:5

r[0]:5, r[1]:5, r[2]:6, mid:5,middle:6

r[0]:9, r[1]:7, r[2]:7, mid:7,middle:8

r[0]:8, r[1]:8, r[2]:8, mid:8,middle:9

1 2 3 4 5 6 7 8 9 10

[email protected]:/mnt/shared/appbox/qksort#

增加对流程的打印:

[email protected]:/mnt/shared/appbox/qksort# cat qksort.c
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>

static int compare_int(const void *int1, const void *int2)
{
        if(*(const int *)int1 == *(const int *)int2)
                return 0;

        return *(const int *)int1 > *(const int *)int2 ? 1 : -1;
}
static int get_mid_value(int *data)
{
        if(compare_int(&data[0], &data[1])>0)//d[0]>d[1]
        {
                if(compare_int(&data[0], &data[2]) > 0)
                        return compare_int(&data[1], &data[2]) > 0 ? data[1] : data[2];
                else
                        return data[0];
        }
        else // d[0] < d[1]
        {
                if(compare_int(&data[0], &data[2]) > 0)//d[0] > d[2]
                        return data[0]; // d[2]<d[0]<d[1], return d[0]
                else//d[0] < d[2]
                        return compare_int(&data[1] ,&data[2]) > 0? data[2]:data[1];
        }

        return -1;
}

static int partition(int *a, int esize, int i, int k, int (*compare)(const void *key1, const void *key2))
{
        int m;
        int mid, middle;
        int r[3];
        int temp;

        r[0] = (rand()%(k-i+1) + i);
        r[1] = (rand()%(k-i+1) + i);
        r[2] = (rand()%(k-i+1) + i);

        mid = get_mid_value(r);
        middle = a[mid];
        printf("r[0]:%d, r[1]:%d, r[2]:%d, mid:%d,middle:%d\n", r[0],r[1],r[2],mid, middle);

        i--;
        k++;

        while(1)
        {
                do
                {
                        k--;
                }while(compare(&a[k], &middle) > 0);

                do
                {
                        i++;
                }while(compare(&a[i], &middle) < 0);

                if(i>=k)
                        break;
                else
                {
                        temp = a[i];
                        a[i] = a[k];
                        a[k] = 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;
        int m;

        while(i < k)
        {
                printf("\n--------------------------------------------------\n");
                printf("i=%d, k=%d\n", i, k);

                for(m=0; m<10; m++)
                        printf("%d ", ((int *)data)[m]);
                printf("\n");

                if((j = partition(data, esize, i, k, compare)) < 0)
                        return -1;

                printf("j=%d, a[j]:%d\n", j, ((int *)data)[j]);

                for(m=0; m<10; m++)
                        printf("%d ", ((int *)data)[m]);
                printf("\n");

                if(qksort(data, size, esize, i, j, compare) < 0)
                        return -1;

                for(m=0; m<10; m++)
                        printf("%d ", ((int *)data)[m]);
                printf("\n");

                i = j + 1;
        }
        return 0;
}

int main(int argc, char *argv[])
{
        int ret;
        int i, j, k;
        i = 11;
        j = 12;
        int array[10]= {1,4,7,2,5,8,3,6,9,10};

        printf("\n******************compare_init test**********************\n");
        printf("compare_int(&i, &j)=%d\n", compare_int(&i, &j));
        printf("compare_int(&j, &i)=%d\n", compare_int(&j, &i));
        printf("compare_int(&i, &i)=%d\n", compare_int(&i, &i));
        printf("\n******************partition    test**********************\n");

        qksort(array, 10, 4, 0, 9, compare_int);

        for(i=0; i<10; i++)
                printf("%d ", array[i]);
        printf("\n");

        return 0;
}
[email protected]:/mnt/shared/appbox/qksort# 

输出:

[email protected]:/mnt/shared/appbox/qksort# ./qksort    

******************compare_init test**********************
compare_int(&i, &j)=-1
compare_int(&j, &i)=1
compare_int(&i, &i)=0

******************partition    test**********************

--------------------------------------------------
i=0, k=9
1 4 7 2 5 8 3 6 9 10
r[0]:3, r[1]:6, r[2]:7, mid:6,middle:3
j=2, a[j]:2
1 3 2 7 5 8 4 6 9 10 

--------------------------------------------------
i=0, k=2
1 3 2 7 5 8 4 6 9 10
r[0]:1, r[1]:2, r[2]:1, mid:1,middle:3
j=1, a[j]:2
1 2 3 7 5 8 4 6 9 10 

--------------------------------------------------
i=0, k=1
1 2 3 7 5 8 4 6 9 10
r[0]:0, r[1]:0, r[2]:1, mid:0,middle:1
j=0, a[j]:1
1 2 3 7 5 8 4 6 9 10
1 2 3 7 5 8 4 6 9 10
1 2 3 7 5 8 4 6 9 10
1 2 3 7 5 8 4 6 9 10 

--------------------------------------------------
i=3, k=9
1 2 3 7 5 8 4 6 9 10
r[0]:6, r[1]:5, r[2]:8, mid:6,middle:4
j=3, a[j]:4
1 2 3 4 5 8 7 6 9 10
1 2 3 4 5 8 7 6 9 10 

--------------------------------------------------
i=4, k=9
1 2 3 4 5 8 7 6 9 10
r[0]:6, r[1]:5, r[2]:9, mid:6,middle:7
j=6, a[j]:7
1 2 3 4 5 6 7 8 9 10 

--------------------------------------------------
i=4, k=6
1 2 3 4 5 6 7 8 9 10
r[0]:5, r[1]:4, r[2]:4, mid:4,middle:5
j=4, a[j]:5
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 

--------------------------------------------------
i=5, k=6
1 2 3 4 5 6 7 8 9 10
r[0]:5, r[1]:5, r[2]:6, mid:5,middle:6
j=5, a[j]:6
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 

--------------------------------------------------
i=7, k=9
1 2 3 4 5 6 7 8 9 10
r[0]:9, r[1]:7, r[2]:7, mid:7,middle:8
j=7, a[j]:8
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 

--------------------------------------------------
i=8, k=9
1 2 3 4 5 6 7 8 9 10
r[0]:8, r[1]:8, r[2]:8, mid:8,middle:9
j=8, a[j]:9
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10 
时间: 2024-11-09 21:50:20

算法(二):快速排序的相关文章

算法整理(二)---快速排序的两种实现方式:双边扫描和单边扫描

首先简单谈下快速排序的特点,时间复杂度O(nLog n),最差时间复杂度O(n^2),平均时间O(nLog n).因为用到了函数栈,空间复杂度为O(lg n),最差为O(n).是一种不稳定的排序方法.基本思想是分治法,这位大大的http://blog.csdn.net/morewindows/article/details/6684558 讲的非常清楚了,分治法+挖坑法,我就不多说了.就是以某个数为参照,使得左边的都小于他,右边的数都大于他.然后对他的左右两个区间采取同样的方法进行递归. 就其整

排序算法 之 快速排序

快速排序是基于分治思想的一种排序算法,就像该方法的名字一样,速度比较快,所以叫做快速排序:它的平均时间复杂度为O(N*logN),最坏时间复杂度为O(n2),由于快速排序在序列元素数量多的时候速度比较快,所以很多语言内置的排序方法也是用快速排序实现的.快速排序也有很多优化的版本,比如在排序时基数的选择等等-下面就说一下一般的快速排序的实现. 基本思想: 快速排序的基本思想就是,先从待排序的序列中任选一个元素作为基数,然后将序列中的其他小于基数的元素放在基数的左边,大于或等于基数的元素放在基数的右

【转】三种快速排序算法以及快速排序的优化

一.  快速排序的基本思想 快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小.之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的. 二.  快速排序的三个步骤 1) 选择基准:在待排序列中,按照某种方式挑出一个元素,作为 “基准”(pivot): 2) 分割操作:以该基准在序列中的实际位置,把序列分成两个子序列.此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大: 3) 递归地对两个序列进行快速排序,直到序列为空或

(转载)排序二 快速排序

排序二 快速排序 目录 要点 算法分析 快速排序算法的性能 时间复杂度 空间复杂度 算法稳定性 完整参考代码 JAVA版本 参考资料 相关阅读 要点 快速排序是一种交换排序. 快速排序由C. A. R. Hoare在1962年提出. 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分:分割点左边都是比它小的数,右边都是比它大的数. 然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 详细的图解往往比大堆的文字更有说明力,所以直接上图:

排序算法之快速排序(Quicksort)解析

一.快速排序算法的优点,为什么称之为快排? Quicksort是对归并排序算法的优化,继承了归并排序的优点,同样应用了分治思想. 所谓的分治思想就是对一个问题“分而治之”,用分治思想来解决问题需要两个步骤: 1.如何“分”?(如何缩小问题的规模) 2.如何“治”?(如何解决子问题) 快排的前身是归并,而正是因为归并存在不可忽视的缺点,才产生了快排.归并的最大问题是需要额外的存储空间,并且由于合并过程不确定,致使每个元素在序列中的最终位置上不可预知的.针对这一点,快速排序提出了新的思路:把更多的时

算法:快速排序

原理: 在一个数组中,选一个元素(通常是第一个元素或者数组的中间元素)与剩余的其它元素进行比较:建立两个分组(左组和右组),比当前元素小的放在左组,比当前元素大的放在右组.这样一来,将左组,中间组合右组合并起来就形成一个已经“排好序”的数组.实际上,左组和右组中的元素并不一定已经排好序,调用自己去排序,只有左右数组的元素个数大于1,就需要排序,如果元素个数等于一个,就不再调用函数. 使用递归实现(步骤): 1.实现从数组中取出一个元素:将小的放左边数组,大的放右边数组,最后返回合并结果 2. 

十大基础实用算法之快速排序和堆排序

快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通常明显比其他Ο(n log n) 算法更快,因为它的内部循环(inner loop)可以在大部分的架构上很有效率地被实现出来. 快速排序使用分治法(Divide and conquer)策略来把一个串行(list)分为两个子串行(sub-lists). 算法步骤: 1 从数列中挑出一个元素,称为 "基准"(pi

经典白话算法之快速排序

[分析] [伪代码] [运行过程] [代码] /********************************* * 日期:2014-04-01 * 作者:SJF0115 * 题目:快速排序 **********************************/ #include <iostream> #include <stdio.h> using namespace std; //对子数组array[p...r]就地重排 int Partition(int array[],i

啊哈!算法之快速排序与桶排序

啊哈!算法之快速排序与桶排序 1.快速排序算法 快速排序由 C. A. R. Hoare(东尼·霍尔,Charles Antony Richard Hoare)在1960 年提出,之后又有许多人做了进一步的优化.在数列种随机找出一个基准数,因为数列是杂乱的,所以取首项为基准数.从后往前找到比基准数大的位置,再从前往后找到比基准数小的位置,交换元素:右游标向前移动与左游标向后移动,它们相遇时用基准数的位置与相遇的位置交换.此时原来数列以相遇的位置被划分为了两个需要排序的数列,再次执行上述过程:当左

排序算法 一 快速排序

算法:快速排序 思想:通过一趟排序,确定了一个data的最终确切位置.(通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列)  特点:不稳定算法. 代码实现: