按名次排序并原地重排

一个元素在序列当中的名次,例如{4,3,9,3,7},最左边出现的3 名次记成0,后面出现的3记1,从小到大从左到右可以将名次记为{2,0,4,1,3}。现在需要对于一组序列进行名次计算,并根据名次对于原序列重新进行排列。这次的方法使用的是原地重排法。

原地重排法介绍:i是循环变量,r[i]存放的是a[i]数组里面的名次,当i!=r[i]时,将r[i]与r[r[i]]交换,对应的a[i]也进行交换,当i=r[i]时,i++进入下一个。

i=0,1,2,3,4

r[i]=2,0,4,1,3

a[i]=4,3,9,3,7

重排1次时:

i=0,1,2,3,4

r[i]=4,0,2,1,3

a[i]=9,3,4,3,7

重排2次时:

i=0,1,2,3,4

r[i]=3,0,2,1,4

a[i]=7,3,4,3,9

重排3次时:

i=0,1,2,3,4

r[i]=1,0,2,3,4

a[i]=3,3,4,7,9

重排4次时:

i=0,1,2,3,4

r[i]=0,1,2,3,4

a[i]=3,3,4,7,9

然后遍历一遍正好满足所求。

具体见代码:

#include<iostream>
using namespace std;
template<class T>
void swap(T *a,T *b)         //交换
{
	T temp;
	temp=a;
	a=b;
	b=temp;
}
template<class T>
void rearrange(T a[],T r[],int n)     //原地重排法
{
	for(int i=0;i<n;i++)
		while(r[i]!=i)
		{
			swap(a[i],a[r[i]]);
			swap(r[i],r[r[i]]);
		}
}
template<class T>
void range(T a[],T r[],int n)
{
	for(int i=0;i<n;i++)
		r[i]=0;
	for(int i=0;i<n;i++)
		for(int j=0;j<i;j++)
			if(a[j]>a[i])r[j]++;
			else r[i]++;
}
int main()
{
	int a[ ]={'d','a','e','f','c','b'};
	int r[10];
	range(a,r,6);
	for(int i=0;i<6;i++)
		cout<<r[i];
	cout<<'\n';
	rearrange(a,r,5);
	for(int i=0;i<6;i++)
		printf("%c",a[i]);
	system("pause");
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_36631272/article/details/80180186