文章目录
一、前文
在生活中,我们有许许多多排序的地方,比如定学号。Sam, Amy, Lingling和Daming四人的排序可能是按照首字母排。也就是:
学号 | 学生 | 首字母 |
---|---|---|
1 | Amy | A |
2 | Daming | D |
3 | Lingling | L |
4 | Sam | S |
C++中,我们应该如何排序呢?这次也是一种算法,叫做排序
二、正文
(一)冒泡排序
1. 如何冒泡?
假如定义一个数组A,我们要从小往大排序,我们可以用i遍历数组A的0到项数-2。如果
A
i
<
A
i
+
1
A_{i}<A_{i+1}
Ai<Ai+1那么交换A和B的值。最终末尾排的值就是最大的值。最终就能成功排序了。在stdlib.h
(或cstdlib
)库中有一个函数swap()
,里面要填入两个变量。下面有三种排序方法
(1)函数交换法
swap(a, b); //交换a和b的值
(2)临时存储法
int t = a;
a = b;
b = t;
(3)位运算法
这种方法意思现在不管,以后再说
a = a ^ b;
b = a ^ b;
a = a ^ b;
三种交换的时间复杂度比较:
函数交换法 < 位运算法 < 临时存储法
看下面动图
2. 如何实现?
会先输入一个数字,表示 A A A的总项数。再依次输入 A i A_{i} Ai。最终会分别输出被排序的 A i A_{i} Ai。
int main() {
int n;
cin >> n;
int a[n];
for(int i=0; i<n; i++) //输入
cin >> a[i];
for(int i=n-1; i>=0; i--)
for(int j=0; j<i; j++)
if(a[j]>a[j+1]) //交换
swap(a[j], a[j+1]);
for(int i=0; i<n; i++) //输出
cout << a[i] << ' ';
}
(二)选择排序
1. 如何选择?
说白了,就是在数组中找最小值,随后放在前面。具体动图
2. 如何实现?
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int a[n];
for(int i=0; i<n; i++) cin >> a[i]; //输入
for(int i=0; i<n; i++) {
int minx=INT_MAX, id=0; //INT_MAX表示int类型存储的极限
for(int j=i; j<n; j++)
if(minx>a[j]) minx=a[j], id=j;
swap(a[i], a[id]); //交换
}
for(int i=0; i<n; i++) cout << a[i] << ' '; //输出
return 0;
}
(三)插入排序
1. 如何插入?
首先,依次用i遍历
A
A
A中的值索引,然后在往前面翻,如果
A
i
<
A
j
A_{i}<A_{j}
Ai<Aj,那么插入在
A
j
A_{j}
Aj前,否则继续遍历。看下面的动图
2. 如何实现?
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int a[n];
for(int i=0; i<n; i++)
cin >> a[i];
for(int i=0; i<n-1; i++) {
int end=i, tmp=a[i+1];
while(end>=0) {
if(tmp<a[end])
a[end+1] = a[end--];
else
break;
}
a[end+1] = tmp;
}
for(int i=0; i<n; i++)
cout << a[i] << ' ';
}
(四)桶排序
1. 如何排?
超市中的收银机见过吧。每回我们支付现钱的时候,收银员会将一样的钱放在一样的盒子里,这就是一个桶。在我们输入的时候,就可以把相应的数字放入一个数组中,到时候输出就直接按照出现的次数了
1. 如何实现?
(1)桶排序
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, a[1000]={}, b[101000]={};
cin >> n;
for(int i=0; i<n; i++) {
cin >> a[i];
b[a[i]] ++;
}
for(int i=0; i<101000; i++)
for(int j=1; j<=b[i]; j++)
cout<<i<<' ';
return 0;
}
(2)桶排序去重
另外,使用桶排序我们还可以进行去重操作。就像这样
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, a[1000]={};
bool b[1010000]={};
cin >> n;
for(int i=0; i<n; i++) {
cin >> a[i];
b[a[i]] = true;
}
for(int i=0; i<1010000; i++)
if(b[i]) cout << i << ' ';
return 0;
}
桶排序的缺点是会占用大量空间
(五)sort排序
1. 如何用?
sort()
函数位于头文件algorithm
,使用方法如下:
#include <algorithm>
sort(Begit, Endit); //从Begit到Endit使用从小到大的方式进行排序
sort(Begit, Endit, Comp); //从Begit到Endit使用Comp规则进行排序
Begit
与Endit
中填的都是指针或迭代器!
(1)指针如何表示?
如果这个是STL(Standard Template Library)容器:
T.begin() //T的起始位置的迭代器
T.begin()+n //T[n]的迭代器
T.end() //T的终止符的迭代器
T.end()-1 //T的最后一项的迭代器
如果这是一个静态数组:
a //a的起始位置的迭代器
a + n //a[n]的迭代器
(2)Comp怎么填
这是一个自定义排序的变量,因此要填入的是一个函数
a. 普通函数填法
...
inline bool cmp (Typ a, Typ b) {
return Compare;
}
int main () {
......
int a[n];
......
sort(a, a+n, cmp);
}
这里的inline
是一个函数修饰词,表示这是一个内联函数,内联函数不能自己调用自己,但可以节省空间。Typ
是数组的类型,a
和b
代表相邻的两项。这样排序后相邻两项会遵守Compare
中的规则(两值相同情况除外,Compare
是布尔类型)
b. 匿名(lambda)函数填法
......
int main () {
......
int a[n];
......
sort(a, a+n, [](Typ a, Typ b){return Compare; });
}
一样的,Typ
填数组的类型,a
和b
表示相邻的两项,最终相邻两项会遵守Compare
的规则(两数相同情况除外,Compare
是布尔类型)
2. 如何写?
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int a[n];
for(int i=0; i<n; i++)
cin >> a[i];
sort(a, a+n); //排序
for(int i=0; i<n; i++)
cout << a[i] << ' ';
return 0;
}