快速排序算法 quick sort 的描述

/*  quick sort algorithm */
/*  snallie@tom.com */
/*  Wed Apr  2 10:57:01 HKT 2008 */

/*
快速排序是基于交换和分划的思想进行排序的一种排序算法,是bubble sort的一种改进算法.
以如下的示例进行说明
下标      01 02 03 04 05 06 07 08 09 10 11
原始 [00] 91 82 71 98 00 76 54 60 88 77 30
(01)
     [91] 30 82 71 98 00 76 54 60 88 77 -1  [i=02,j=11]
     [91] 30 82 71 -1 00 76 54 60 88 77 98  [i=04,j=11]
     [91] 30 82 71 77 00 76 54 60 88 -1 98  [i=05,j=10]
     [91] 30 82 71 77 00 76 54 60 88 -1 98  [i=10,j=10]
(02)
     [30] 00 82 71 77 -1 76 54 60 88 91 98  [i=02,j=05]
     [30] 00 -1 71 77 82 76 54 60 88 91 98  [i=02,j=05]
(03)
     [71] 00 30 60 77 82 76 54 -1 88 91 98  [i=04,j=08]
     [71] 00 30 60 -1 82 76 54 77 88 91 98  [i=04,j=08]
     [71] 00 30 60 54 82 76 -1 77 88 91 98  [i=05,j=07]
     [71] 00 30 60 54 -1 76 82 77 88 91 98  [i=05,j=07]
(04)
     [60] 00 30 54 -1 71 76 82 77 88 91 98  [i=04,j=04]
     [60] 00 30 54 -1 71 76 82 77 88 91 98  [i=04,j=04]
(05)
(06)
     [82] 00 30 54 60 71 76 77 -1 88 91 98  [i=08,j=08]
     [82] 00 30 54 60 71 76 77 -1 88 91 98  [i=08,j=08]
qsort result below:
     [82] 00 30 54 60 71 76 77 82 88 91 98  最终排序的结果
前提:升序排序
一般地,所谓的分划操作即是,任意选取一个枢轴记录ai,(一般为方便起见,选取待排序序列
的首元素为枢轴记录ai), 将待排序的记录序列分划为两部分:前半部分A1和后半部分A2,使得
A1中的元素都小于(或小于等于)枢轴记录ai, 而位于后半部分A2的记录元素都大于枢轴记录ai,
此时已经基本有序,这一分划的过程主要进行的即是交换的操作。 在分划的过程中主要是采
取从两边向中央进行扫描的方法,(一般地,先从后向前扫描,而从前向后扫描,反复进行,
直到前向扫描和后向扫面的指针碰到一起,则结束),在扫描的过程中,逐渐将小于枢轴记录的
元素移动至左半部,而 将大于枢轴记录的元素移动至右半部,在每个半部分中的元素可以无序,
上面所进行是一遍的分划。而后再递归地将前半部分A1进行如上的快速排序,再对后半部分A2
递归快速排序即可。所以,快速排序要进行递归的排序调用

如上面的排序示例数据所示:设数据存在数组data[12]中,其中的data[0]为辅助暂存单元,
下标为1~11区间的数据为有效的数据,原始状态如“原始”所示,以data[1]=91为枢轴记录,将
枢轴记录存放于暂存单元data[0],先从后向前扫描,即11~1的方向,查找小于91的第1个元素,
结果为data[11]=30,将30移动到data[1]中,(data[1]的数据被覆盖,但是先前已经被保存到
data[0]中,所以数据不会丢失),同时data[11]置为空闲待填充的单元(用-1进行表示),这
时后向的扫描的指针j指向11,此时再进行从前向后的扫描,即从2~11的方向,查找大于枢轴
记录91的第1个元素,结果找到data[4]=98,此时前向的扫描指针i指向4,将98移动至data[11],
同时data[4]置为空闲待填充的单元,再从后向扫描指针j=10的位置向低下标的方向进行扫描,
找到77<枢轴记录91,将77移动至刚才留下的空闲待填充单元data[4],而后再从i=5向高下标的
方向进行扫描,结果i与j碰到了一起, 这时i与j所指的位置10即为枢轴记录91应该落入的位置,
将暂存单元data[0]=91复制至data[10],这时第一遍分划即完成:位于data[10]前的数据均小于
91,位于data[10]后的数据均大于91。以下的过程即是上面过程的递归重复(但是数据的规模在
逐步缩小),将1~数轴的前一位置区块的数据进行快速排序;上面的过程完成后再将数轴的后一
位置区块(至数据区的结尾)数据进行快速排序。 最终完成排序。
*/

#include <stdio.h>
#define SIZE 20
/* 数组的初始化,产生一组随机数填充数组 */
void initAry(int data[])
{
    int i;
    data[0] = 0;
    srand(time(&i));
    for (i = 1; i < SIZE; i++) {
 data[i] = rand() % 100;
    }
}

/*    */
void outputAry(int data[], int cr)
{
    int i;
    printf("     [%02d] ", data[0]);
    for (i = 1; i < SIZE; i++) {
 printf("%02d ", data[i]);
    }
    if (cr)
 printf("/n");
}

