冒泡排序中交换次数与比较次数

本文探讨冒泡排序算法在排序过程中交换次数与比较次数的关系。通过使用归并排序计算逆序对,并利用树状数组求解最大逆序对数。算法实现包括对外层循环和内层循环次数的详细分析,代码可供测试验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

冒泡排序的过程中每次交换就是消除一个逆序对,而比较次数由其外层循环确定,因为内层是肯定循环至结束的。

用了归并排序求逆序对,树状数组求一个数的最大逆序对数。内部循环的次数为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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值