排序(一)

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;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2013-02-28 21:04  放空自己  阅读(175)  评论(0编辑  收藏  举报