簡體   English   中英

具有置換簽名的堆算法

[英]Heap's algorithm with permutation signature

我正在編寫一個可以生成元素列表的所有排列以及基於原始列表的排列簽名的代碼。

通常,排列的數量由第一種斯特林數給出,它是由k = n-划分n個元素的C環的組合組成的。

       [n]           [n - 1]   [n - 1]
       [ ] = (n - 1) [     ] + [     ]
       [k]           [  k  ]   [k - 1]

將n個元素划分為k個周期的方法是將n-1個非最大元素划分為k個周期並以n-1種方式之一拼接最大元素,或者將最大元素置於其自己的周期中並划分n個-1個非最大元素成k-1個周期。 然后,符號將由(-1)^ NC給出,其中N是索引數,C是元素從其原始位置移動時形成的循環數。

我已經對堆算法的變體進行了編碼,該算法可以產生每個排列的簽名。

    def permute(a, l, r): 
        if l==r:          
            print'Permutation--:',a
        else: 
            for i in xrange(l,r+1): 
                if i!=l:
                    a[0]=(-1)*int(a[0])#Sign for permutation
                a[l], a[i] = a[i], a[l] 
                permute(a, l+1, r)             
                a[l], a[i] = a[i], a[l]                         
                if i!=l:#Sign for permutation
                    a[0]=(-1)*int(a[0])




    test = "1hgfe"
    n = len(test) 
    a = list(test) 
    permute(a, 1, n-1)

在例行置換中,將列表a引入列表a [0]的第一個成員是正負號,在這種情況下為+1,並且對於每個排列,列表的單數乘以-1。 到目前為止,我認為代碼有效,這是測試的結果。

          ['1', 'h', 'g', 'f', 'e']  (h->h) (g->g) (f->f) (e->e)       (-1)^(4-4) or identity =+1  
          [-1, 'h', 'g', 'e', 'f']   (h->h) (g->g) (f->e)              (-1)^(4-3)=-1
          [-1, 'h', 'f', 'g', 'e']   (h->h) (g->f) (e->e)              (-1)^(4-3)=-1
          [1, 'h', 'f', 'e', 'g']    (h->h) (g->f->e)                  (-1)^(4-2)=+1
          [-1, 'h', 'e', 'f', 'g']   (h->h) (g->e) (f->f)              (-1)^(4-3)=-1
          [1, 'h', 'e', 'g', 'f']    (h->h) (g->e->f)                  (-1)^(4-2)=+1
          [-1, 'g', 'h', 'f', 'e']   (h->g) (f->f) (e->e)              (-1)^(4-3)=-1
          [1, 'g', 'h', 'e', 'f']    (h->g) (f->e)                     (-1)^(4-2)=+1
          [1, 'g', 'f', 'h', 'e']    (h->g->f) (e->e)                  (-1)^(4-2)=+1
          [-1, 'g', 'f', 'e', 'h']   (h->g->f->e)                      (-1)^(4-1)=-1
          [1, 'g', 'e', 'f', 'h']    (h->g->e) (f->f)                  (-1)^(4-2)=+1
          [-1, 'g', 'e', 'h', 'f']   (h->g->e->f)                      (-1)^(4-1)=-1
          [-1, 'f', 'g', 'h', 'e']   (h->f) (g->g)(e->e)               (-1)^(4-3)=-1
          [1, 'f', 'g', 'e', 'h']    (h->f->e) (g->g)                  (-1)^(4-2)=+1
          [1, 'f', 'h', 'g', 'e']    (h->f->g) (e->e)                  (-1)^(4-2)=+1
          [-1, 'f', 'h', 'e', 'g']   (h->f->e->g)                      (-1)^(4-1)=-1
          [1, 'f', 'e', 'h', 'g']    (h->f) (g->e)                     (-1)^(4-2)=+1
          [-1, 'f', 'e', 'g', 'h']   (h->f->g->e)                      (-1)^(4-1)=-1
          [-1, 'e', 'g', 'f', 'h']   (h->e) (g->g) (f->f)              (-1)^(4-3)=-1
          [1, 'e', 'g', 'h', 'f']    (h->e->f) (g->g)                  (-1)^(4-2)=+1
          [1, 'e', 'f', 'g', 'h']    (h->e) (g->f)                     (-1)^(4-2)=+1
          [-1, 'e', 'f', 'h', 'g']   (h->e->g->f)                      (-1)^(4-1)=-1
          [1, 'e', 'h', 'f', 'g']    (h->e->g) (f->f)                  (-1)^(4-2)=+1
          [-1, 'e', 'h', 'g', 'f']   (h->e->f->g)                      (-1)^(4-1)=-1  

我的問題是:您認為我的代碼將適用於任何列表大小,即[1,A,B,C ......,Z_n]嗎? 有沒有更有效的方法來生成排列及其符號?

是的,您的方法是正確的。 而不是直接證明這一點,您應該證明

(1)的執行permute(a, l, r)返回的每個排列l個,直到r個字母a一次,以及退出與a等於它是在執行開始。

通過對r - l歸納可以直接證明這一點。 如果沒有“退出與a相等的”索賠的一部分,這將是很難。

至於正確的符號,這只是一個循環不變式:每次交換兩個不同的條目時,都將符號乘以-1,這是更改符號的唯一次數。 因此,是的,第0個條目是過程中每次的排列符號。

Knuth的TAoCP(第4A卷)的7.2.1.2節專門介紹了生成所有排列的算法。 它們中的一些也可以很容易地修改以產生它們的符號。 我想知道你是否在其中。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM