求组合的算法

cxjddd 2004-05-10 03:41:04
下面是代码,详细文章有时间再写。经过我的简单测试,应该很稳定了吧:)
可怜的我五一大半就给这东西给郁闷了:(

简单说明:
next_combination:求下一个更大的组合。返回值:true 如果输入组合不是“值”最大的组合。
prev_combination:求下一个更小的组合。返回值:true 如果输入组合不是“值”最小的组合。

使用上面两个函数前,应该用 init_combination 或 adjust_combination 初始化。

#include <algorithm>

namespace benbear
{

using namespace std;

template <typename BiIterator>
void
sort_combination (BiIterator first, BiIterator last)
{
if (first == last)
return;

BiIterator i = first;
++i;
if (i == last)
return;

int n = 1;
int half = distance (first, last) / 2;
BiIterator middle = first;
advance (middle, half);
sort_combination (first, middle);
sort_combination (middle, last);
inplace_merge (first, middle, last);
}

template <typename BiIterator>
void
adjust_combination (BiIterator first, BiIterator middle, BiIterator last)
{
if ((first == middle) || (middle == last))
return;

sort_combination (first, middle);
sort_combination (middle, last);

BiIterator b = middle;
--b;
BiIterator j = lower_bound (middle, last, *b);
reverse (j, last);
reverse (middle, last);
}

template <typename BiIterator>
void
init_combination (BiIterator first, BiIterator middle, BiIterator last,
bool next)
{
sort_combination (first, last);

if (next == false)
{
reverse (first, last);
reverse (first, middle);
}
}

template <typename BiIterator>
bool
next_combination (BiIterator first, BiIterator middle, BiIterator last)
{
if ((first == middle) || (middle == last))
return false;

BiIterator b = middle;
--b;

if (*b < *middle)
{
BiIterator j = b;
while ((++b != last) && (*j < *b))
{
iter_swap (j, b);
j = b;
}
return true;
}

BiIterator e = last;
--e;
while (e != middle)
{
BiIterator k = e;
--k;
if (!(*k < *e))
e = k;
else
break;
}

BiIterator f = e;
++f;
while ((f != last) && !(*f < *e))
++f;

if (!(*first < *e))
{
reverse (first, middle);
reverse (first, last);
return false;
}

if (*b < *e)
{
BiIterator bb = b;
while ((++bb != e) && !(*b < *bb))
;
reverse (bb, f);
reverse (b, f);
}
else
{
BiIterator a = b;
while (!(*--a < *e))
;

BiIterator j = last;
while (!(*a < *--j))
;

iter_swap (a, j);
reverse (middle, j);
inplace_merge (++a, middle, j);
}
return true;
}

template <typename BiIterator>
bool
prev_combination (BiIterator first, BiIterator middle, BiIterator last)
{
if ((first == middle) || (middle == last))
return false;

BiIterator b = middle;
--b;

if (*middle < *b)
{
BiIterator i = upper_bound (first, middle, *middle);
if (i != b)
iter_swap (i, middle);
else
{
BiIterator s = middle;
while ((++s != last) && !(*s < *middle))
;
inplace_merge (b, middle, s);
}

return true;
}

BiIterator e = last;
--e;
while (e != middle)
{
BiIterator k = e;
--k;
if (!(*k < *e))
e = k;
else
break;
}

BiIterator f = e;
++f;
while ((f != last) && !(*f < *e))
++f;

if (!(*e < *b) && (f == last))
{
reverse (first, last);
reverse (first, middle);
return false;
}

BiIterator i = upper_bound (first, middle, *f);
if (i == b)
{
BiIterator s = f;
while ((++s != last) && !(*s < *f))
;

inplace_merge (b, f, s);
}
else
{
iter_swap (i, f);
reverse (++i, f);
reverse (i, middle);
}
return true;
}

} // end of namespace benbear


#include <iostream>
#include <cstdlib>
#include <vector>
using namespace std;

template <typename BiIterator>
void
show_array (BiIterator f, BiIterator m, BiIterator l)
{
while (f != m)
cout << *f++;
cout << " ";
while (f != l)
cout << *f++;
cout << endl;
}

template <typename BiIterator>
void
combi (BiIterator f, BiIterator m, BiIterator l, bool next)
{
benbear::init_combination (f, m, l, next);
int c = 0;
cout << endl;
do
{
show_array (f, m, l);
c++;
}
while (next ? benbear::next_combination (f, m, l)
: benbear::prev_combination (f, m, l));
cout << "The end: ";
show_array (f, m, l);
cout << "There's: " << c << endl;
}

int
main ()
{
int a[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
bool dir = true;

for (int i = 1; i < 10; i++)
{
random_shuffle (a, a+7);
sort (a, a+3);
benbear::adjust_combination (a, a+3, a+7);
show_array (a, a+3, a+7);
}
system ("Pause");


for (int i = 1, j = 9; i < j; i++)
{
combi (a, a+i, a+j, dir);
system ("Pause");
}

sort (a, a+9);
benbear::sort_combination (a, a+7);
a[1] = 1;
a[4] = 6;
//a[6] = 6;
for (int i = 1, j = 7; i < j; i++)
{
combi (a, a+i, a+j, dir);
system ("Pause");
}

int n;
cout << "The n: ";
cin >> n;
vector<int> vec(n);
cout << "please. input numbers: " << endl;
for (int i = 0; i < n; i++)
cin >> vec[i];

for (int i = 1; i < n; i++)
{
combi (vec.begin(), vec.begin()+i, vec.end(), dir);
system ("Pause");
}


system ("Pause");
return 0;
}
...全文
65 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
cxjddd 2004-05-10
  • 打赏
  • 举报
回复
部分运算结果:
12345678 9
12345679 8
12345689 7
12345789 6
12346789 5
12356789 4
12456789 3
13456789 2
23456789 1
The end: 12345678 9
There's: 9
请按任意键继续. . .

1 134667
3 466711
4 667311
6 674311
7 664311
The end: 1 134667
There's: 5
请按任意键继续. . .

11 34667
13 46671
14 66731
16 67431
17 66431
34 66711
36 67411
37 66411
46 67311
47 66311
66 74311
67 64311
The end: 11 34667
There's: 12
请按任意键继续. . .
RookieStar 2004-05-10
  • 打赏
  • 举报
回复
好东西,顶一下,慢慢看。

24,854

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 工具平台和程序库
社区管理员
  • 工具平台和程序库社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