排序算法C++实现

来源:互联网 发布:网络调试助手apk 编辑:程序博客网 时间:2024/05/13 16:05

整理一下排序算法。

首先一个数组,A={x1,x2,x3......xN},我们先要从大到小经行排序

1.按照人们最直观的思想,应该是一次次的遍历,每次从里面取最大的一个,放到另一个数组里面,这就是简单选择排序。

2.我们从第一个值开始,跟其后面的值对比,如果后面的大,则与后面的交换。那么每一次的结果就是最小被放到了最后,接着是第二小的呗放到了倒数第二,依次类推。经过N此之后,变为一个有序数组,这就是冒泡排序。

3.我们新建一个数组B,刚开始B的大小是0,我们依次从A中取出一个数,放入B中。放的规则是,从B的第一个到已有的最后一个元素,一个个与A中取出的数比较,直到B中某个数小于取出的数,我们就把取出的数放在其前面。也就是我们有序地用A去构造B,最后得到一个有序数组B。这就是直接插入排序。

4.两路合并排序。两路合并排序牵扯到分治算法的思想。我们先把一个大的数组A,分为两个小数组,先把两个小数组有序后,再把两个小数组合并为大的有序数组。相应的,这两个小数组也可以用这种思想继续细分下去,知道只有一个元素。两路合并排序最后的方法就是,两两合并为大数组,再递归两两合并,最后合并为有序数组B。

5.快速排序。快速排序也是一个分治思想的排序算法,先取一个元素作为key,按照这个key,把原数组分为大于key的,和小于key的。然后作为两个小数组,继续这样划分,直到只有一个元素为止。

上面简单介绍了5中排序算法的基本思想,接下来编程实现,并计算其时间复杂度。

1.简短选择:

#include<iostream>using namespace std;void swap(int &a,int &b){a=a+b;b=a-b;a=a-b;}void f(int A[],int N)//简单选择{for(int i=N-1;i>=0;i--){int MAX=A[0];int key=0;for(int j=0;j<=i;j++){if(A[j]>MAX){MAX=A[j];key=j;}}if(i!=key)swap(A[i],A[key]);}for(int i=0;i<N;i++)cout<<A[i]<<' ';cout<<endl;}int main(){const int N=10;int A[N]={2,7,14,96,3,56,23,46,76,88};f(A,N);system("pause");return 0;}

2.冒泡

#include<iostream>using namespace std;void swap(int &a,int &b){a=a+b;b=a-b;a=a-b;}void f(int A[],int N)//冒泡{for(int i=N-1;i>=0;i--)for(int j=0;j<=i-1;j++){if(A[j]>A[j+1])swap(A[j],A[j+1]);}for(int i=0;i<N;i++)cout<<A[i]<<' ';cout<<endl;}int main(){const int N=10;int A[N]={2,7,14,96,3,56,23,46,76,88};f(A,N);system("pause");return 0;}


3.直接插入:

#include<iostream>using namespace std;void swap(int &a,int &b){a=a+b;b=a-b;a=a-b;}void f(int A[],int N)//冒泡{int i,j,k;for(i=1;i<N;i++){for(j=i-1;j>=0;j--){if(A[j]<A[i])break;}if(j!=i-1){int temp=A[i];for(k=i;k>=j+2;k--){A[k]=A[k-1];}A[j+1]=temp;}}for(int i=0;i<N;i++)cout<<A[i]<<' ';cout<<endl;}int main(){const int N=10;int A[N]={2,7,14,96,3,56,23,46,76,88};f(A,N);system("pause");return 0;}

4.两路合并排序:

#include<iostream>using namespace std;void marge(int m,int temp,int n,int A[]){int B[10];int i,j,k;j=m,k=temp+1;for(i=0;i<n-m+1;i++){if(j>temp||k>n)break;if(A[j]<=A[k]){B[i]=A[j];j++;}else{B[i]=A[k];k++;}}if(j>temp&&k<=n){int temp2=k;while(i<=n-m){B[i]=A[temp2];i++;temp2++;}}if(j<=temp&&k>n){int temp2=j;while(i<=n-m){B[i]=A[temp2];i++;temp2++;}}for(i=0;i<n-m+1;i++)A[m+i]=B[i];return ;}void f(int A[],int m,int n)//两路合并{if(m==n)return ;int temp=(m+n)/2;f(A,m,temp);f(A,temp+1,n);marge(m,temp,n,A);return ;}int main(){const int N=10;int A[N]={2,7,14,96,3,56,23,46,76,88};f(A,0,N-1);for(int i=0;i<N;i++)cout<<A[i]<<" ";cout<<endl;system("pause");return 0;}

5.快速排序:

#include<iostream>using namespace std;#define MAX 999999;void swap(int &a,int &b){int temp=a;a=b;b=temp;return ;}void f(int A[],int m,int n)//快速排序{if(m==n)return ;int i=m,j=n+1;int temp=A[n+1];A[n+1]=MAX;int key=m;do{do{i++;}while(A[i]<=A[key]);do{j--;}while(A[j]>A[key]);if(i<j)swap(A[i],A[j]);}while(i<j);swap(A[j],A[key]);A[n+1]=temp;if(j-1>m)f(A,m,j-1);if(i<n)f(A,i,n);return ;}int main(){const int N=10;int A[N]={2,7,14,96,3,56,23,46,76,88};f(A,0,N-1);for(int i=0;i<N;i++)cout<<A[i]<<" ";cout<<endl;system("pause");return 0;}

接着讨论上面5个排序算法的时间复杂度:

1.简单选择:每次遍历一遍,假设每次对比一半搜索到最小值,遍历次数为(n+n-1+n-2+n-3.....+2+1)/2=(n+1)n/4,则时间复杂度为O(N^2);

2.冒泡排序:假设每次交换一半的个数,则交换次数为(n+n-1+n-2....+1)/2=(n+1)n/4,时间复杂度也是O(N^2);

3.直接插入排序:还是假设插入一次对比一半,(n+n-1+n-2...1)/2,再加上移动元素时间,每次移动也是一半(n+n-1+n-2...1)/2,则最后的时间复杂度为两者相加,为(n+1)n/2,时间复杂度为O(N^2);

4.两路合并排序:递归次数为logN,每次两个子序列并在一起时间最多为两路长度之和,2*L,而L的平均值为N/4,那么合并的时间平均为N/2,那么最后的总时间为(N/2)logN,也就是O(NlogN)

5.快速排序:类似于两路合并,递归次数大概为logN,分裂子序列时间为N/2,于是时间复杂度为O(NlogN);

PS:上述程序为一个上午所写,图快,没有优化代码。有时间在回来重新写过,优化各个算法。


原创粉丝点击