全排序(All Rangled)

全排序:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。当m=n时所有的排列情况叫全排列


如1,2,3三个元素的全排列为:

1,2,3
1,3,2
2,1,3
2,3,1
3,1,2
3,2,1
共3*2*1=6种

公式:全排列数f(n)=n!(定义0!=1)


一 全排序递归实现(不去掉重复情况)

// AllRange.cpp : 定义控制台应用程序的入口点。
//全排序——递归
//全排序——不考虑重复情况
#include "stdafx.h"
#include <iostream>
using namespace std;

template<class T>
void AllRangle(T data[], int arrsize, int key = 0)
{
	if (key == arrsize)
	{
		Sprint(data, arrsize);
	}

	for (int i = key; i < arrsize; i++)
	{
		swap(data[key], data[i]);
		AllRangle(data, arrsize, key + 1);
		swap(data[key], data[i]);
	}
}

template<class T>
void Sprint(T data[], int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << data[i] << " ";
	}

	cout << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int data[] = { 0, 1, 2, 3 };
	int n = sizeof(data) / sizeof(int);
	AllRangle(data, n);
	Sprint(data, n);
	return 0;
}

结果:



二 全排序递归实现(去掉重复情况)

//递归
//全排序——考虑重复情况
#include "stdafx.h"
#include <iostream>
using namespace std;

//在pszStr数组中,[nBegin,nEnd)中是否有数字与下标为nEnd的数字相等  
template<class T>
bool IsSwap(T data[], int nBegin, int nEnd)
{
	for (int i = nBegin; i < nEnd; i++)
	if (data[i] == data[nEnd])
		return false;
	return true;
}

template<class T>
void AllRangle(T data[], int arrsize, int key = 0)
{
	if (key == arrsize)
	{
		Sprint(data, arrsize);
	}

	for (int i = key; i < arrsize; i++)
	{
		if (IsSwap(data, key, i))
		{
			swap(data[key], data[i]);
			AllRangle(data, arrsize, key + 1);
			swap(data[key], data[i]);
		}
	}
}

template<class T>
void Sprint(T data[], int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << data[i] << " ";
	}

	cout << endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
	char data[] = { '2', '1', '2' };
	int n = sizeof(data) / sizeof(char);
	AllRangle(data, n);
	//Sprint(data, n);
	return 0;
}



三 全排序非递归实现(去掉重复情况)

思路:给出一个数求出它的下一个数一直重复这个过程

分析:对于一串数字(字符串)将它由组合成最小数一直到组合成最大的数即为整个全排序过程

实现过程:

(1)例如235864 下一个数字为 236458,也就是5864 -> 6458

(2)将数字235864由后往前扫描当data[i] < data[i+1]说明此事 i 这个位置上的数字需要被别的数字取代

(3)在864中找到一个最小大于5的数,由于864为降序data[i]>data[j](j = length - 1, j--)需要交换的数为6,交换data[i]与data[j]( swap(data[i], data[j]) )

(4)后3位854进行倒转458,结果是236458

(5)重复上述过程直到下一个数字不存在为止


实例代码

#include "stdafx.h"
#include <iostream>
using namespace std;

template<class T>
void Reverse(T data[], int low, int hight)
{
	for (; low < hight; low++, hight--)
	{
		swap(data[low], data[hight]);
	}
}

template<class T>
void AllRangle(T data[], int length)
{
	if (length < 2)
		return;

	int i, j;
	while (true)
	{
		Sprint(data, length);

		for (i = length - 2; i >= 0; i--)
		{
			if (data[i] < data[i + 1])
				break;
			else if (i == 0)
				return;
		}

		for (j = length - 1; j > i; j--)
		{
			if (data[j] > data[i])
				break;
		}

		swap(data[i], data[j]);
		Reverse(data, i + 1, length - 1);
	}
}

template<class T>
void Sprint(T data[], int n)
{
	for (int i = 0; i < n; i++)
	{
		cout << data[i] << " ";
	}

	cout << endl;
}

int main(int argc, char **argv)
{
	int data[] = { 1, 2, 3 };
	int length = sizeof(data) / sizeof(int);

	//打印不小于data(123)的所有数
	AllRangle(data, length);
	return 0;
}
备注:若data不是升序需要对data进行升序排序


结果:

int data[] = { 1, 2, 3 }




int data[] = { 1, 2, 2 }










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值