从一个全组合算法想到的……

jackylingzeng jackylingzeng 墨衍会员 · AI 创作全网分发 墨衍智能分发 通过墨衍一键同步至各平台 可同步平台 CSDN微信公众号微博知乎掘金百家号博客园抖音小红书 你的文章也可以这样分发 墨衍会员 ¥399起/年,写一次发全网 我也要 + 加入社区
我刚学算法,这两天都在写全排列全组合,都是用字典序法,今天有幸看到了 http://topic.csdn.net/u/20090217/21/f41ed9f6-f929-451c-a5c9-80d2e408422a.html?seed=2130980366 这张帖子,其中大牛们的算法很精妙让我耳目一新,但我现在有些疑惑,我按组合数学书上的字典序算法实现的全组合 n = 11(ABCDEFGHIJk)时 平均时间在0.3秒带屏幕显示排列结果(我的配置是迅驰I 1.4G 1G内存),和帖子里 127楼 min_jie 用C#实现的时间差不多。我不是认为我比帖子里的大牛们强,因为他们的方法很精妙,我一点都没想到过,而且要慢慢看才能理解他们的算法,也不认为他们钻研算法达到最好是徒劳的,因为当n很大时,只有最优秀的算法才能体现效率,但我的疑惑是最普遍的字典序算法比这些精妙的算法其实相差多少呢?而且当N很大时,真的就相差很大吗?希望大家多谈谈意见。

这是我实现的字典序全组合 n = 11 完全按照组合数学书上算法写的。


#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// 元素数量
#define ELEM_SIZE 11
// 打印元素排列
void printString(char s[], int list[], int size);
// 初始化数组
void initList(int list[], int size);
// 字典序生成组合
void combinDict(char s[], int n, int k);

int main(void)
{
clock_t ct;
// 定义 ELEM_SIZE + 1个元素数组,使下标与值相对应
int k;
char s[ELEM_SIZE + 2] = "0ABCDEFGHIJk";

ct = clock();
// 字典序生成组合
for (k = 1; k <= ELEM_SIZE; k++)
{
combinDict(s, ELEM_SIZE, k);
}

ct = clock() - ct;

printf("time : %f\n", (double)ct / CLK_TCK);

return 0;
}

void initList(int list[], int size)
{
int i;

// 使 list[0] 为有符号最大值
list[0] = ~0U >> 1;

// 生成数组
for (i = 1; i <= size; i++)
{
list[i] = i;
}
}

void combinDict(char s[], int n, int k)
{
int i, j, *list, *blist;

i = k;
list = calloc(sizeof(int), n + 1);
blist = calloc(sizeof(int), k + 1);

// 初始化数组
initList(list, n + 1);
// 打印第一个元素组合
printString(s, list, k + 1);


// 字典序算法
while (i > 0)
{
if (list[i] < n - k + i)
{
// 生成 blist[i]
blist[i] = list[i] + 1;

// 若 i 不是最后一个元素k
if (i < k)
{
j = i + 1;

// 生成 blist[i + 1]...[k]
while (j <= k)
{
blist[j] = blist[j - 1] + 1;
j++;
}
}

// 使list[i]...[k] = blist[i]...[k]
while (i <= k)
{
list[i] = blist[i];
i++;
}

// 打印元素组合
printString(s, list, k + 1);

i = k;
}
else
{
i--;
}
}
}

void printString(char s[], int list[], int size)
{
int i;
for (i = 1; i < size; i++)
{
printf("%c", s[list[i]]);
}

printf("\n");
}



...全文

相关推荐

Java递归实现字符串全排列与全组合

主要为大家详细介绍了Java递归实现字符串全排列与全组合,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

weixin_38665668

C#中实现任意List的全组合算法代码

主要是介绍了.net C# 实现任意List的全组合算法实现代码,需要的朋友可以参考下

weixin_38688371

python生成n个元素的全组合方法

利用二进制反格雷码(bynary reflected Gray code)的方式生成n个元素的全组合,Cn1+Cn2+…+Cnn, 如在利用穷举方法解决背包问题时,就需要找出物品的所有组合的子集。如有物品1,2,3.我们就可以生成3个位串的格雷码,0表示不选择该物品,1表示选择该物品。 算法如下所示: import copy def brgd(n): ''' 递归生成n位的二进制反格雷码 :param n: :return: ''' if n==1: return ["0","1"] L1 = brgd(n-1) L2 = copy.deepcopy(L1) L2.re

weixin_38719702

算法之排列算法与组合算法详解

1. 前言 本文介绍了常用的排列组合算法,包括全排列算法,全组合算法,m个数选n个组合算法等。 2. 排列算法 常见的排列算法有: (A)字典序法 (B)递增进位制数法 (C)递减进位制数法 (D)邻位对换法 (E)递归法 介绍常用的两种: (1) 字典序法 对给定的字符集中的字符规定了一个先后关系,在此基础上按照顺序依次产生每个排列。 [例]字符集{1,2,3},较小的数字较先,这样按字典序生成的全排列是:123,132,213,231,312,321。 生成给定全排列的下一个排列 所谓一个的下一个就是这一个与下一个之间没有字典顺序中相邻的字符串。这就要求这一个与下一个有尽可能长的共同前缀,

weixin_38747906

c++ 排列组合算法,代码简单

c++课程设计,排列组合,算法 超级简单的,

zp11223344
评论 3
收藏 已收藏
分享
返回顶部