1.按名次排序。思路先将数组中的元素的序号求出并储存在一个数组中,再创建一个数组将目标数组的元素按序号储存到该数组中,再将该数组复制到目标数组中,最后删除该数组。
复杂度需要n*(n-1)/2次比较和2n次移动所以时间复杂度为O(n^2)
代码如下:
//1.计数排序 复杂度需要n*(n-1)/2次比较和2n次移动
void ranks(int a[],int n, int r[]){//r【i】中存的是第i元素的大小在第r【i】
for(int i=0;i<n;i++){
r[i] = 0;
}
//比较所有元素得到序号
for(int i=0;i<n-1;i++){
for(int j=i+1;j<n;j++){
if(a[j]>=a[i])//!!!确保有序性
{
r[j]++;
} else{
r[i]++;
}
}
}
}
void ranksort(int a[],int n,int r[]){
int *u = new int[n];
for(int i=0;i<n;i++){
// u[i] = a[r[i]];错误的想法
u[r[i]] = a[i];
}
for(int i=0;i<n;i++){
a[i] = u[i];
}
delete [] u;
}
2.选择排序法。思路将整体分为有序和无序两部分,每次比出最大的放到有序的集合中,直至无序集长度为一。
复杂度需要n*(n-1)/2次比较和3*(n-1)次比较。所以时间的复杂度为:O(n2)
代码如下:
//2.选择排序法 复杂度需要n*(n-1)/2次比较和3*(n-1)次比较。
int indexOfMax(int a[],int n) {//寻找最大值
if(n>0){
int indexOfMax = 0;
for(int i=0;i<n;i++){
if(a[indexOfMax]<a[i]){
indexOfMax = i;
}
}
return indexOfMax;
} else{
throw ;
}
}
void selectionSort(int a[],int n){
for(int i=n-1;i>0;i--){
int j = indexOfMax(a,i+1);//i+1控制有效数组的长度
swap(a[i],a[j]);//swap()方法相当于移动了(赋值了)三次
}
}
3.冒泡排序法。每个相邻的比较将最大的“冒”到最后,每次“冒出”一个元素,直至长度为一。
复杂度:需要n*(n-1)/2次比较和n*(n-1)/2次交换。所以时间复杂度为:O(n2)
代码如下:
//3.冒泡排序法 复杂度:需要n*(n-1)/2次比较和n*(n-1)/2次交换
void bubbleSort(int a[],int n){
for(int i=1;i<n;i++){//控制进行冒泡的次数,冒n-1次
for(int j=0;j<n-i;j++){
if(a[j+1]<a[j]) swap(a[j],a[j+1]);
}
}
}
4.插入排序法。原理:将一个元素插入到一个有序集合的正确位置中,将第二个元素起依次添加到左边有序的集合中。
两种插入排序的比较次数相同,最好是n-1次,最坏是(n-1)*n/2次。所以时间复杂度为:O(n^2)
代码如下:
//4.插入排序法 两种插入排序的比较次数相同,最好是n-1次,最坏是(n-1)*n/2次。
void insert(int a[],int n,const int x ){
int i = 0;
for(i=n-1;i>=0&&x<a[i];i--) a[i+1] = a[i];//凡是比x大的就右移一格!!!重要的一点数组的长度必须大于n
a[i+1] = x;
}
void insertSort(int a[],int n){
for(int i=1;i<n;i++){
int t = a[i];
insert(a,i,t);//将右边的元素逐渐插入到左边有序的序列中
}
}
所以综上所述四种排序方法的时间复杂度均为:O(n^2)