排列组合是高中是学到的 知识,理论上很清楚,但如何使用代码实现,却一直没有尝试过,近段时间由于项目需要,写一个组合的算法,想不到却花费了不少时间。
需求很简单,就是典型的组合应用。
例如输入:C0,C1,C2,C3,C4,输出C0,C1,C2,C3,C4的所有组合。
由于输入数据的个数不确定,自然不能使用一般的循环,只能使用递归加循环。
经过不断的实验的和测试,发现有两种实现方法,
1根据组合长度的输出,例如对于输入C0,C1,C2,C3,C4的五个元素,先输出,一个元素的所有组合,再输出两个元素的所有组合,一次类推,直到所有元素的组合都输出完成。
具体实现代码:
public static void CreatSumData2(List<string> columnNameList)
{
string res = "";
// 一个元素
for (int i = 0; i < columnNameList.Count; i++)//
{
string name = columnNameList[i];
List<string> listContion = new List<string>();
listContion.Add(name);
res += OutPutData(listContion);
listContion.Clear();
}
//两个以上元素
int length = 2;
int max = columnNameList.Count;//组合的最大元素个数
while (length <= max)//一直循环到所有元素的组合,每一次循环,处理某一个长度的组合
{
for (int i = 0; i <= columnNameList.Count - length + 1; i++)//
{
string name = columnNameList[i];
int currentlLvel = i + 1;
List<string> hasAddNameList = new List<string>();//保存已添加的元素
hasAddNameList.Add(name);
res += addOneContion(hasAddNameList, columnNameList, currentlLvel, length);
hasAddNameList.Clear();//清空元素
}
length++;
}
WrieData(res);
}
/// <summary>
/// 添加一个元素
/// </summary>
/// <param name="hasAddNameList">已添加的元素</param>
/// <param name="columnNameList">所有可能的元素</param>
/// <param name="currentlLvel"></param>
/// <param name="currentMaxLength">添加的元素的最大个数</param>
/// <returns></returns>
private static string addOneContion(List<string> hasAddNameList, List<string> columnNameList, int currentlLvel, int currentMaxLength)
{
string res = "";
bool hasAddOutNames = false;
int currentlLvelInner = currentlLvel;
if (hasAddNameList.Count == currentMaxLength)
{
res += OutPutData(hasAddNameList);
hasAddNameList.Clear();
return res;
}
List<string> hasAddNameListInner = new List<string>();
for (int i = currentlLvelInner; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
currentlLvelInner++;
if (!hasAddOutNames)
{
hasAddNameListInner.AddRange(hasAddNameList);
hasAddOutNames = true;
}
hasAddNameListInner.Add(colunmname);
if (hasAddNameListInner.Count == currentMaxLength)
{
res += OutPutData(hasAddNameListInner);
hasAddNameListInner.Clear();
hasAddOutNames = false;
}
else
{
res += addOneContion(hasAddNameListInner, columnNameList, currentlLvelInner, currentMaxLength);
hasAddNameListInner.Clear();
hasAddOutNames = false;
}
}
return res;
}
改进版:
public static void CreatSumData22(List<string> columnNameList)
{
string res = "";
// 一个元素
for (int i = 0; i < columnNameList.Count; i++)//
{
string name = columnNameList[i];
List<string> listContion = new List<string>();
res += OutPutData(listContion, name);
}
//两个以上元素
int length = 2;
int max = columnNameList.Count;//组合的最大元素个数
while (length <= max)//一直循环到所有元素的组合,每一次循环,处理某一个长度的组合
{
for (int i = 0; i <= columnNameList.Count - length + 1; i++)//
{
string name = columnNameList[i];
List<string> hasAddNameList = new List<string>();//保存已添加的元素
res += addOneContion(hasAddNameList, columnNameList, i + 1, length, name);
}
length++;
}
WrieData(res);
}
/// <summary>
/// 添加一个元素
/// </summary>
/// <param name="hasAddNameList">已添加的元素</param>
/// <param name="columnNameList">所有可能的元素</param>
/// <param name="startIndex"></param>
/// <param name="currentMaxLength">添加的元素的最大个数</param>
/// <returns></returns>
private static string addOneContion(List<string> hasAddNameList, List<string> columnNameList, int startIndex, int currentMaxLength,string parentName)
{
string res = "";
List<string> hasAddNameListInner = new List<string>();
hasAddNameListInner.AddRange(hasAddNameList);
hasAddNameListInner.Add(parentName);
for (int i = startIndex; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
if (hasAddNameListInner.Count + 1 == currentMaxLength)
{
res += OutPutData(hasAddNameListInner, colunmname);
}
else
{
res += addOneContion(hasAddNameListInner, columnNameList, i+1, currentMaxLength, colunmname);
}
}
return res;
}
private static string OutPutData(List<string> listold,string name)
{
List<string> listoldinner = new List<string>();
listoldinner.AddRange(listold);
listoldinner.Add(name);
return OutPutData(listoldinner);
}
2 根据元素的输出,例如对于输入C0,C1,C2,C3,C4的五个元素,先输出包含C0这个元素的所有组合,再输出包含C1但不包含C0的所有组合,一次类推,直到所有元素的组合都输出完成。
具体实现代码
public static void CreatSumData(List<string> columnNameList)
{
string res = "";
List<string> hasAddNameList = new List<string>();
for (int i = 0; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
int currentlLvel = i;
currentlLvel++;
hasAddNameList.Add(colunmname);
res += OutPutData(hasAddNameList);
res += CreatNextLevelData(hasAddNameList, columnNameList, currentlLvel);
hasAddNameList.Clear();
}
WrieData(res);
}
private static string CreatNextLevelData(List<string> hasAddNameList, List<string> columnNameList, int currentlLvel)
{
string res = "";
List<string> hasAddNameListInner = new List<string>();
bool hasAddOutNames = false;
int currentlLvelInner = currentlLvel;
for (int i = currentlLvelInner; i < columnNameList.Count; i++)//
{
if (!hasAddOutNames) {
hasAddNameListInner.AddRange(hasAddNameList);
}
string colunmname = columnNameList[i];
currentlLvelInner++;
hasAddNameListInner.Add(colunmname);
res += OutPutData(hasAddNameListInner);
res += CreatNextLevelData(hasAddNameListInner, columnNameList, currentlLvelInner);
hasAddOutNames = false;
hasAddNameListInner.Clear();
}
return res;
}
改进版
public static void CreatSumData1(List<string> columnNameList)
{
string res = "";
List<string> hasAddNameList = new List<string>();
for (int i = 0; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
res += OutPutData(hasAddNameList, colunmname);
res += CreatNextLevelData(hasAddNameList, columnNameList, i+1, colunmname);
}
WrieData(res);
}
private static string CreatNextLevelData(List<string> hasAddNameList, List<string> columnNameList, int startIndex, string parentcolumn)
{
string res = "";
List<string> hasAddNameListInner = new List<string>();
hasAddNameListInner.AddRange(hasAddNameList);
hasAddNameListInner.Add(parentcolumn);
for (int i = startIndex; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
res += OutPutData(hasAddNameListInner, colunmname);
res += CreatNextLevelData(hasAddNameListInner, columnNameList, i + 1, colunmname);
}
return res;
}
完整的代码:
#region 根据组合长度的输出
public static void CreatSumData2(List<string> columnNameList)
{
string res = "";
// 一个元素
for (int i = 0; i < columnNameList.Count; i++)//
{
string name = columnNameList[i];
List<string> listContion = new List<string>();
listContion.Add(name);
res += OutPutData(listContion);
listContion.Clear();
}
//两个以上元素
int length = 2;
int max = columnNameList.Count;//组合的最大元素个数
while (length <= max)//一直循环到所有元素的组合,每一次循环,处理某一个长度的组合
{
for (int i = 0; i <= columnNameList.Count - length + 1; i++)//
{
string name = columnNameList[i];
int currentlLvel = i + 1;
List<string> hasAddNameList = new List<string>();//保存已添加的元素
hasAddNameList.Add(name);
res += addOneContion(hasAddNameList, columnNameList, currentlLvel, length);
hasAddNameList.Clear();//清空元素
}
length++;
}
WrieData(res);
}
public static void CreatSumData22(List<string> columnNameList)
{
string res = "";
// 一个元素
for (int i = 0; i < columnNameList.Count; i++)//
{
string name = columnNameList[i];
List<string> listContion = new List<string>();
res += OutPutData(listContion, name);
}
//两个以上元素
int length = 2;
int max = columnNameList.Count;//组合的最大元素个数
while (length <= max)//一直循环到所有元素的组合,每一次循环,处理某一个长度的组合
{
for (int i = 0; i <= columnNameList.Count - length + 1; i++)//
{
string name = columnNameList[i];
List<string> hasAddNameList = new List<string>();//保存已添加的元素
res += addOneContion(hasAddNameList, columnNameList, i + 1, length, name);
}
length++;
}
WrieData(res);
}
/// <summary>
/// 添加一个元素
/// </summary>
/// <param name="hasAddNameList">已添加的元素</param>
/// <param name="columnNameList">所有可能的元素</param>
/// <param name="startIndex"></param>
/// <param name="currentMaxLength">添加的元素的最大个数</param>
/// <returns></returns>
private static string addOneContion(List<string> hasAddNameList, List<string> columnNameList, int startIndex, int currentMaxLength,string parentName)
{
string res = "";
List<string> hasAddNameListInner = new List<string>();
hasAddNameListInner.AddRange(hasAddNameList);
hasAddNameListInner.Add(parentName);
for (int i = startIndex; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
if (hasAddNameListInner.Count + 1 == currentMaxLength)
{
res += OutPutData(hasAddNameListInner, colunmname);
}
else
{
res += addOneContion(hasAddNameListInner, columnNameList, i+1, currentMaxLength, colunmname);
}
}
return res;
}
private static string OutPutData(List<string> listold,string name)
{
List<string> listoldinner = new List<string>();
listoldinner.AddRange(listold);
listoldinner.Add(name);
return OutPutData(listoldinner);
}
/// <summary>
/// 添加一个元素
/// </summary>
/// <param name="hasAddNameList">已添加的元素</param>
/// <param name="columnNameList">所有可能的元素</param>
/// <param name="currentlLvel"></param>
/// <param name="currentMaxLength">添加的元素的最大个数</param>
/// <returns></returns>
private static string addOneContion(List<string> hasAddNameList, List<string> columnNameList, int currentlLvel, int currentMaxLength)
{
string res = "";
bool hasAddOutNames = false;
int currentlLvelInner = currentlLvel;
if (hasAddNameList.Count == currentMaxLength)
{
res += OutPutData(hasAddNameList);
hasAddNameList.Clear();
return res;
}
List<string> hasAddNameListInner = new List<string>();
for (int i = currentlLvelInner; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
currentlLvelInner++;
if (!hasAddOutNames)
{
hasAddNameListInner.AddRange(hasAddNameList);
hasAddOutNames = true;
}
hasAddNameListInner.Add(colunmname);
if (hasAddNameListInner.Count == currentMaxLength)
{
res += OutPutData(hasAddNameListInner);
hasAddNameListInner.Clear();
hasAddOutNames = false;
}
else
{
res += addOneContion(hasAddNameListInner, columnNameList, currentlLvelInner, currentMaxLength);
hasAddNameListInner.Clear();
hasAddOutNames = false;
}
}
return res;
}
#endregion
#region 根据列输出
public static void CreatSumData(List<string> columnNameList)
{
string res = "";
List<string> hasAddNameList = new List<string>();
for (int i = 0; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
int currentlLvel = i;
currentlLvel++;
hasAddNameList.Add(colunmname);
res += OutPutData(hasAddNameList);
res += CreatNextLevelData(hasAddNameList, columnNameList, currentlLvel);
hasAddNameList.Clear();
}
WrieData(res);
}
public static void CreatSumData1(List<string> columnNameList)
{
string res = "";
List<string> hasAddNameList = new List<string>();
for (int i = 0; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
res += OutPutData(hasAddNameList, colunmname);
res += CreatNextLevelData(hasAddNameList, columnNameList, i+1, colunmname);
}
WrieData(res);
}
private static string CreatNextLevelData(List<string> hasAddNameList, List<string> columnNameList, int startIndex, string parentcolumn)
{
string res = "";
List<string> hasAddNameListInner = new List<string>();
hasAddNameListInner.AddRange(hasAddNameList);
hasAddNameListInner.Add(parentcolumn);
for (int i = startIndex; i < columnNameList.Count; i++)//
{
string colunmname = columnNameList[i];
res += OutPutData(hasAddNameListInner, colunmname);
res += CreatNextLevelData(hasAddNameListInner, columnNameList, i + 1, colunmname);
}
return res;
}
private static string CreatNextLevelData(List<string> hasAddNameList, List<string> columnNameList, int currentlLvel)
{
string res = "";
List<string> hasAddNameListInner = new List<string>();
bool hasAddOutNames = false;
int currentlLvelInner = currentlLvel;
for (int i = currentlLvelInner; i < columnNameList.Count; i++)//
{
if (!hasAddOutNames) {
hasAddNameListInner.AddRange(hasAddNameList);
}
string colunmname = columnNameList[i];
currentlLvelInner++;
hasAddNameListInner.Add(colunmname);
res += OutPutData(hasAddNameListInner);
res += CreatNextLevelData(hasAddNameListInner, columnNameList, currentlLvelInner);
hasAddOutNames = false;
hasAddNameListInner.Clear();
}
return res;
}
#endregion
private static string OutPutData(List<string> listold)
{
string text = "";
for (int i = 0; i < listold.Count; i++)
{
string item = listold[i];
text += "[\"" + item + "\"]";
}
return text + "\r\n";
}
private static void WrieData(string text)
{
string file = "ZuheTestout.js";
StreamWriter sr = new StreamWriter(file);
sr.WriteLine(text);
sr.Close();
}