您的位置:首页 > 其它

使用分治法实现的全排列算法

2007-08-29 11:06 218 查看
我们将使用分治法实现一个全排列算法。先来看一下算法实现后的效果:

['a','b','c'].permutation #=> [["a", "b", "c"],

# ["a", "c", "b"],

# ["b", "a", "c"],

# ["b", "c", "a"],

# ["c", "a", "b"],

# ["c", "b", "a"]]

算法描述

分治法求解问题分为三个步骤:

- 分解:将问题分为若干个子问题。

- 解决:递归地求解每个子问题。

- 合并:将每个子问题的解合并成为整个问题的解。

现在我们需要求具有n个元素的数组A的全排列。例如:大小为3的数组A=[a,b,c] (为方便起见,我把引号全都省略了,其实应该是A=['a','b','c']。下同),它的全排列为:

[[a,b,c],

[a,c,b],

[b,a,c],

[b,c,a],

[c,a,b],

[c,b,a]]

这是一个大小为 n!*n 的二维数组。

使用分治算法求解全排列的过程如下

- 分解:将数组分为子数组 A[1..k-1] 和一个元素 A[k]。 (1≤k≤n)

- 解决:递归地求解每个子数组 A[1..k-1] 的全排列,直至子数组A[1..k-1]为空时结束递归。

- 合并:将上一步的结果---A[1..k-1]的全排列(一个二维数组)与元素A[k]合并,得出A[1..k]的全排列。例如:

[[]] 与 a 合并得到 [[a]]

[[a]] 与 b 合并得到 [[a,b], [b,a]]

[[a,b],[b,a]] 与 c 合并得到 [[a,b,c],[a,c,b],[c,a,b],[b,c,a],[c,a,b],[c,b,a]]

看下面的图示会更直观一些

1. 分解过程

[a,b,c]

/ \

[a,b] c

/ \

[a] b

/ \

[] a

2. 合并过程

[] a

\ /

[[a]] b

\ /

[[a,b],[b,a]] c

\ /

[[a,b,c],

[a,c,b],

[c,a,b],

[b,a,c],

[b,c,a],

[c,b,a]]

源代码

下面是ruby的源代码(文件名“permutation.rb”)

class Array

# Returns permutation(a new two-dimentional array) of self.

# Example

# - [].permutation #=> [[]]

# - ['A'].permutation #=> [['A']]

# - ['A','B'].permutation #=> [['A','B'],['B','A']]

# - ['A','B','C'].permutation #=> [['A','B','C'],

# ['A','C','B'],

# ['B','A','C'],

# ['B','C','A'],

# ['C','A','B'],

# ['C','B','A']]

def permutation()

permutation_i(self.length-1).sort!

end

private

def permutation_i(i)

if i> 0

return Array.merge_permutation(permutation_i(i-1), self[i])

else

return Array.merge_permutation([[]], self[i])

end

end

# Example

# - Array.merge_permutation([[]], 'A') #=> [['A']]

# - Array.merge_permutation([['A']], 'B') #=> [['B','A'],['A','B']]

# - Array.merge_permutation([['B','A'],['A','B']], 'C') #=> [['C','B','A'],

# ['B','C','A'],

# ['B','A','C'],

# ['C','B','A'],

# ['A','C','B'],

# ['A','B','C']]

def Array.merge_permutation(src, item)

result = Array.new

src.each do |each_array|

result += Array.item_permutation(each_array, item)

end

return result

end

# Returns a new two-dimentional array. Inserts "item" in each pertential place in "src".

# Example

# - Array.item_permutation([], 'A') #=> [['A']]

# - Array.item_permutation(['A'], 'B') #=> [['B','A'], ['A','B']]

# - Array.item_permutation(['A','B'], 'C') #=> [['C','A','B'], ['A','C','B'], 'A','B','C']]

def Array.item_permutation(src, item)

result = Array.new

(0..src.length).each do |i|

new_array = src.collect

new_array.insert(i, item)

result << new_array

end

return result

end

end

require 'pp_extension'

pp(['a','b','c'].permutation)

源代码用于输出二维数组的“pp_extension”可以看我的这篇文章让ruby以矩阵的样式输出二维数组

源代码如下(文件名"pp_extension.rb")

require 'pp'

# Outputs two-dimension array like matrix

class Array

def pretty_print(q)

q.group(1, '[', ']') {

q.seplist(self) {|v|

q.current_group.break if v.is_a?(Array) && !q.current_group.first? # added by me

q.pp v

}

}

end

end

运行时间

算法运行时间 T(n) = T(n-1) + Θ(n2) = Θ(n3)

注 本文并不是从教科书上抄下来的,而是我闭门造车的结果,所以很可能有不正之处,请不吝赐教。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: