排列 遞迴與非遞迴 演算法及介面設計

2021-08-22 20:11:26 字數 3365 閱讀 1819

本文我將首先用遞迴和非遞迴演算法實現對整數陣列的全排列,然後通過提煉介面,將這種演算法運用到實現對其它資料型別的全排列,對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...

全排列的遞迴與非遞迴

全排列是乙個十分基礎的概念,是一串有可比權值的元素出現的所有排列形式,例如 張全蛋 張蛋全 全張蛋 全蛋 張 蛋全張 蛋張全 就是張全蛋的全排列,所以我們發現全排列用來取名字是很不錯的,如果對每個漢字在名字中的權值做一 張表,再來一張可能出現的不同字同時出現在名字中的關聯權值表,那麼全排列可以算出一...