您的位置:首页 > 其它

【自写】【求全排列】【新算法】【递归实现】

2010-10-19 02:07 344 查看
算法思想从根本上区别于网 上的诸多方法,思想基于把用来存储一组数形成的所有序列的二维数组看成一个表(每个排列都是竖着放的,看着顺眼)。而使用递归进行了类似于把表从上到下一行一行的填满,有几个数就有几层递归(每层有多个递归)。这次关键一个递归函数(只有30左右行),但从构思到写代码到调试完成,花了将近一天半。还是纸上打稿,在写代码,最关键就在于画图了,根据图来写代码。

举例:当一组数为4个是(1,2,3,4)总排列数为(4*3*2*1)

分别以1,2,3,4开头的序列各为6个(也就是以相同的一个数开头的有3*2*1个)

所以第一行分别连需填6个1,6个2,6个3,6个4;

而以1开头的,它的下一行往后相当于(对除1以外的其他数(2,3,4)的所有排列(用递归了));

以2开头。。。。。。。。。。。。。。。。。。。。。。。(1,3,4)。。。。。。。。。。。。;

以3开头。。。。。。。。。。。。。。。。。。。。。。。(1,2,4)。。。。。。。。。。。。;

以4开头。。。。。。。。。。。。。。。。。。。。。。。(1,3,2)。。。。。。。。。。。。;

就这样从上往下一行一行地填表;

普遍性:当一组数为n个(a1,a2,a3...........an)总排列数为an*......*a3*a2*a1;

分别以a1,a2,a3,.....an开头的序列各有(an-1*..........a3*a2*a1)(也就是总排列数除以数的总数)

。.....。。。。。。。。。。。。。。。。。。。

此时的二维数组为【n】【总排列数】;看成表格进行填表;一层一层的填;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
// Console.WriteLine("zhangbilei");
Console.Write("输入要排列的一组数的个数:");
int item_num = int.Parse(Console.ReadLine());
int PaiLie_num = 1;//所有排列的总数
for(int i=1;i<=item_num;i++)
PaiLie_num*=i;
Console.WriteLine(item_num);
Console.WriteLine(PaiLie_num);

int[] item = new int[item_num];//用来存要排列的一组数
int[,] XuLie = new int[item_num, PaiLie_num];//用来存所有的排列(竖着放)

// Console.WriteLine(x);
Console.WriteLine("输入要排列的所有数,每输入一个数按回车确认:");
for (int i = 0; i < item_num; i++)
{
int a = int.Parse(Console.ReadLine());
item[i] = a;
}
Console.WriteLine("---------------------------");

for (int i = 0; i < item_num; i++)
{
// int a = int.Parse(Console.ReadLine());
Console.WriteLine(item[i]);
}

// int[] item = new int[4] { 1, 2, 4, 4};
// int[,] XuLie = new int[4, 24];
QiongJu(XuLie, 0, 0, item);//进行重复的排列

/* int[] a = new int[5] { 1, 2, 3, 4, 5 };
int[] b = new int[4];
NewArray(a, b, 4);
for (int i = 0; i < 4; i++)
{
Console.WriteLine(b[i]);
}
*/
// bool Insert==false;
int[,] N_XuLie = new int[item_num, PaiLie_num];//将重复的排列删了,剩下的都存入这个新数组中;
int x_count=0;//上面新数组存的数的个数
///////////////////////////////////////////////////////
///////////
///////////以下的循环执行删除并存放的操作,画个图比较容易看懂
///////////////////////////////////////////////////////////////////////////////////////////////////
for (int i = 0; i < PaiLie_num-1; i++)
{
bool Insert = true;
for (int j = i+1 ; j < PaiLie_num; j++)
{
int Flag = 0;
for (int k = 0; k < item_num; k++)
{

if (XuLie[k,i] == XuLie[k, j])
{
Flag++;

}
}
if (Flag == item_num)
{
Insert = false;
//Console.WriteLine("Insert");
break;
}

}
if (Insert == true)
{
for (int l = 0; l < item_num; l++)
{
N_XuLie[l, x_count] = XuLie[l, i];
}
x_count++;
}
if (i ==PaiLie_num-2 )
{
for (int l = 0; l < item_num; l++)
{
N_XuLie[l, x_count] = XuLie[l, i + 1];
}
x_count++;
}

}

for (int a = 0; a < x_count; a++)
{
for (int b = 0; b < item_num; b++)
Console.Write(N_XuLie[b, a]);
Console.WriteLine();
}
// test(XuLie, 4, 24);
//Console.WriteLine("zhangbilei");
Console.ReadLine();
}
///////////////////////////////////////
/////////将Array看成一个横向(列数为X),竖向(行数为Y);利用递归进行类似于填表的操作
/////////对数组Array的每一行进行填数,数组的每一列为一个序列,行数为总序列数目
//////y_start用来记录要填充的当前行,
//////
/////////
static void QiongJu(int[,] Array, int y_start, int x_start, int[] item)
{
if (item.Length > 0)
{
int item_num = item.Length;
int XuLie_num = 1;//在item数组中的数能组成的序列的总数
for (int i = 1; i <= item_num; i++)
XuLie_num *= i;

int TongItem_num = XuLie_num / item_num;//每一层中相同的数的个数
int x_index = x_start;
// int y_index = y_start;
/////////////////////
///////循环实现对数组Array的每一层进行填数
///////y_start用于保持当前行的输入
///////y_index用于当前行中相同数进入下一行中,相同数进入下一行后使用递归(用y_index做为参数)
///////
/////////////////////////////////////////////////////////////////////////////
for (int a = 0; a < item_num; a++)//外循环:用于保证当前行的输入
{
int y_index = y_start;/// ///进入每一个外循环y_index重置为y_start
for (int b = 0; b < TongItem_num; b++)//内循环:当前行的输入(数组item中一共有item_num个数,数组Array中每行中每个数就有TongItem_num个)
{
Array[y_start, x_index] = item[a];
x_index++;
}
/////////////////////
///////以下作用:当前行中相同数进入下一层使用递归,y_index用于递归(区别于y_start,相当于进入递归后作为y_start)
/////////////////////
int new_num = item_num - 1;
if (new_num > 0)
{
int[] sub_item = new int[new_num];
NewArray(item, sub_item, a);
y_index++;
QiongJu(Array, y_index, x_start, sub_item);///////当前相同数进入下一行进行递归
x_start = x_index;////x_start改为本行中下一个相同数进入下一行的递归的水平起点
}
}
}

}
/// ////// ///
/// /// ///
/// /// ///将Old数组中下标不为deleted_index的数存入数组New中;
/// /// ////// ///
///

static void NewArray(int[] Old, int[] New, int delete_index)
{
int index = 0;
for (int i = 0; i < Old.Length; i++)
{
if (i != delete_index)
{
New[index] = Old[i];
index++;
}
}

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: