经典递归算法之排列,组合,集合和换零钱, Python yield实现.
2014-08-08 14:51
429 查看
对于每个函数名'f',还有个非递归的版本'xf',例如 perm和xperm, comb和xcomb等.
全部是以生成器的形式实现.例如:perm((1,2,3))返回(1,2,3)的全排列生成器.
全部是以生成器的形式实现.例如:perm((1,2,3))返回(1,2,3)的全排列生成器.
def subsets(s): if not s: yield () else: head, rest = s[:1], s[1:] for se in subsets(rest): yield se yield head + se def xsubsets(s): stk = [(s, ())] while stk: s, head = stk.pop() if not s: yield head else: stk.append((s[1:], head + s[:1])) stk.append((s[1:], head)) def comb(s,k=None): n = len(s) if k is None: k = n if k < 0: raise ValueError("k must be non-negative") if k > n: return () def recur(s, k, n): if k == n: yield s elif k == 0: yield () else: head, rest = s[:1], s[1:] yield from recur(rest, k, n-1) yield from (head + x for x in recur(rest, k-1, n-1)) return recur(s, k, n) def xcomb(s,k=None): n = len(s) if k is None: k = n if k < 0: raise ValueError("k must be non-negative") if k > n: return () def recur(s, k, n): stk = [(s, k, n, ())] while stk: s, k, n, head = stk.pop() if k == n: yield head + s elif k == 0: yield head else: stk.append((s[1:], k-1, n-1, head + s[:1])) stk.append((s[1:], k, n-1, head)) return recur(s, k, n) def wperm(s): if not s: yield () else: head, rest = s[:1], s[1:] rest_n = len(rest) + 1 for ele in wperm(rest): for i in range(rest_n): yield ele[:i] + head + ele[i:] def xwperm(s): stk = [(s, ())] while stk: s, head = stk.pop() if not s: yield head else: h = s[:1] n = len(head) + 1 for i in range(n): stk.append((s[1:], head[:i] + h + head[i:])) def perm(s,k=None): for cs in comb(s,k): yield from wperm(cs) def xperm(s,k=None): for cs in xcomb(s,k): yield from xwperm(cs) def exch(my,arr): if my < 0 or not arr: pass elif not arr[1:]: c = arr[0] div, mod = divmod(my, c) if mod == 0: yield tuple(c for _ in range(div)) else: head, rest = arr[:1], arr[1:] yield from exch(my, rest) yield from (head + x for x in exch(my-arr[0], arr)) def xexch(my,arr): stk = [(my, arr, ())] while stk: my, arr, head = stk.pop() if my < 0 or not arr: continue if not arr[1:]: c = arr[0] div, mod = divmod(my, c) if mod == 0: yield head + tuple(c for _ in range(div)) else: stk.append((my-arr[0], arr, head + arr[:1])) stk.append((my, arr[1:], head)) import itertools s = tuple(range(5)) arr=tuple(range(1,6000)) def test(): for i in range(len(s)+1): assert(set(itertools.combinations(s,i))==set(comb(s,i))) def test2(): for i in range(len(s)+1): assert(set(itertools.permutations(s,i))==set(perm(s,i))) def test3(): for x in xexch(10,arr): print(x) #assert(set(xexch(10,arr))==set(exch(10,arr))) def test4(): for i in range(len(s)+1): assert(set(xcomb(s,i))==set(comb(s,i))) for x in xcomb(s, 2): print(x) def test5(): for ss in subsets(arr): print(ss) print('---') for ss in xsubsets(arr): print(ss) assert(set(subsets(arr))==set(xsubsets(arr))) def test6(): #assert(set(perm(arr,3))==set(xperm(arr,3))) for x in xperm(arr,3): print(x) if __name__=='__main__': test6()
相关文章推荐
- 高效率的排列组合算法--《编程珠矶》--python实现
- 排列组合算法的递归实现
- [经典算法] 排列组合-N元素集合的所有子集(二)
- Python实现的简单排列组合算法示例
- [经典算法] 排列组合-N元素集合的所有子集(一)
- 排列和组合算法的实现方法_C语言经典案例
- 基于python快速实现排列组合算法
- [经典算法] 排列组合-N元素集合的M元素子集
- 排列和组合算法 C语言经典实现
- 排列和组合算法 C语言经典实现
- 递归实现全排列和组合
- 每日一题系列 - 全排列算法python实现
- C#实现排列组合算法
- 两两组合算法-递归实现方法
- 全排列算法递归实现(笔试题)
- 组合算法-递归实现
- Java 非递归实现的排列组合中的平均分组问题
- 用递归实现排列组合
- 两两组合算法-递归实现方法
- 全排列和组合的实现算法