HDU-1040-As Easy As A+B(各种排序)
- 希尔排序
Accepted 1040 0MS 1224K 564 B G++ #include "cstdio"
using namespace std;
int arr[];
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i < n; i++) {
scanf("%d", &arr[i]);
}
// 一开始将增量设置为n的一半,将n个数分成n/2份进行插排,每份大概只有两个数,每次增量减半
for (int i = n >> ; i > ; i >>= ) {
for (int j = i; j < n; j++) {
int u = arr[j];
int id = j - i;
while (id >= && arr[id] > u) {
arr[id + i] = arr[id];
id -= i;
}
arr[id + i] = u;
}
}
printf("%d", arr[]);
for (int i = ; i < n; i++) {
printf(" %d", arr[i]);
}
puts("");
}
return ;
}希尔排序是优化版的插入排序。
- 快速排序
Accepted 1040 0MS 1372K 1736 B G++ #include "bits/stdc++.h"
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
int arr[];
void quickSort(int l, int r) {
/*
注意一种错误写法:if (l == r)
在排序9 8这样的数据时会造成无限循环
*/
if (l >= r) {
return;
}
int mid = l + r >> , id;
// 找arr[l]、arr[r]、arr[mid]三个点中的中位数
if (arr[l] <= arr[mid] && arr[l] <= arr[r]) {
id = arr[mid] <= arr[r] ? mid : r;
} else {
if (arr[mid] <= arr[r]) {
id = arr[l] <= arr[r] ? l : r;
} else {
id = arr[l] <= arr[mid] ? l : mid;
}
}
// 将找到的中位数放在待排序数组的最左端
swap(arr[l], arr[id]);
int le = l + , gt = r;
// 在下面的循环过程中,arr[l + 1]到arr[le]小于等于arr[l],arr[gt]到arr[r]大于arr[l];
while (le < gt) {
if (arr[le] <= arr[l]) {
le++;
} else if (arr[gt] <= arr[l]){
swap(arr[le], arr[gt]);
le++;
gt--;
} else {
while (arr[gt] > arr[l] && le < gt) {
gt--;
}
}
}
if (arr[le] > arr[l]) {
le--;
}
swap(arr[le], arr[l]);
/*
注意一个错误写法:quickSort(l, le);
在排序如4 0 2 4这样的数据时会造成无限循环
*/
quickSort(l, le - );
quickSort(le + , r);
}
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%d", &arr[i]);
}
quickSort(, n);
for (int i = ; i < n; i++) {
printf("%d ", arr[i]);
}
printf("%d\n", arr[n]);
}
return ;
}这是最常用的一种排序方式,Java里面的Array.sort用的就是这种方式进行排序的,还有就是之前一直说这种排序方式的复杂度为nlogn,但是要注意nlgn是最好情况。一般达不到的,在排序个数小于等于8时用n^2复杂度的插入排序反而更快,所以quickSort函数里还可以进行一个判断if (r - l + 1 <= 8){插排}来进行优化。
- 插入排序
Accepted 1040 0MS 1380K 705 B G++ #include "bits/stdc++.h"
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
int arr[];
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i < n; i++) {
scanf("%d", &arr[i]);
}
for (int i = ; i < n; i++) {
int temp = arr[i], j = i - ;
while (j >= && arr[j] > temp) {
arr[j + ] = arr[j];
j--;
}
arr[j + ] = temp;
}
printf("%d", arr[]);
for (int i = ; i < n; i++) {
printf(" %d", arr[i]);
}
puts("");
}
return ;
}就是让arr[0]到arr[i - 1]保持有序之后把arr[i]插入到前面的有序数列中去从而使arr[0]到arr[i]有序,逆序转正序的情况下复杂度最高,算法复杂度为O(N^2);
- 归并排序
Accepted 1040 0MS 1376K 1270B G++ #include "bits/stdc++.h"
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
int arr[], help[];
void mergeSort(int l, int r) {
if (l >= r) {
return;
}
int mid = l + r >> ;
// 递归排序l到mid和mid + 1到r
mergeSort(l, mid);
mergeSort(mid + , r);
// 将l到r拷贝到help数组对应位置,此时可将help[l]到help[mid]看成一个数组,help[mid + 1]到help[r]看成另一个数组
memmove(help + l, arr + l, sizeof(int) * (r - l + ));
int L = l, R = mid + , id = l;
// 每次取出help[L]和help[R]中值小的填入arr[id]直到一边被取完为止
while (L <= mid && R <= r) {
if (help[L] <= help[R]) {
arr[id++] = help[L++];
} else {
arr[id++] = help[R++];
}
}
// 如果被取完的是help[l],那么help[R]后面的数已经存在于arr中对应位置不用移动,否则将help[L]后面的数移到arr数组后面;
while (L <= mid) {
arr[id++] = help[L++];
}
}
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%d", &arr[i]);
}
mergeSort(, n);
for (int i = ; i < n; i++) {
printf("%d ", arr[i]);
}
printf("%d\n", arr[n]);
}
return ;
}和快速排序一样是O(nlogn)的排序方法,这个方法需要借助辅助空间。
- 堆排序
Accepted 1040 0MS 1372K 1117 B G++ #include "bits/stdc++.h"
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
const int INF = 0x3f3f3f3f;
int arr[], m;
void maxHeapFix(int id) {
// mx存左右儿子中比较大的,一开始假设左儿子比右儿子大
int mx = id << ;
// 如果左儿子越界,右儿子肯定越界,id为叶子节点,直接返回
if (mx > m) {
return;
}
// 否则如果右儿子没越界并且右儿子大于左儿子,则mx = 右儿子
if (mx < m && arr[mx | ] > arr[mx]) {
mx |= ;
}
if (arr[mx] > arr[id]) {
swap(arr[mx], arr[id]);
maxHeapFix(mx);
}
}
int main() {
int t, n;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i <= n; i++) {
scanf("%d", &arr[i]);
}
m = n;
for (int i = n >> ; i; i--) {
maxHeapFix(i);
}
while (m != ) {
swap(arr[], arr[m--]);
maxHeapFix();
}
for (int i = ; i < n; i++) {
printf("%d ", arr[i]);
}
printf("%d\n", arr[n]);
}
return ;
}就是不断维护大顶堆,大顶堆的堆顶是堆中最大,和最后一个元素交换后将堆的大小减1后继续维护大顶堆,复杂度O(nlgn)
- 基数排序
Accepted 1040 0MS 1416K 1160 B G++ #include "bits/stdc++.h"
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
// 选取基数,不一定非要选10
const int BASE = ;
vector<int> arr;
// 因为涉及负数排序,bucket开基数的两倍,前一半用来存负数
vector<int> bucket[BASE << ];
int main() {
int t, n , m;
scanf("%d", &t);
while (t--) {
arr.clear();
scanf("%d", &n);
for (int i = ; i < n; i++) {
scanf("%d", &m);
arr.push_back(m);
}
// 因为int中绝对值最大为 1LL << 31, 所以上限设为1LL << 31
for (LL bit = ; bit <= 1LL << ; bit *= BASE) {
for (int i : arr) {
// 这里可以想象成进制转换,将i转换成BASE进制后求某一位
bucket[i / bit % BASE + BASE].push_back(i);
}
arr.clear();
for (int i = ; i < BASE << ; i++) {
arr.insert(arr.end(), bucket[i].begin(), bucket[i].end());
bucket[i].clear();
}
}
printf("%d", arr[]);
for (int i = ; i < n; i++) {
printf(" %d", arr[i]);
}
puts("");
}
return ;
}基数排序原理有点像字典序,从右边往左一遍遍扫描,高位补0。其时间复杂度为O (nlog(r)m),其中r为所采取的基数,而m为堆数。
- 桶排序
Accepted 1040 0MS 1412K 1142 B G++ #include "bits/stdc++.h"
using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
int t, n, m;
vector<int> bucket[];
int getHash(LL m) {
// 减INT_MIN的作用是保证m为非负数,减完后的最大值为(1LL << 32) - 1,为保证哈希值在[0,n)的范围内除1LL << 32
return (m - INT_MIN) * n / (1LL << );
}
void insert(int id, int m) {
int j = bucket[id].size();
bucket[id].push_back(m);
while (j > && bucket[id][j - ] > m) {
bucket[id][j] = bucket[id][j - ];
j--;
}
bucket[id][j] = m;
}
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = ; i < n; i++) {
scanf("%d", &m);
insert(getHash(m), m);
}
bool flag = true;
for (int i = ; i < n; i++) {
for (auto j : bucket[i]) {
if (flag) {
printf("%d", j);
flag = false;
} else {
printf(" %d", j);
}
}
bucket[i].clear();
}
puts("");
}
return ;
}桶排序的适用范围是数据平均分布的情况,这种情况下复杂度很低可达到O(N),所以考虑在一个桶内的数不会太多,用插入排序。但是分布极不均匀的情况下(所有数据在一个桶中)将退化成插入排序;
HDU-1040-As Easy As A+B(各种排序)的更多相关文章
- HDU 1040.As Easy As A+B【排序】【如题(水!水!水!)】【8月24】
As Easy As A+B Problem Description These days, I am thinking about a question, how can I get a probl ...
- HDU 1040 As Easy As A+B (排序。。。水题)
题意:给定n个数,让你从小到大排序. 析:不说什么了. 代码如下: #include <cstdio> #include <iostream> #include <cst ...
- hdu 1040 As Easy As A+B(排序)
题意:裸排序 思路:排序 #include<iostream> #include<stdio.h> #include<algorithm> using namesp ...
- hdu 1040 As Easy As A+B
As Easy As A+B Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) T ...
- HDU 1040 As Easy As A+B(排序)
As Easy As A+B Problem Description These days, I am thinking about a question, how can I get a probl ...
- HDU 1040 As Easy As A+B [补]
今天去老校区找她,不想带电脑了,所以没时间A题了 /*******************************************************************/ As Ea ...
- 杭电 1040 As Easy As A+B 【排序】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1040 解题思路:数据不大,可以直接用冒泡排序 #include<stdio.h> int ...
- HDU 5572 An Easy Physics Problem (计算几何+对称点模板)
HDU 5572 An Easy Physics Problem (计算几何) 题目链接http://acm.hdu.edu.cn/showproblem.php?pid=5572 Descripti ...
- hdu 5058 So easy
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5058 So easy Description Small W gets two files. Ther ...
- hdu 5475 An easy problem(暴力 || 线段树区间单点更新)
http://acm.hdu.edu.cn/showproblem.php?pid=5475 An easy problem Time Limit: 8000/5000 MS (Java/Others ...
随机推荐
- Python说文解字_杂谈03
1. 我们从前面的知识得到,所有的类都要继承自object这个基类(超类),另外我们知道“继承”可以继承类的属性和方法.我们起始通过type创建类的时候,自然而然的也会从ojbect继承他的一些属性和 ...
- ZJNU 1125 - A == B ?——中级
处理后再判断即可,处理过程注意考虑全面. /* Written By. StelaYuri */ #include<iostream> #include<string> usi ...
- Linux-竟态初步引入
(1).竟态全称是:竞争状态,多进程环境下,多个进程同时抢占系统资源(内存.CPU.文件IO). (2).竞争状态对于操作系统OS来说是很危险的,此时的操作系统OS如果没有处理好就会造成结果不确定. ...
- Python笔记_第三篇_面向对象_8.对象属性和类属性及其动态添加属性和方法
1. 对象属性和类属性. 我们之前接触到,在类中,我们一般都是通过构造函数的方式去写一些类的相关属性.在第一次介绍类的时候我们把一些属性写到构造函数外面并没有用到构造函数,其实当时在写的时候,就是在给 ...
- PyTorch基础——使用卷积神经网络识别手写数字
一.介绍 实验内容 内容包括用 PyTorch 来实现一个卷积神经网络,从而实现手写数字识别任务. 除此之外,还对卷积神经网络的卷积核.特征图等进行了分析,引出了过滤器的概念,并简单示了卷积神经网络的 ...
- callable和runnable的区别
Runnable接口源码 @FunctionalInterface public interface Runnable { /** * When an object implementing inte ...
- spi设备描述过程
一.spi通信 中控制器驱动及spi设备.spi设备驱动的关系入下图: 控制器驱动以及设备全志已经完成,在/driver/spi/spi--sunxi.c 中,打开源码文件可以看到spi控制器属于平 ...
- iOS keychain报错 25293
经过查找发现25293对应的错误是如下,即用户名和密码不正确. errSecAuthFailed = -25293, /* The user na ...
- Java复习(三)类中的方法
3.1方法的控制流程 与C/C++类似 3.2异常处理 Java处理错误的方法 抛出(throw)异常 在方法的运行过程中,如果发生了异常,则该方法生成一个代表该异常的代码并把它交给运行时系统,运行时 ...
- 方格取数(多线程dp,深搜)
https://www.luogu.org/problem/P1004 题目描述 设有N×N的方格图(N≤9),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0.如下图所示(见样例): 某 ...