冒泡排序的交换次数,即数组逆序对的求解

冒泡排序的交换次数,即数组中逆序对的求解
问题描述
--------------------------------------------------
给定一个数组A=[4,6,3,2,1],求其中逆序对的个数。
答案为:6个,分别是<4,3>,<4,2>,<4.1>,<6,3>,<6,2>,<6,1>。
--------------------------------------------------
分析
此类问题其实就是冒泡排序的次数求解问题,若采用冒泡排序统计交换次数,则答案很明朗,时间复杂度为O(N^2),对于较长的数组,可以考虑采用其他办法降低时间复杂度,归并排序是一种很好的解决办法,其时间复杂度为O(lNogN)。(PS:此类问题的解决方案的优化是建立在对数据结构知识的大量储备上的,换句话说,来自基础)。
归并排序俗称“分治”算法,采用“分而治之”的方法,每次将要解决的问题均分成前后两半,进行求解。

详细代码(c++):
#include <iostream>
#include <malloc.h>
using namespace std;
int MergeArray(int arry[],int start,int mid,int end,int temp[])
{
	//数组的归并操作
	int i=mid;
	int j=end;
    int k=0;//临时数组末尾坐标
    int count=0;
    //设定两个指针ij分别指向两段有序数组的头元素,将小的那一个放入到临时数组中去。
    while(i>=start&&j>mid){
        if(arry[i]>arry[j]){
            temp[k++]=arry[i--];//从临时数组的最后一个位置开始排序
            count+=j-mid;      
        }
        else
            temp[k++]=arry[j--];
    }
    while(i>=start)//表示前半段数组中还有元素未放入临时数组
	{
        temp[k++]=arry[i--];
    }
    while(j>mid){
        temp[k++]=arry[j--];
    }
    for(i=0;i<k;i++){
    	arry[end-i]=temp[i];//将临时数组中的元素写回到原数组当中去。
    }
    return count;
}
int InversePairsCore(int arry[],int start,int end,int temp[])
{
    int inversions = 0;  
    if(start<end){
        int mid=(start+end)/2;
        inversions+=InversePairsCore(arry,start,mid,temp);//找左半段的逆序对数目
        inversions+=InversePairsCore(arry,mid+1,end,temp);//找右半段的逆序对数目
        inversions+=MergeArray(arry,start,mid,end,temp);//找两段之间的逆序对。最小的逆序段只有一个元素
    }    
    return inversions;
}
int InversePairs(int arry[],int len)
{
    int *temp=new int[len];
    int count=InversePairsCore(arry,0,len-1,temp);
    delete[] temp;
    return count;
}
int main()
{
	int count,k,*arry;
    <span style="white-space:pre">	</span>while(cin>>k){
    	arry = (int *)malloc(k*sizeof(int));
    	for(int i=0;i<k;i++)
    		cin>>arry[i];
	    count=InversePairs(arry,k);
	   	cout<<count<<endl;
	   	free(arry);
    }
    return 0;
}



 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值