快速排序方法

背景

快速排序(Quicksort)是对冒泡排序的一种改进,它由C. A. R. Hoare在1960年提出,其基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列,这种方法既不浪费空间,又可以快速地排序。

方法的简单介绍

例如对 a[10] = {6, 1, 2, 7, 9, 3, 4, 5, 10, 8} 进行排序,首先我们要在这个序列中随便找一个数作为基准数,以 “6” 为例作基准数

temp = a[0];
6 1 2 7 9 3 4 5 10 8
^

我们需要做的是把比 6 小的数移到左边,比 6 大的数移到右边,有什么办法能做到这点吗?

我们分别从序列的两端开始“探测”, 左端标记为 i , 右端标记为 j

6 1 2 7 9 3 4 5 10 8
^                  ^
i                  j

因为所设置的基准数是最左边的数,所以 j 先开始一步一步向左移动,直到找到比基准数 temp 小的数时停下(注意要保证 j 在 i 右边)

while(a[j] >= temp && j > i)j--;

接下来向右移动i,当i遇到比基准数temp大的数时停下

while(a[i] >= temp && j > i)i++;

此时 i ,j 位置如下

6 1 2 7 9 3 4 5 10 8^       ^     i       j

下一步,交换 a[i] 和 a[j]

6 1 2 5 9 3 4 7 10 8^       ^     i       j

到此,第一次交换结束,接下来进行第二次交换(每次都是 j 先移动)

6 1 2 5 9 3 4 7 10 8^   ^       i   j

交换 a[i]和 a[j]

6 1 2 5 4 3 9 7 10 8^   ^       i   j

当进行第三次交换时,j 停在了 “3” 的位置,而 i 向右移动会与 j 相遇
当他们相遇时,我们将基准数temp与 “3” 交换

3 1 2 5 4 6 9 7 10 8
^         ^

到此第一轮 “探测” 结束我们发现比基准数小的数都移到了左边,比基准数大的数都移到了右边。

不过我们发现 “6” 左右两边的序列还是混乱的。
接下来只要模拟刚才的方法,分别处理6左边的序列和右边的序列即可。

例如对左边的序列

3 1 2 5 4

我们可以以 “3” 为基准数进行“探测”,当 “3” 归位时再处理 “3” 左右两边的序列,直到无法拆分出新的子序列。

最终序列即为

1 2 3 4 5 6 7 8 9 10

图解快速排序

C语言代码实现