/* data[]存放待排序的数据,其中的data[0]为暂存单元,start指示待排序数据起始下标,end为结束下标 */
void qsort(int data[], int start, int end)
{
    int i, j, tmp;
    static int invokeNum; /* 辅助变量,记录qsort函数被调用的次数 */
    invokeNum++;
    tmp = data[0] = data[start]; /* 枢轴记录于data[0] */
    i = start;   /*  i为前向扫描指针,初始指向排序缓冲区的首部 */
    printf("(%02d)/n", invokeNum); /* 显示qsort被调用的次数 */
    for (j = end; j > i; j--) { /*  j为后向扫描指针,先从后向前进行扫描 */
 if (data[j] > tmp)
     continue;
 data[i] = data[j]; /* 找到小于枢轴记录的元素,存放缓冲区的前部 */
 data[j] = -1;  /* j所指单元置为空闲待填充状态,可有可无,为便于观察 */
 i++;
 outputAry(data, 0); /* 输出数据,便于查看,可有可无 */
 printf(" [i=%02d,j=%02d]/n", i, j); /* 输出 i,j指向的位置。可有可无,为便于观察 */

 for (; i < j; i++) { /* i为前向扫描指针,从前向后进行扫描 */
     if (data[i] < tmp) /*  找大于枢轴记录的元素 */
  continue; /*  没找到,返回继续找。 */
     else
  break;  /*  找到,跳出 */
 }
 data[j] = data[i]; /*  找到的大于枢轴记录的元素存放至缓冲区的后部待填充的单元, */
 data[i] = -1;  /*  i所指单元置为空闲待填充状态,可有可无,为便于观察 */
 outputAry(data, 0); /* 输出数据,便于查看,可有可无 */
 printf(" [i=%02d,j=%02d]/n", i, j); /* 输出 i,j指向的位置。可有可无,为便于观察 */
    }
    data[i] = tmp;  /* i,j指针碰到一起,即枢轴记录应该落入的位置。 */

    if (i - 1 > start)
 qsort(data, start, i - 1); /* 递归调用 qsort 对枢轴记录前的元素进行快速排序 */
    if (i + 1 < end)
 qsort(data, i + 1, end); /* 递归调用 qsort 对枢轴记录后的元素进行快速排序 */
}

int main()
{
    int data[SIZE], i;
    initAry(data);  /*  产生初始数据  */
    printf("          "); /*  格式化显示输出。 */
    for (i = 1; i < SIZE; i++) /*  输出下标。 */
 printf("%02d ", i);
    printf("/n");
    outputAry(data, 1);  /*  输出初始数据  */
    qsort(data, 1, SIZE - 1);
    printf("qsort result below:/n");
    outputAry(data, 1);  /*  输出排序数据 */

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 快速排序算法是一种高效的排序算法,它的基本思想是选择一个数作为基准值,然后将待排序序列中小于基准值的数放在基准值的左边,大于基准值的数放在基准值的右边,再对左右两边的子序列分别进行递归排序,直到整个序列有序为止。具体实现可以使用Python代码来描述,例如下面这段代码: ``` def quick_sort(arr): if len(arr) <= 1: return arr else: pivot = arr[0] left = [x for x in arr[1:] if x < pivot] right = [x for x in arr[1:] if x >= pivot] return quick_sort(left) + [pivot] + quick_sort(right) ``` 这段代码中,首先判断序列长度是否小于等于1,如果是,则返回原序列;否则选择第一个数作为基准值,将小于基准值的数放在左边,大于等于基准值的数放在右边,然后对左右两边的子序列进行递归排序,最后将左边、基准值、右边三部分拼接在一起返回即可。 ### 回答2: 快速排序是一种常用的排序算法,其基本思想是通过一趟排序将待排序的记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,然后对这两部分记录分别再进行快速排序,最后合并顺序即可得到有序序列。 快速排序的具体步骤如下: 1. 选择一个基准元素 pivot,一般为待排序序列的第一个元素。 2. 设置两个指针 left 和 right,分别指向待排序序列的最左和最右元素。 3. 从 right 开始,找到第一个小于 pivot 的元素,交换 right 和 pivot 元素的值,并将 right 向左移动一位。 4. 从 left 开始,找到第一个大于 pivot 的元素,交换 left 和 pivot 元素的值,并将 left 向右移动一位。 5. 重复步骤 3 和步骤 4,直到 left 和 right 指针相遇。 6. 将 pivot 元素放到 left 和 right 指针相遇的位置,此时 pivot 左边的元素均小于 pivot,右边的元素均大于 pivot。 7. 分别对 pivot 左边和右边的子序列进行快速排序,直到子序列长度为 1 或 0。 快速排序的时间复杂度为 O(nlogn),其中 n 为待排序序列的长度。相比其他排序算法,快速排序具有较高的平均性能和较好的适应性,尤其在大数据量排序时表现更为突出。 ### 回答3: 快速排序算法是一种非常高效的排序算法,在处理大量数据时表现出色。它采用分治法的思想,通过递归的方式将数据分割成更小的子数组,然后对这些子数组进行排序,最终将所有子数组合并成一个有序的数组。 具体来说,快速排序算法的步骤如下: 1. 选择一个基准元素,通常是数组的第一个或最后一个元素。 2. 将数组分割成两个子数组,其中一个子数组的元素值都小于基准元素,另一个子数组的元素值都大于基准元素。 3. 递归地对两个子数组进行快速排序。 4. 将两个有序的子数组合并成一个有序的数组。 快速排序的核心是分割操作,通过将元素按照基准元素进行分割,使得基准元素左边的元素都小于基准元素,右边的元素都大于基准元素。具体的分割操作可以使用两个指针,一个指向数组的开头,一个指向数组的结尾,然后不断地交换元素,直到两个指针相遇。最后,将基准元素与相遇点的元素交换,完成一次分割操作。 快速排序算法的平均时间复杂度为O(nlogn),最坏情况下为O(n^2),空间复杂度为O(logn)。因为快速排序算法是原地排序算法,不需要额外的空间来存储临时数据。 总结来说,快速排序算法是一种高效的排序算法,它通过递归的方式将数据进行分割和排序,最终得到一个有序的数组。它的核心是分割操作,通过不断地交换元素将数组分成两个子数组。这使得快速排序算法具有较好的时间复杂度和空间复杂度,适用于处理大量数据的排序任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值