C++ 中的递归 lambda 表达式
递归 lambda 表达式是函数直接或间接调用自身的过程称为递归,相应的函数称为递归函数。使用递归算法,可以很容易地解决某些问题。此类问题的示例有河内塔 (TOH)、中序/前序/后序树遍历、图的 DFS 等。
递归函数只是一种循环结构。不同之处在于它自己维护一个内存堆栈。显然,它必须有像 for 和 while 循环这样的中断条件。因此,递归函数具有以下结构-
function name(arguments)
{
a base case (a breaking condition)
recursive code (the actual logic)
}
int fact(int n)
{
// Base Case
if (n < = 1)
return 1;
else
return n * fact(n - 1);
}
C++ 11 引入了 lambda 表达式,使我们能够编写一个内联函数,该函数可用于不会重用且不值得命名的短代码片段。最简单的 lambda 表达式可以定义如下:
[ capture clause ] (parameters) -> return-type
{
definition of method
}
方案一:
下面是 C++ 中 sort() 方法中 lambda 表达式的程序:
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
int arr[] = { 5, 2, 1, 4, 3 };
sort(arr, arr + 5, [](int& a,
int& b) {
// Instant lambda function
return a > b;
});
for (int i = 0; i < 5; i++)
cout << arr[i] << " ";
return 0;
}
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Stored lambda expression
auto cmp = [](int& a, int& b) {
return a > b;
};
// Driver code
int main()
{
int arr[] = { 5, 2, 3, 1, 4 };
sort(arr, arr + 5, cmp);
for (int i = 0; i < 5; i++)
cout << arr[i] << " ";
return 0;
}
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Recursive function to print
// the digits of a number
void printReverse(int n)
{
if (n == 0)
return;
cout << n % 10 << " ";
printReverse(n / 10);
}
// Driver code
int main()
{
int n = 12345;
printReverse(n);
return 0;
}
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Recursive lambda function to
// print the digits of a number
auto printReverse = [&]() {
if (n == 0)
return;
cout << n % 10;
n = n / 10;
printReverse();
// As it is a part of main body,
// semicolon is must
};
printReverse();
return 0;
}
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Function itself as a parameter
auto printReverse = [&](auto&& printReverse) {
if (n == 0)
return;
cout << n % 10 << " ";
n = n / 10;
printReverse(printReverse);
};
// Function as an argument
printReverse(printReverse);
return 0;
}
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Declaring of a function
void declaringFunction(string s);
// Driver code
int main()
{
declaringFunction("Hello I am learning how to declare a function");
return 0;
}
// Body of a function
void declaringFunction(string s)
{
cout << s;
}
C++14
// C++ program to implement
// the above approach
#include
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Function < return type (parameter
// types) > functionName
// Don't forget to include functional
// header
// Declaration
function printReverse;
printReverse = [&]() {
if (n == 0)
return;
// Defination
cout << n % 10 << " ";
n /= 10;
printReverse();
};
printReverse();
}
C++14
// C++ program to implement
// the above approach
#include
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Function < return type (parameter
// types) > functionName
function printReverse = [&]() {
if (n == 0)
return;
// Declaration + Body
cout << n % 10 << " ";
n /= 10;
printReverse();
};
printReverse();
}
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
int n = 6;
// Recursive Lambda function to
// find the factorial of a number
auto factorial = [&](auto&& factorial) {
if (n == 1)
return n;
return n-- * factorial(factorial);
};
auto factorial2 = [](int n, auto&& factorial2) {
if (n == 1)
return n;
return n * factorial2(n - 1, factorial2);
};
// Given n = 6
cout << factorial(factorial) << endl;
// Given n = 5
cout << factorial2(5, factorial2);
}
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
// Sorted array
int arr[] = { 1, 2, 5, 7, 10, 12, 15 };
int size = 7;
// Item to be searched
int key = 10;
auto binarySearch = [&](int startIndex,
int endIndex,
auto&& binarySearch) {
if (startIndex > endIndex)
return -1;
int midIndex = (startIndex + endIndex) / 2;
if (arr[midIndex] == key)
return midIndex;
if (arr[midIndex] > key)
return binarySearch(startIndex,
midIndex - 1,
binarySearch);
if (arr[midIndex] < key)
return binarySearch(midIndex + 1,
endIndex,
binarySearch);
// Not found
return -1;
};
int index = binarySearch(0, size - 1,
binarySearch);
if (index == -1)
cout << "Not found";
else
cout << "Found on index " << index;
return 0;
}
5 4 3 2 1
说明:这里使用的是 Instant lambda函数,不能在其他排序方法中使用,即需要重新编写相同的代码。此 lambda 表达式仅在执行 sort() 方法期间存在。但是也可以将 lambda 表达式存储在变量中(最好将其称为函数),如下所示。通过存储它,它可以进一步使用,当然也可以进行递归。
方案二:
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Stored lambda expression
auto cmp = [](int& a, int& b) {
return a > b;
};
// Driver code
int main()
{
int arr[] = { 5, 2, 3, 1, 4 };
sort(arr, arr + 5, cmp);
for (int i = 0; i < 5; i++)
cout << arr[i] << " ";
return 0;
}
5 4 3 2 1
说明:这里的 auto cmp 是 lambda 存储函数,可用于多种排序方法。
使用 Lambda 进行递归:让我们通过考虑下面的递归函数一起讨论递归和 lambda 表达式的概念:
方案三:
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Recursive function to print
// the digits of a number
void printReverse(int n)
{
if (n == 0)
return;
cout << n % 10 << " ";
printReverse(n / 10);
}
// Driver code
int main()
{
int n = 12345;
printReverse(n);
return 0;
}
5 4 3 2 1
说明:以上是使用递归以相反顺序打印数字的数字的函数。使用 lambda 表达式也可以做到这一点。
程序4:
下面是使用 lambda 表达式实现上述代码的 C++ 程序:
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Recursive lambda function to
// print the digits of a number
auto printReverse = [&]() {
if (n == 0)
return;
cout << n % 10;
n = n / 10;
printReverse();
// As it is a part of main body,
// semicolon is must
};
printReverse();
return 0;
}
输出:
解释:这里,函数将如何识别变量 n,即使它没有作为参数传递。带有空捕获子句 [ ] 的 lambda 只能访问其本地变量。这里使用了捕获close[&],它允许函数访问变量n(变量n的实际值正在改变)。有两种方法可以解决上述错误:
1. 通过将函数本身传递给函数参数:
下面是实现上述概念的 C++ 程序:
计划5:
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Function itself as a parameter
auto printReverse = [&](auto&& printReverse) {
if (n == 0)
return;
cout << n % 10 << " ";
n = n / 10;
printReverse(printReverse);
};
// Function as an argument
printReverse(printReverse);
return 0;
}
5 4 3 2 1
2. 首先声明函数:
声明一个函数意味着声明其名称和参数类型,以通知编译器有一个名为 xyz 的函数,该函数稍后将编写其主体。
计划6:
下面是实现上述概念的 C++ 程序:
C++
// C++ program to implement
// the above approach
#include
using namespace std;
// Declaring of a function
void declaringFunction(string s);
// Driver code
int main()
{
declaringFunction("Hello I am learning how to declare a function");
return 0;
}
// Body of a function
void declaringFunction(string s)
{
cout << s;
}
Hello I am learning how to declare a function
程序 7:
由于它是一个 lambda函数,因此必须有某种独特的方法来声明该函数。下面是相同的 C++ 程序:
C++14
// C++ program to implement
// the above approach
#include
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Function < return type (parameter
// types) > functionName
// Don't forget to include functional
// header
// Declaration
function printReverse;
printReverse = [&]() {
if (n == 0)
return;
// Defination
cout << n % 10 << " ";
n /= 10;
printReverse();
};
printReverse();
}
5 4 3 2 1
说明:在上面的代码中,首先声明了函数printReverse,然后我们定义了它的主体。取而代之的是,我们可以直接声明函数及其主体,这称为定义函数。下面是实现上述方法的 C++ 程序:
程序8:
C++14
// C++ program to implement
// the above approach
#include
#include
using namespace std;
// Driver code
int main()
{
int n = 12345;
// Function < return type (parameter
// types) > functionName
function printReverse = [&]() {
if (n == 0)
return;
// Declaration + Body
cout << n % 10 << " ";
n /= 10;
printReverse();
};
printReverse();
}
5 4 3 2 1
示例:以下是使用 lambda 表达式的递归函数的一些示例。
程序 9:
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
int n = 6;
// Recursive Lambda function to
// find the factorial of a number
auto factorial = [&](auto&& factorial) {
if (n == 1)
return n;
return n-- * factorial(factorial);
};
auto factorial2 = [](int n, auto&& factorial2) {
if (n == 1)
return n;
return n * factorial2(n - 1, factorial2);
};
// Given n = 6
cout << factorial(factorial) << endl;
// Given n = 5
cout << factorial2(5, factorial2);
}
720
120
说明:在阶乘函数,使用 [&] 捕获子句直接访问 n。在 factorial2函数, n 作为参数传递。因此,不需要 [&] 子句。
计划10:
C++14
// C++ program to implement
// the above approach
#include
using namespace std;
// Driver code
int main()
{
// Sorted array
int arr[] = { 1, 2, 5, 7, 10, 12, 15 };
int size = 7;
// Item to be searched
int key = 10;
auto binarySearch = [&](int startIndex,
int endIndex,
auto&& binarySearch) {
if (startIndex > endIndex)
return -1;
int midIndex = (startIndex + endIndex) / 2;
if (arr[midIndex] == key)
return midIndex;
if (arr[midIndex] > key)
return binarySearch(startIndex,
midIndex - 1,
binarySearch);
if (arr[midIndex] < key)
return binarySearch(midIndex + 1,
endIndex,
binarySearch);
// Not found
return -1;
};
int index = binarySearch(0, size - 1,
binarySearch);
if (index == -1)
cout << "Not found";
else
cout << "Found on index " << index;
return 0;
}
Found on index 4