选择排序法
从小到大排列,选取数组中最小的数,每次循环将最小的数与最前面的还没有顺序的数交换。
时间复杂度为o(n^2),空间复杂度为o(1)。
代码如下
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int a[1000];
int i,j;
for(i=0;i<n;i++){
cin>>a[i];
}
int max;//用于记录最大值的下标
int tem;
for (i = 0; i < n - 1; i++) {
max = i;
for (j = i + 1; j < n; j++) {
if (a[j] > a[max]) {
max = j;//记录最大值的下标
}
}
tem = a[i];
a[i] = a[max];
a[max] = tem;//与无序的数进行交换
}
for(i=0;i<n;i++){
cout<<a[i];
}
}
冒泡排序法
比较相邻元素的大小,如果顺序不对则交换。
时间复杂度为o(n^2),空间复杂度为o(1)。
代码如下
//冒泡排序法
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int a[1000];
int i,j;
for(i=0;i<n;i++){
cin>>a[i];
}
int tem;
for(i=0;i<n-1;i++){
for(j=0;j<n-1-i;j++){
if(a[j]>a[j+1]){
tem=a[j];
a[j]=a[j+1];
a[j+1]=tem; //遍历数组相邻的数比较大小并交换
}
}
}
for(i=0;i<n;i++){
cout<<a[i];
}
}
插入排序法
每次将一个待排序的数据,跟前面已经有序的序列的数字一一比较找到自己合适的位置,插入到序列中,直到全部数据插入完成。
时间复杂度为o(n^2),空间复杂度为o(1).
代码如下
//插入排序法
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int a[1000];
int i,j;
for(i=0;i<n;i++){
cin>>a[i];
}
int tem;
for(i=1;i<n;i++){
tem=a[i];//记录有序数后面一个数
for(j=i-1;j>=0;j--){
if(a[j]>tem){
a[j+1]=a[j];//与前面的有序数比较,若成立将后面的数后移
}
else break;
}
a[j+1]=tem;将数插入
}
for(i=0;i<n;i++){
cout<<a[i];
}
}
快速排序法
设置一个基数,将数组分成两部分,从两边开始扫描,比较与基数的大小,将比基数小的全部放到左边,比基数大的全部放到右边,并在左右两边继续调用函数。
时间复杂度为o(nlog2 (n)),空间复杂度为o(log2 (n))
代码如下
//快速排序法
#include <iostream>
using namespace std;
long a[100100];
void qsort(int left,int right){
if(left>=right){
return;
}
int tem,t;
tem=a[(left+right)/2];
int i,j;
i=left;
j=right;
while(i<=j){
while(a[j]>tem){
j--;//找到比基数小的数的下标
}
while(a[i]<tem){
i++;//找到比基数大的数的下标
}
if(i<=j){
t=a[i];
a[i]=a[j];
a[j]=t;
i++;
j--;//进行交换
}
}
if(i<right) qsort(i,right);
if(left<j) qsort(left,j);//分别再进行交换
}
int main()
{
int n;
while(cin>>n){
int i;
for(i=0;i<n;i++){
cin>>a[i];
}
qsort(0,n-1);
int flag=0;
for(i=0;i<n;i++){
if(flag!=0){
cout<<" ";
}
cout<<a[i];
flag++;
}
return 0;
}
}
归并排序法
归并排序主要分为两步:分数列,每次把数列一分为二,然后分到只有两个元素的小数列;合数列,合并两个已经内部有序的子序列,直至所有数字有序。用递归可以实现。
时间复杂度为o(nlog2 (n)),空间复杂度为o(n)
代码如下
//归并排序
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int arr[1005], tmp[1005];
void msort(int l, int r) {
if(l == r) return;
int m = (l + r) / 2;
msort(l, m);
msort(m + 1, r);//分
int i = l, j = m + 1, k = l; // i, j管理arr, k管理tmp
while(i <= m && j <= r) {
if(arr[i] > arr[j]) {
tmp[k++] = arr[j++]; // 小的在前
}
else {
tmp[k++] = arr[i++];
}
}
// 处理两部分长度不等的情况
while(i <= m) {
tmp[k++] = arr[i++];
}
while(j <= r) {
tmp[k++] = arr[j++];
}
for(int i = l; i <= r; i++) {
arr[i] = tmp[i];
}
}
int main()
{
int i,n;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&arr[i]);
msort(0,n-1);
for(i=0;i<n;i++)
printf("%d ",arr[i]);
return 0;
}
逆序对问题
我们有一个数列a1, a2, …, an,现在我们规定满足条件i < j且ai > aj的数对(ai, aj)为该数列的一个逆序对。给定数列{an},求数列中所有的逆序对数。
可以使用归并算法来统计逆序对,每次进行交换,交换前都是逆序对。
代码如下
//逆序对问题
#include <cstdio>
int arr[40005], tmp[40005];
int msort(int l, int r) {
int cnt = 0;
if(l == r) return 0;
int m = (l + r) /2;
cnt += msort(l, m);
cnt += msort(m + 1, r);
int i = l, j = m + 1, k = l; // i, j管理arr, k管理tmp
while(i <= m && j <= r) { if(arr[i] > arr[j]) {
tmp[k++] = arr[j++]; // 小的在前
cnt += m - i + 1;
} else {
tmp[k++] = arr[i++];
}
}
// 处理两部分长度不等的情况
while(i <= m) {
tmp[k++] = arr[i++];
}
while(j <= r) {
tmp[k++] = arr[j++];
}
for(int i = l; i <= r; i++) {
arr[i] = tmp[i];
}
return cnt;
}
int n;
int main() {
scanf("%d", &n);
for(int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
printf("%d ", msort(0, n - 1));
return 0;
}
关于sort函数的使用
在进行实际问题排序时,如 学生考试成绩,这类有多组数据的排序。可以使用结构体加sort函数进行排序。
先定义排序规则
bool cmp(a,b){
return a>b;
}
使用sort排序
sort(n,n+5,cmp)//n+5为排序的个数