Java基于遞歸和循環(huán)兩種方式實(shí)現(xiàn)未知維度集合的笛卡爾積算法示例
本文實(shí)例講述了Java基于遞歸和循環(huán)兩種方式實(shí)現(xiàn)未知維度集合的笛卡爾積。分享給大家供大家參考,具體如下:
什么是笛卡爾積?
在數(shù)學(xué)中,兩個(gè)集合X和Y的笛卡兒積(Cartesian product),又稱直積,表示為X × Y,第一個(gè)對(duì)象是X的成員而第二個(gè)對(duì)象是Y的所有可能有序?qū)Φ钠渲幸粋€(gè)成員。
假設(shè)集合A={a,b},集合B={0,1,2},則兩個(gè)集合的笛卡爾積為{(a,0),(a,1),(a,2),(b,0),(b,1), (b,2)}。
如何用程序算法實(shí)現(xiàn)笛卡爾積?
如果編程前已知集合的數(shù)量,通過程序的多次循環(huán)即可得出笛卡爾積。但是如果編程前不知道集合的數(shù)量,如何得到笛卡爾積哪?比如集合表示List < List<String>> list
;這個(gè)list在編程前l(fā)ist的數(shù)量是未知的。下面的代碼使用遞歸和循環(huán)兩種方法實(shí)現(xiàn)未知維度集合的笛卡爾積:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * 循環(huán)和遞歸兩種方式實(shí)現(xiàn)未知維度集合的笛卡爾積 * Created on 2015-05-22 * @author luweijie */ public class Descartes { /** * 遞歸實(shí)現(xiàn)dimValue中的笛卡爾積,結(jié)果放在result中 * @param dimValue 原始數(shù)據(jù) * @param result 結(jié)果數(shù)據(jù) * @param layer dimValue的層數(shù) * @param curList 每次笛卡爾積的結(jié)果 */ private static void recursive (List<List<String>> dimValue, List<List<String>> result, int layer, List<String> curList) { if (layer < dimValue.size() - 1) { if (dimValue.get(layer).size() == 0) { recursive(dimValue, result, layer + 1, curList); } else { for (int i = 0; i < dimValue.get(layer).size(); i++) { List<String> list = new ArrayList<String>(curList); list.add(dimValue.get(layer).get(i)); recursive(dimValue, result, layer + 1, list); } } } else if (layer == dimValue.size() - 1) { if (dimValue.get(layer).size() == 0) { result.add(curList); } else { for (int i = 0; i < dimValue.get(layer).size(); i++) { List<String> list = new ArrayList<String>(curList); list.add(dimValue.get(layer).get(i)); result.add(list); } } } } /** * 循環(huán)實(shí)現(xiàn)dimValue中的笛卡爾積,結(jié)果放在result中 * @param dimValue 原始數(shù)據(jù) * @param result 結(jié)果數(shù)據(jù) */ private static void circulate (List<List<String>> dimValue, List<List<String>> result) { int total = 1; for (List<String> list : dimValue) { total *= list.size(); } String[] myResult = new String[total]; int itemLoopNum = 1; int loopPerItem = 1; int now = 1; for (List<String> list : dimValue) { now *= list.size(); int index = 0; int currentSize = list.size(); itemLoopNum = total / now; loopPerItem = total / (itemLoopNum * currentSize); int myIndex = 0; for (String string : list) { for (int i = 0; i < loopPerItem; i++) { if (myIndex == list.size()) { myIndex = 0; } for (int j = 0; j < itemLoopNum; j++) { myResult[index] = (myResult[index] == null? "" : myResult[index] + ",") + list.get(myIndex); index++; } myIndex++; } } } List<String> stringResult = Arrays.asList(myResult); for (String string : stringResult) { String[] stringArray = string.split(","); result.add(Arrays.asList(stringArray)); } } /** * 程序入口 * @param args */ public static void main (String[] args) { List<String> list1 = new ArrayList<String>(); list1.add("1"); list1.add("2"); List<String> list2 = new ArrayList<String>(); list2.add("a"); list2.add("b"); List<String> list3 = new ArrayList<String>(); list3.add("3"); list3.add("4"); list3.add("5"); List<String> list4 = new ArrayList<String>(); list4.add("c"); list4.add("d"); list4.add("e"); List<List<String>> dimValue = new ArrayList<List<String>>(); dimValue.add(list1); dimValue.add(list2); dimValue.add(list3); dimValue.add(list4); List<List<String>> recursiveResult = new ArrayList<List<String>>(); // 遞歸實(shí)現(xiàn)笛卡爾積 recursive(dimValue, recursiveResult, 0, new ArrayList<String>()); System.out.println("遞歸實(shí)現(xiàn)笛卡爾乘積: 共 " + recursiveResult.size() + " 個(gè)結(jié)果"); for (List<String> list : recursiveResult) { for (String string : list) { System.out.print(string + " "); } System.out.println(); } List<List<String>> circulateResult = new ArrayList<List<String>>(); circulate(dimValue, circulateResult); System.out.println("循環(huán)實(shí)現(xiàn)笛卡爾乘積: 共 " + circulateResult.size() + " 個(gè)結(jié)果"); for (List<String> list : circulateResult) { for (String string : list) { System.out.print(string + " "); } System.out.println(); } } }
輸出結(jié)果是:
遞歸實(shí)現(xiàn)笛卡爾乘積: 共 36 個(gè)結(jié)果 1 a 3 c 1 a 3 d 1 a 3 e 1 a 4 c 1 a 4 d 1 a 4 e 1 a 5 c 1 a 5 d 1 a 5 e 1 b 3 c 1 b 3 d 1 b 3 e 1 b 4 c 1 b 4 d 1 b 4 e 1 b 5 c 1 b 5 d 1 b 5 e 2 a 3 c 2 a 3 d 2 a 3 e 2 a 4 c 2 a 4 d 2 a 4 e 2 a 5 c 2 a 5 d 2 a 5 e 2 b 3 c 2 b 3 d 2 b 3 e 2 b 4 c 2 b 4 d 2 b 4 e 2 b 5 c 2 b 5 d 2 b 5 e 循環(huán)實(shí)現(xiàn)笛卡爾乘積: 共 36 個(gè)結(jié)果 1 a 3 c 1 a 3 d 1 a 3 e 1 a 4 c 1 a 4 d 1 a 4 e 1 a 5 c 1 a 5 d 1 a 5 e 1 b 3 c 1 b 3 d 1 b 3 e 1 b 4 c 1 b 4 d 1 b 4 e 1 b 5 c 1 b 5 d 1 b 5 e 2 a 3 c 2 a 3 d 2 a 3 e 2 a 4 c 2 a 4 d 2 a 4 e 2 a 5 c 2 a 5 d 2 a 5 e 2 b 3 c 2 b 3 d 2 b 3 e 2 b 4 c 2 b 4 d 2 b 4 e 2 b 5 c 2 b 5 d 2 b 5 e
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
基于Java swing組件實(shí)現(xiàn)簡(jiǎn)易計(jì)算器
這篇文章主要介紹了基于Java swing組件實(shí)現(xiàn)簡(jiǎn)易計(jì)算器,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04java實(shí)現(xiàn)的連接oracle/mysql數(shù)據(jù)庫功能簡(jiǎn)單示例【附oracle+mysql數(shù)據(jù)庫驅(qū)動(dòng)包】
這篇文章主要介紹了java實(shí)現(xiàn)的連接oracle/mysql數(shù)據(jù)庫功能,結(jié)合實(shí)例形式分析了java基于jdbc連接Oracle與mysql的相關(guān)操作技巧,并附帶完整實(shí)例代碼與oracle+mysql數(shù)據(jù)庫驅(qū)動(dòng)包供讀者下載參考,需要的朋友可以參考下2017-10-10解決使用mybatis-plus時(shí),生成的SQL大寫變小寫加下劃線問題
這篇文章主要介紹了解決使用mybatis-plus時(shí),生成的SQL大寫變小寫加下劃線問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12關(guān)于log4j日志擴(kuò)展---自定義PatternLayout
這篇文章主要介紹了關(guān)于log4j日志擴(kuò)展---自定義PatternLayout,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12Object類toString()和equals()方法使用解析
這篇文章主要介紹了Object類toString()和equals()方法使用解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02詳解IntelliJ IDEA2020.1和JDK14體驗(yàn)
這篇文章主要介紹了詳解IntelliJ IDEA2020.1和JDK14體驗(yàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05