Johnson-Trotter(JT)演算法產生排列

來源:互聯網
上載者:User

標籤:

    對於產生{1,……,n}的所有n!個排列的問題,我們可以利用減治法,該問題的規模減一就是要產生所有(n-1)!個排列。假設這個小問題已經解決了,我們可以把n插入到n-1個元素的每一種排列中的n可能的位置中去,來得到較大規模大問題的一個解。按照這種方式產生的所有排列都是獨一無二的,並且他們的總數應該是n(n-1)!=n!。這樣,我們都得到了{1,……,n}的所有排列。    JohnsonTrotter演算法實現形式。    JohnsonTrotter(n)        輸入:一個正整數n        輸出:{1,……,n}的素有排列的列表        將第一個排列初始化為方向向左的元素數組        while 存在一個移動元素k do            求最大的移動元素k            把k和它箭頭指向的相鄰元素互換            調轉所有大於k的元素的方向            將新排列添加到列表(摘自演算法設計與分析基礎)     下午自己實現了一下這個演算法,將其改成可以把N個不重複的元素排列出來,程式中使用到的比較子提供介面需要自己去實現,程式運行需要把使用者自己實現的比較子注入程式。自我感覺程式靈活性還可以。
/** * 使用JT演算法進行排列組合。 * 注意:請務必保持範型和比較介面範型一致,否則可能產生不可預知的錯誤 * @author LiuYeFeng<[email protected]> * @date 2015年4月9日 下午5:31:00 * @CopyRight 2015 TopView Inc * @version V1.0 * @param <E> 需要排列的元素的範型,請務必保持範型和比較介面範型一致,否則可能產生不可預知的錯誤 */public class JTAlgorithm<E>{    //存放排列元素的數組    protected E[] array;    //元素的方向數組    private Direction[] directions;    //比較子,用於比較元素大小    private Compare<E> compare;        public JTAlgorithm(Class<? extends Compare<E>> clazz) {        //擷取比較方法的執行個體        this.compare = (Compare) ReflectUtils.newInstance(clazz);    }        public JTAlgorithm(Compare<E> compare) {        //擷取比較方法的執行個體        this.compare = compare;    }
public List<E[]> generate(E[] elements) { List<E[]> result = new ArrayList<E[]>(); //初始化工作 init(elements); //最大可移動元素的位置 int biggestFlag = findBiggestMobileElement(); //自身也為一種排列 result.add(Arrays.copyOf(array, array.length)); //存在可移動最大元素k while (biggestFlag != -1) { //將k和箭頭指向的相鄰元素互換 biggestFlag = changeBiggestElementAndNeighbor(biggestFlag); //調轉所有大於k的元素的方向 changeDirection(biggestFlag); //將新排列添加到結果集 result.add(Arrays.copyOf(array, array.length)); //重新尋找可移動最大元素 biggestFlag = findBiggestMobileElement(); } return result; }
private void init(E[] elements) { //用快排把元素排序 QuickSort<E> qk = new QuickSort<E>(compare); qk.sort(elements, 0, elements.length - 1); array = elements; directions = new Direction[array.length]; //初始化方向 for (int i = 0; i < directions.length; i++) { directions[i] = Direction.LEFT; } }
/** * 把比loc位置大的元素的方向反轉 * @param loc */ private void changeDirection(int loc) { for (int i = 0; i < array.length; i++) { if (compare.greaterThan(array[i], array[loc])) { directions[i] = (directions[i] == Direction.LEFT) ? Direction.RIGHT : Direction.LEFT; } } }
/** * 把loc元素和它的鄰居互換,並把互換後loc的新位置返回 * @param loc * @return loc的新位置 */ private int changeBiggestElementAndNeighbor(int loc) { int neighbor = -1; if (directions[loc] == Direction.LEFT) { neighbor = loc - 1; } else { neighbor = loc + 1; } E temp = array[loc]; array[loc] = array[neighbor]; array[neighbor] = temp; Direction dTemp = directions[loc]; directions[loc] = directions[neighbor]; directions[neighbor] = dTemp; return neighbor; }
/** * 尋找最大可移動元素 * @return 最大可移動元素的位置 */ private int findBiggestMobileElement() { int loc = -1; int biggestLoc = -1; for (int i = 0; i < array.length; i++) { //判斷左右方向 if (directions[i] == Direction.LEFT) { //如果是頭元素,則無法向左比較,跳過 if (i == 0) { continue; } if (compare.greaterThan(array[i], array[i - 1])) { loc = i; } } else { //如果是尾元素,則無法向右比較,跳過 if (i == array.length - 1) { continue; } if (compare.greaterThan(array[i], array[i + 1])) { loc = i; } } //如果第一次找到可移動元素,則把最大可移動元素改變,之後把本次找到的可移動元素和最大可移動元素進行比較 if (loc != -1 && biggestLoc == -1) { biggestLoc = loc; }else if (biggestLoc != -1 && compare.greaterThan(array[loc], array[biggestLoc])) { biggestLoc = loc; } } return biggestLoc; }}

 

Johnson-Trotter(JT)演算法產生排列

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.