排序(一)
1.插入排序
插入算法的设计使用的是增量方法:在排好序的数组A[1..j-1]后,将元素A[j]插入,形成排序好的子数组A[1..j],不满足的元素往后平移。
插入排序的效率是O(n^2)
c++实现:
void insertsort(int *a,int length){
int key,i,j;
for(j=1;j<length;++j){
key=a[j];
i=j-1;
while(i>=0&&a[i]>key){
a[i+1]=a[i];
--i;
}
a[i+1]=key;
}
}
2,分治法-合并排序
分治策略基本思想:将原问题划分成n个规模较小而结构与原问题相似的子问题,递归的解决这些字问题,然后在合并其结果,就得到原问题的解。
分治模式在每一层递归上都有三个步骤:
分解 ——解决——合并
时间复杂度:O(nlgn)
c++实现:
/* 分治排序算法 p代表排序数组的开始下标 q排序数组的中间下标 r排序数组的结束下标 */ #include<iostream> using namespace std; void merge(int A[],int p,int q,int r){ int n1=q-p+1; int n2=r-q; int i,j; int *L=new int[n1]; int *R=new int[n2]; for(i=0;i<n1;++i)L[i]=A[p+i];//拆分数组 for(j=0;j<n2;++j)R[j]=A[q+j+1]; //排序 int m=0; int n=0; for(i=p;i<=r;++i){//包含A[r] if(m<n1&&n<n2){ A[i]=L[m]<R[n]?L[m++]:R[n++];//巧妙的写法 } else{ if(m<n1){ A[i]=L[m++]; } else{ A[i]=R[n++]; } } } delete []L;//删除开辟的数组 delete []R; } void mergesort(int A[],int p,int r){ int q; if(p<r){ q=(p+r)/2; mergesort(A,p,q); mergesort(A,q+1,r); merge(A,p,q,r); } } void main(){ int i; int a[]={5,2,4,7,1,3,6,2}; int total=sizeof(a)/sizeof(int); cout<<"排序前:"; for(i=0;i<total;++i)cout<<a[i]<<" "; cout<<endl; mergesort(a,0,total-1); cout<<"排序后:"; for(i=0;i<total;++i)cout<<a[i]<<" "; cout<<endl; }
3,利用合并排序求任意序列的逆序对
求合并两个子序列时,出现右边元素小于左边元素的情况,亦即R[j]<L[i]时,出现逆序对。此时L[i+1...n1]里面的元素均比R[j]大,而R[j]又在它们的右边。所以,逆序对数:
n1-i.后面的元素以此类推。
代码实现:
/* 求任意排列的逆序对 */ #include<iostream> using namespace std; //const int M=9999; int count=0; void nixu(int A[],int p,int q,int r){ int i,j; int n1=q-p+1; int n2=r-q; int *L=new int[n1+1]; int *R=new int[n2+1]; //将数组分开 for(i=0;i<n1;++i)L[i]=A[p+i]; for(j=0;j<n2;++j)R[j]=A[q+1+j]; L[n1]=100;//底部存放“哨兵”,避免比较式判空,很巧 R[n2]=100; int n=0; int m=0; for(int k=p;k<=r;++k){ if(L[n]<=R[m]){ A[k]=L[n++]; } else{ count+=n1-n;//全局变量总计逆序对的个数 A[k]=R[m++]; } } delete []L; delete []R; } void mergesort(int A[],int p, int r){ int q; if(p<r){ q=(p+r)/2; mergesort(A,p,q); mergesort(A,q+1,r); nixu(A,p,q,r); } } void main(){ int a[]={2,3,8,6,1}; cout<<"the count of the reverse is: "; int total=sizeof(a)/sizeof(int); mergesort(a,0,total-1); cout<<count<<endl; }
4,冒泡排序和选择排序
选择排序和冒泡排序都是从当前位置i的后面所有数中选择一个最小的一个数,交换到i位置中,但是选择排序只需要交换一次,冒泡排序可能会交换多次,速度应该是选择排序更快。。时间复杂度都是O(n^2)
5,霍纳规则用于计算多项式
#include<iostream> using namespace std; int huona(int A[],int length,int x){ int y=0; int i=length-1; while(i>=0){ y=A[i]+x*y; --i; } return y; } void main(){ int x,i; int a[]={12,2,3}; int total=sizeof(a)/sizeof(int); cout<<"要计算的多项式系数从低次幂到高次幂分别是:"; for(i=0;i<total;++i){ cout<<a[i]<<" "; } cout<<endl; cout<<"未知数x的值为:"; cin>>x; cout<<"计算得到的多项式的值为:"; int sum=huona(a,total,x); cout<<sum<<endl; }