![](/img/trans.png)
[英]Converting loop implementation of Pancake Sort to a recursive implementation
[英]Converting a recursive implementation to a loop based implementation
我有兩個接口負責持有一個閉包
這是第一個在地圖操作時保持閉包的方法。
package com.fs;
/**
* This interface is responsible for holding the closures when it comes to map.
* It uses two generic types. One for the argument and one for the return type.
* @param <B> Generic type
* @param <A> Generic type
*/
public interface Func<B,A> {
/**
* Function prototype m takes an argument of type A and returns a type B.
* A map operation can produce a different type.
* @param x of type A
* @return type B
*/
B m(A x);
}
第二個用於過濾操作
package com.fs;
/**
* This interface is responsible for holding the closures when it comes to filter.
* @param <A> Generic type
*/
public interface Pred<A> {
/**
* Function prototype m takes an argument of type A and returns a boolean.
* A filter operation checks every element if it fits a predicate.
* @param x of type A
* @return boolean
*/
boolean m(A x);
}
我有一個名為CList的類,它能夠使用閉包。
package com.impl.list;
import com.fs.*;
public class CList<T> {
T head;
CList<T> tail;
public CList(T x, CList<T> xs){
head = x;
tail = xs;
}
static <A,B> CList<B> map(Func<B,A> f, CList<A> xs){
if(xs==null){
return null;
}
return new CList<>(f.m(xs.head),map(f,xs.tail));
}
static <A,B> CList<B> maploop(Func<B,A> f, CList<A> xs){
//?????
return null;
}
static <A> CList<A> filter(Pred<A> f, CList<A> xs){
if(xs == null){
return null;
}
if(f.m(xs.head)){
return new CList<>(xs.head, filter(f,xs.tail));
}
return filter(f,xs.tail);
}
static <A> int length(CList<A> xs){
int ans =0;
while(xs!= null){
++ans;
xs=xs.tail;
}
return ans;
}
}
這是我使用閉包實現CList的公共接口。
package com.impl.list;
import com.fs.Func;
import com.fs.Pred;
public class CListClient {
public static CList<Integer> doubleAll(CList<Integer> xs){
Func<Integer, Integer> df = new Func<Integer, Integer>() {
@Override
public Integer m(Integer x) {
return x * 2;
}
};
return CList.map(df, xs);
}
public static int countNs(CList<Integer> xs,final int n){
Pred<Integer> pf = new Pred<Integer>() {
@Override
public boolean m(Integer x) {
return x==n;
}
};
return CList.length(CList.filter(pf, xs));
}
public static CList<Integer> doubleAllloop(CList<Integer> xs){
Func<Integer, Integer> df = new Func<Integer, Integer>() {
@Override
public Integer m(Integer x) {
return x * 2;
}
};
return CList.maploop(df, xs);
}
}
一個簡單的測試人員:
package basic;
import com.impl.list.CList;
import com.impl.list.CListClient;
import org.junit.Test;
public class ListTester {
CList<Integer> intlist_1 = new CList<>(new Integer(1),null);
CList<Integer> intlist_2 = new CList<>(new Integer(2),intlist_1);
CList<Integer> intlist_3 = new CList<>(new Integer(3),intlist_2);
CList<Integer> intlist_4 = new CList<>(new Integer(4),intlist_3);
CList<Integer> intlist_5 = new CList<>(new Integer(4),intlist_4);
CList<Integer> intlist = new CList<>(new Integer(5),intlist_5);
@Test
public void test_doubleAll(){
CList<Integer> doubled = CListClient.doubleAll(intlist);
CList<Integer> doubledloop = CListClient.doubleAllloop(intlist);
}
@Test
public void test_CountNs(){
int count3s = CListClient.countNs(intlist, 3);
}
}
我試圖將以遞歸方式實現的map函數轉換為while循環。 我把它命名為maploop。 它讓我的大腦受傷了兩天。任何提示都會讓我非常高興。我在這里問這個問題,因為有可能有人可能會參加Dan Grossman課程並看到這個例子並試圖實現這個功能。 我更喜歡暗示而非實際答案。 謝謝。
將遞歸函數轉換為迭代函數時,必須檢查需要哪種非尾調用狀態(如果有)。 然后創建一個堆棧並將狀態推送到堆棧,並像編碼一樣編寫它,否則就像遞歸函數一樣。 如果函數中有多個遞歸調用,則需要新的狀態項還包含一個值,指示函數中的哪個點。
在這種情況下,您只有一個遞歸調用,唯一的狀態是xs
,因此事情非常簡單,您不需要自定義狀態對象。
這是我做事的方式(未經測試)。
static <A,B> CList<B> maploop(Func<B,A> f, CList<A> xs){
Stack<CList<A>> stack = new Stack<>();
while(xs != null){
stack.push(xs);
xs = xs.tail;
}
CList<a> result = xs;
while(!stack.empty()){
xs = stack.pop();
result = new CList<>(f.m(xs.head), result);
}
return result;
}
將遞歸程序轉換為迭代程序的標准方法是通過尾遞歸變量。 作為一個非常簡單的例子,考慮以下遞歸因子函數來計算N!
:
int factorial(int x) {
if (x == 0)
return 1;
else
return x * factorial(x-1);
}
呼叫factorial(N);
。
使這個尾遞歸涉及添加一個累積變量:
int tailRecursiveFactorial(int x, int y) {
if (x == 0)
return y;
else
return tailRecursiveFactorial(x-1, x*y);
}
調用tailRecursiveFactorial(N, 1);
這個直接轉換為迭代程序:
int x = N;
int y = 1;
while (x != 0) {
y = x*y;
x = x-1;
}
當然,你的問題要困難得多,但一般的方法仍然可行。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.