【快速排序】—— [USACO07DEC]Bookshelf B
快速排序方法
背景
快速排序(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相关推荐
- 排序——[USACO07DEC]Bookshelf B
排序--[USACO07DEC]Bookshelf B 题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书 ...
- P2676 [USACO07DEC]Bookshelf B(随缘学习)
P2676 [USACO07DEC]Bookshelf B(随缘学习) 前言 # 一.题目 **题目描述** Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是 ...
- (Java) [USACO07DEC]Bookshelf B
[USACO07DEC]Bookshelf B 题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上 ...
- P2676 [USACO07DEC]Bookshelf B
题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有 N(1≤N≤20,000 ...
- 【洛谷】P2676 [USACO07DEC]Bookshelf B (c++)
题目描述 Farmer John最近为奶牛们的图书馆添置了一个巨大的书架,尽管它是如此的大,但它还是几乎瞬间就被各种各样的书塞满了.现在,只有书架的顶上还留有一点空间. 所有 N(1≤N≤20,000 ...
- ACM寒假训练第二周总结
时间:2022.1.17--2022.1.23 一.刷题记录 1. P1271 [深基9.例1]选举学生会 using namespace std; int a[1005]={0}; int main ...
- 【OJ】洛谷排序题单题解锦集
题单简介 题目解析 P1271[深基9.例1]选举学生会 P1177[模板]快速排序 P1923[深基9.例4]求第 k 小的数 P1059 明明的随机数 P1093 奖学金 P1781 宇宙总统 P ...
- 【算法1-2】排序(今天刷洛谷了嘛)
P1271 [深基9.例1]选举学生会 #include<iostream> #include<algorithm> #include<cstdio> #inclu ...
- 1177: 按要求排序(指针专题)_L2算法基础第10课 排序中
L2-算法基础-第10课 排序中 排序 归并排序 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用 ...
最新文章
- c# hdf5 写string_聊一聊C#8.0中的 await foreach
- c语言原始,[蓝桥杯][历届试题]回文数字 最原始的方法(C语言代码)
- 查看用户过期linux,linux下控制帐户过期的多种方法讲解
- [开源] FreeSql.Tools Razor 生成器
- 7-5 汽车加油问题 (20 分)(思路+详解)Come 宝!!!!!!!!!!!!!
- Windows 系统补丁管理策略
- opensource项目_生日快乐,Opensource.com:9年
- JavaScript==比较的规则
- flex 左右布局_移动端开发常用布局:前端弹性布局总结
- 德芙网络营销策略ppt_看德芙网络营销策划经典案例,戳这里!
- 计算机网络技术毕业生实习报告_计算机毕业实习报告8篇完美版
- android输入法好用,安卓手机输入法哪个最好用?
- 怎样在微信上发淘宝商品链接?
- 伦斯勒理工大学计算机专业,伦斯勒理工学院计算机科学硕士排名第60(2020年TFE Times排名)...
- 写一函数,将一个3*3的整型矩阵转置。
- Android实现图片轮播
- python版钉钉回调
- socksDroid结合charles抓取绕过代理的apk数据包(快手/闲鱼等)
- 【学习笔记】PHP进阶
- aix打开linux共享目录超长,AIX修改用户名和密码长度限制