分治法求解逆序数问题

// Sort_and_Count.cpp : 定义控制台应用程序的入口点。
//

#pragma once
#include "stdafx.h"
#include <fstream>
#include <vector>
#include <iostream>
#include <sstream>

using namespace std;

int fileLength = 10000;
int numbers[10000];//存储所有数据的数组
long int inversionCount=0;

void readData(char* filePath){
	ifstream fin;
	string line;
	int oneNumber;
	stringstream ss;

	fin.open(filePath);

	cout<<"开始读文件..."<<endl;
	int i=0;
	while(getline(fin,line)){
		ss<<line;
		ss>>oneNumber;
		ss.clear();
		numbers[i++] = oneNumber;
		//cout<<"i="<<i<<endl;
	}
	cout<<"读文件结束,i="<<i<<endl;

} 

void printArray(int left,int right){
	for(int i=left;i<=right;i++){
		cout<<numbers[i]<<",";
	}
	cout<<endl;
}

int quickSort(int arrayBegin,int arrayEnd){
	//cout<<arrayBegin<<","<<arrayEnd<<endl;

	if(arrayBegin>=arrayEnd){
		return 0;
	}else{
		

	int leftIndex = arrayBegin;
	int rightIndex = arrayEnd;

	int center = numbers[leftIndex];//选定最左端的元素作为中轴值
	int centerIndex = leftIndex;//中轴值的index

	while(leftIndex<rightIndex){

		//从后向前找,找到比中轴值小的元素,写到中轴位置处
		while(leftIndex<rightIndex&&numbers[rightIndex]>=center){
			rightIndex--;
		}
		
		if(leftIndex<rightIndex){//找到了
			numbers[centerIndex]=numbers[rightIndex];
			centerIndex = rightIndex;
			rightIndex--;
		}
		//从前向后找,找到比中轴值大的元素,写到中轴值位置处
		while(leftIndex<rightIndex&&numbers[leftIndex]<=center){
			leftIndex++;
		}

		if(leftIndex<rightIndex){//找到了
			numbers[centerIndex] = numbers[leftIndex];
			centerIndex=leftIndex;
			leftIndex++;
		}
	}
	numbers[centerIndex]=center;
	
	quickSort(arrayBegin,centerIndex-1);
	quickSort(centerIndex+1,arrayEnd);
	return 1;
}
}

void writeData(char * filePath){
	ofstream fout;
	stringstream ss;
	string s;

	fout.open(filePath);

	cout<<"开始写文件..."<<endl;
	for(int i=0;i<fileLength;i++){
		ss<<numbers[i];
		ss>>s;
		ss.clear();
		fout<<s<<endl;
	}
	cout<<"写文件结束"<<endl;

	}

	

int combine(int left,int right){
	if(left>=right){
		return 0;
	}
	int center = (right+left)/2;

	//两段数据分别进行排序
	quickSort(left,center);
	quickSort(center+1,right);

	
	int compareIndex=left;
	//遍历后半段数据,计算每个数的逆序数值
	for(int i = center+1;i<=right;i++){
		int value = numbers[i];
		while(compareIndex<=right&&numbers[compareIndex]<=value){
			compareIndex++;
		}
		if(compareIndex<=right){
			int temp = center-compareIndex+1;
			//cout<<value<<"的逆序数是:"<<temp<<endl;
			inversionCount = inversionCount+temp;
		}
	}
	return inversionCount;

}

//计算逆序数个数
int countInversion(int left,int right){
	if(left>=right){
		return 0;
	}else{
	//cout<<"left="<<left<<",right="<<right<<endl;
	int center = (right+left)/2;
	int n1 = countInversion(left,center);
	int n2 = countInversion(center+1,right);
	int n3 = combine(left,right);

	return n1+n2+n3;
	}
	
}


int _tmain(int argc, _TCHAR* argv[])
{
	readData("Q5.txt");
	cout<<"开始计算逆序数..."<<endl;
	//quickSort(0,fileLength-1);
	countInversion(0,fileLength-1);
	cout<<"结束逆序数计算,inversionCount="<<inversionCount<<endl;
	//writeData("result.txt");
	getchar();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值