1. 程式人生 > >氣泡排序中交換次數與比較次數

氣泡排序中交換次數與比較次數

氣泡排序的過程中每次交換就是消除一個逆序對,而比較次數由其外層迴圈確定,因為內層是肯定迴圈至結束的。

用了歸併排序求逆序對,樹狀陣列求一個數的最大逆序對數。內部迴圈的次數為n-1,n-2.....n-m 數列求和。

程式碼如下,大家可以測試下。

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<ctime>
#define lowbit(x) (-x)&(x)
#define N 110
#define M 100
using namespace std;
int num[N];
int use[N];
int tmp[N];
int vis[N];
int sum[N];
int antinum;
void mergesort(int l,int r)//歸併排序求逆序數
{
    if(l>=r) return;
    int mid=(l+r)>>1;
    mergesort(l,mid);
    mergesort(mid+1,r);
    int st=l,mt=mid+1,k=l;
    while(st<=mid && mt<=r)
    {
        if(tmp[st]<=tmp[mt])
            use[k++]=tmp[st++];
        else
            use[k++]=tmp[mt++],antinum+=mid-st+1;
    }
    while(st<=mid)
        use[k++]=tmp[st++];
    while(mt<=r)
        use[k++]=tmp[mt++];
    while(l<=r)
        tmp[l]=use[l],l++;
}
void up(int n,int x)
{
    while(n<=M)
    {
        sum[n]+=x;
        n+=lowbit(n);
    }
}
int getsum(int n)
{
    int res=0;
    while(n>0)
    {
        res+=sum[n];
        n-=lowbit(n);
    }
    return res;
}
int main()
{
    srand( time(NULL) );
    antinum=0;
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=M;i++)
    {
        int x=rand()%M+1;
        if(vis[x]) {i--;continue;}
        vis[x]=1;
        num[i]=x,tmp[i]=x;
        cout<<x<<endl;
    }
    int antimax=0;
    for(int i=1;i<=M;i++)//樹狀陣列求一個數的最大逆序數對
    {
        antimax=max(antimax,i-getsum(num[i]-1));
        up(num[i],1);
    }
    mergesort(1,M);
    int m=antimax*(2*M-1-antimax)/2;
    int u=0,v=0;
    for(int i=1;i<M;i++)
    {
        int tag=1;
        for(int j=1;j<M-i+1;j++,v++)
            if(num[j]>num[j+1]) u++,swap(num[j],num[j+1]),tag=0;
        if(tag) break;
    }//正常的冒泡,以便比較結果 冒泡寫錯好幾次
    cout<<u<< " "<<v<<endl;
    cout<<antinum<<" "<< m<<endl;

    return 0;
}