本文我將首先用遞迴和非遞迴演算法實現對整數陣列的全排列,然後通過提煉介面,將這種演算法運用到實現對其它資料型別的全排列,對long陣列,列表,字串等。
下面**是用來實現對整數陣列的排列的演算法,具體原理見這裡 。
public static listperm(int a)
public static listperm(int a, int fromindex, int toindex)
private static void perm(int a, int fromindex, int toindex, listresult) else
} }private static void swap(int a, int i, int j)
這裡將所有的結果放在乙個list中,這樣對小的資料很好,但是對大的資料可能會outofmemory,在我的機器上當資料的大小》=10時就會outofmemory。我需要將它轉換成非遞迴演算法,並返回iterator,這樣儲存在記憶體中的資料極少,而不會outofmemory。將該程式轉換成非遞迴演算法時,需要先畫出遞迴樹,具體該怎麼做,這裡就不詳述了,見**:
public static iteratorpermiterator(int a, int fromindex, int toindex)
public static iteratorpermiterator(int a)
public static iterablepermiterable(int a, int fromindex, int toindex)
public static iterablepermiterable(int a)
// 將遞迴翻譯成非遞迴
private static class intarraypermiterator implements iterator, iterable
public boolean hasnext()
public int next()
int result = array.clone();
frame = frames.removelast();
while (!frames.isempty())
frames.removelast();
}return result;
} public void remove()
public iteratoriterator() }
private static class stackframe
public string tostring()
}
intarraypermiterator實現iterator和iterable介面,實現iterable介面是為了能夠在利用jdk5中增強for迴圈:
for (int a: permiterable(new int))
這樣做的問題是,如果要實現對long陣列,char陣列,list資料,字串的排列,我幾乎需要將它們重寫一遍。我想重用這些演算法,該怎麼辦呢?每當這時我都會想到提取介面。讓我們觀察遞迴版本的perm(int a, int fromindex, int toindex, listresult)方法(非遞迴版本類似),它用到對陣列a的進行操作的方法只有swap方法和a.clone()方法,因此可以將它提取出乙個介面叫做permable,為了不指定toindex,我新增了乙個新方法size()。另外為了不和object中clone()方法衝突,我使用了copy這個名字。介面如下:
public inte***ce permable
該介面使用了型別引數t,表示返回的資料型別。使用這個介面,遞迴版本的排列演算法為:
public static listperm(permabledata)
public static listperm(permabledata, int fromindex, int toindex)
private static void perm(permabledata, int fromindex, int toindex, listresult) else
} }
要對long陣列,字串,list等進行排序,只需要提供它們自己的permable介面實現:
public static class longarraypermable implements permable
public void swap(int i, int j)
public long copy()
public int size()
} public static class chararraypermable implements permable
public void swap(int i, int j)
public char copy()
public int size() }
public static class stringpermable implements permable
public stringpermable(char data)
public string copy()
public int size()
public void swap(int i, int j)
} public static class objectarraypermable implements permable
public void swap(int i, int j)
public object copy()
public int size() }
public static class listpermableimplements permable>
public listpermable(listdata)
@suppresswarnings("unchecked")
public listcopy() else catch (instantiationexception e) catch (illegalacces***ception e)
}} public int size()
public void swap(int i, int j)
}
現在要得到字串,long陣列的排列,可以:
for (long a : perm(new longarraypermable(new long)))
for (string a : perm(new stringpermable("abc")))
它該介面用在非遞迴版本的排列演算法上也很簡單,只需要做幾處簡單的替換就可以了,這裡就不列舉了,見附件。 全排列演算法的遞迴與非遞迴實現
對於給定的集合a,其中的n個元素互不相同,如何輸出這n個元素的所有排列 全排列 例如 給定集合 1,2,3 它的全排列子集為 1,2,3 1,3,2 2,1,3 2,3,1 3,1,2 3,2,1 思路 1.保持第乙個數不變,對後面的數進行全排列 2.將第乙個數換成其它數,對後面的數進行全排列 3....
遞迴與非遞迴演算法
一 題目分析 將非負十進位制整n轉換成b進製 其中b 2 16 將任意正整數n用2的冪次方表示 二 演算法設計 1 轉換進製問題 exer.cpp 遞迴演算法 遞迴出口 n b b 遞迴表示式 f n,b f n b,b n b b 遞迴棧表示 2 用二的冪次方表示任意正整數n問題 exer2.cp...
全排列的遞迴與非遞迴
全排列是乙個十分基礎的概念,是一串有可比權值的元素出現的所有排列形式,例如 張全蛋 張蛋全 全張蛋 全蛋 張 蛋全張 蛋張全 就是張全蛋的全排列,所以我們發現全排列用來取名字是很不錯的,如果對每個漢字在名字中的權值做一 張表,再來一張可能出現的不同字同時出現在名字中的關聯權值表,那麼全排列可以算出一...