排序(一)

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;

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(排序)