#include <stdio.h>
#include <stdlib.h>
int a[100000], n;
void QuickSort(int left, int right)
{int i,j,t,temp;if(left<=right){temp = a[left];   /*  定义基准数  */i = left;j = right;while(i != j){/*  将j向左移动 */while(a[j]>=temp && i<j)j--;/*  将i向右移动 */while(a[i]<=temp && i<j)i++;if(i < j)             //***********************//{                     //    若i与j没有相遇     //t = a[i];         //   交换i与j指向的数    //a[i] = a[j];      //**********************//a[j] = t;}}a[left] = a[i];a[i] = temp;QuickSort(left, i-1);    /*  递归处理左边的序列  */QuickSort(i+1, right);   /*  递归处理右边的序列  */}
}int main()
{/*    读入数据    */scanf("%d", &n);for(int i=0; i<n; i++)scanf("%d", a+i);/*    排序    */QuickSort(0, n-1);/*    输出    */for(int i=0; i<n; i++)printf("%d ", a[i]);return 0;
}

用二分法改进快速排序

用二分法的思想,把中间数作为基准数,因此QuickSort函数可改为如下形式:

void QuickSort(int left, int right)
{int i,j,t,temp;if(left<right){temp = a[(left+right)/2];   /*  定义中间数为基准数  */i = left;j = right;while(i <= j){           /*  将i向右移动 */while(a[i] < temp)i++;/*  将j向左移动 */while(a[j] > temp)j--;if(i <= j){                       //***********************//t = a[i];           //   交换i与j指向的数     //a[i++] = a[j];      //***********************//a[j--] = t;}}if(left<j) QuickSort(left, j);    /*  递归处理左边的序列  */if(i<right) QuickSort(i, right);   /*  递归处理右边的序列  */}
}

例题分析

下面来看一道有关快速排序的题吧

[USACO07DEC]Bookshelf B

  • 题目描述
    Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了。现在,只有书架的顶上还留有一点空间。
    所有N(1 <= N <= 20,000)头奶牛都有一个确定的身高H_i(1 <= H_i <= 10,000)。设所有奶牛身高的和为S。书架的高度为B,并且保证 1 <= B <= S < 2,000,000,007。
    为了够到比最高的那头奶牛还要高的书架顶,奶牛们不得不像演杂技一般,一头站在另一头的背上,叠成一座“奶牛塔”。当然,这个塔的高度,就是塔中所有奶牛的身高之和。为了往书架顶上放东西,所有奶牛的身高和必须不小于书架的高度。
    显然,塔中的奶牛数目越多,整座塔就越不稳定,于是奶牛们希望在能够到书架顶的前提下,让塔中奶牛的数目尽量少。 现在,奶牛们找到了你,希望你帮她们计算这个最小的数目。

  • 输入格式
    第1行: 2个用空格隔开的整数:N 和 B * 第2…N+1行: 第i+1行是1个整数:H_i

  • 输出格式
    第1行: 输出1个整数,即最少要多少头奶牛叠成塔,才能够到书架顶部

  • 输入输出样例

    • 输入 #1

      6 40
      6
      18
      11
      13
      19
      11

    • 输出 #1

      3

  • 说明/提示

    • 输入说明:

      一共有6头奶牛,书架的高度为40,奶牛们的身高在6~19之间。

    • 输出说明:

      一种只用3头奶牛就达到高度40的方法:18+11+13。当然还有其他方法,在此不一一列出了。

  • 代码实现

#include <stdio.h>
#include <stdlib.h>
int a[200000], n;void QuickSort(int left, int right)
{int i,j,t,temp;if(left<right){temp = a[(left+right)/2];   /*  定义中间数为基准数  */i = left;j = right;while(i <= j){           /*  将i向右移动 */while(a[i] < temp)i++;/*  将j向左移动 */while(a[j] > temp)j--;if(i <= j){                       //***********************//t = a[i];           //   交换i与j指向的数     //a[i++] = a[j];      //***********************//a[j--] = t;}}if(left<j) QuickSort(left, j);    /*  递归处理左边的序列  */if(i<right) QuickSort(i, right);   /*  递归处理右边的序列  */}
}int main()
{int i, max, sum=0;/*    读入数据    */scanf("%d%d", &n, &max);for(i=0; i<n; i++){scanf("%d", a+i);}/*    排序    */QuickSort(0, n-1);for(i=n-1; i>=0; i--){  sum += a[i];if(sum >= max)break;}/*    输出    */printf("%d", n-i);return 0;
}

【快速排序】—— [USACO07DEC]Bookshelf B相关推荐

  1. 排序——[USACO07DEC]Bookshelf B

    排序--[USACO07DEC]Bookshelf B 题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书 ...

  2. P2676 [USACO07DEC]Bookshelf B(随缘学习)

    P2676 [USACO07DEC]Bookshelf B(随缘学习) 前言 # 一.题目 **题目描述** Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是 ...

  3. (Java) [USACO07DEC]Bookshelf B

    [USACO07DEC]Bookshelf B 题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上 ...

  4. P2676 [USACO07DEC]Bookshelf B

    题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有 N(1≤N≤20,000 ...

  5. 【洛谷】P2676 [USACO07DEC]Bookshelf B (c++)

    题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有 N(1≤N≤20,000 ...

  6. ACM寒假训练第二周总结

    时间:2022.1.17--2022.1.23 一.刷题记录 1. P1271 [深基9.例1]选举学生会 using namespace std; int a[1005]={0}; int main ...

  7. 【OJ】洛谷排序题单题解锦集

    题单简介 题目解析 P1271[深基9.例1]选举学生会 P1177[模板]快速排序 P1923[深基9.例4]求第 k 小的数 P1059 明明的随机数 P1093 奖学金 P1781 宇宙总统 P ...

  8. 【算法1-2】排序(今天刷洛谷了嘛)

    P1271 [深基9.例1]选举学生会 #include<iostream> #include<algorithm> #include<cstdio> #inclu ...

  9. 1177: 按要求排序(指针专题)_L2算法基础第10课 排序中

    L2-算法基础-第10课 排序中 排序 归并排序 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用 ...

最新文章

  1. c# hdf5 写string_聊一聊C#8.0中的 await foreach
  2. c语言原始,[蓝桥杯][历届试题]回文数字 最原始的方法(C语言代码)
  3. 查看用户过期linux,linux下控制帐户过期的多种方法讲解
  4. [开源] FreeSql.Tools Razor 生成器
  5. 7-5 汽车加油问题 (20 分)(思路+详解)Come 宝!!!!!!!!!!!!!
  6. Windows 系统补丁管理策略
  7. opensource项目_生日快乐,Opensource.com:9年
  8. JavaScript==比较的规则
  9. flex 左右布局_移动端开发常用布局:前端弹性布局总结
  10. 德芙网络营销策略ppt_看德芙网络营销策划经典案例,戳这里!
  11. 计算机网络技术毕业生实习报告_计算机毕业实习报告8篇完美版
  12. android输入法好用,安卓手机输入法哪个最好用?
  13. 怎样在微信上发淘宝商品链接?
  14. 伦斯勒理工大学计算机专业,伦斯勒理工学院计算机科学硕士排名第60(2020年TFE Times排名)...
  15. 写一函数,将一个3*3的整型矩阵转置。
  16. Android实现图片轮播
  17. python版钉钉回调
  18. socksDroid结合charles抓取绕过代理的apk数据包(快手/闲鱼等)
  19. 【学习笔记】PHP进阶
  20. aix打开linux共享目录超长,AIX修改用户名和密码长度限制

热门文章

  1. java jsp中文乱码怎么解决_JSP中文乱码的解决
  2. vue 之 echarts饼形图 如何显示负数份额
  3. 基于layui框架的登录验证
  4. JAVA最新编程50题
  5. Android Studio key SHA1获取方法
  6. android 滤镜高仿,“抖音一姐”花10亿整成高仿baby?关掉滤镜不敢认…
  7. 记录一次 使用easyexcel设置数据有效性
  8. Intel官网资料下载链接
  9. 通知:PostgreSQL证书申报退税请抓紧
  10. 重磅|火山引擎边缘计算节点服务正式发布!