2021年第一天,学习lua源代码,本文记录学习过程中遇到的问题和知识点,希望能在2021年上半年完成lua源代码的初步学习。
使用C模拟面向对象
使用union将所有数据包起来,一般情况下,如果看到一个数据类型是union,就可以知道这个数据想以一种较为省内存的方式来表示多种用途,而这些用途之间是互斥的,也就是说,在某个时刻该数据类型只会是其中的一个含义,一个简单的例子:
#include <stdio.h>
#include <stdlib.h>
typedef struct string {
int len;
char *data[0];
}string;
typedef struct number {
double num;
}number;
typedef struct value {
int type;
union {
string str;
number num;
}value;
}value;
int main()
{
string *str = (string *)malloc(sizeof(string) + sizeof(char) * 1024);
str->len = 1024;
value val;
val.type = 1;
val.value.str = *str;
free(str);
return 0;
}
递归算法优化(空间换时间)
看lua源码发现对性能要求做到了极致,能用char解决的不会用int,看另一本书上从递归讲到动态规划时举的一个例子非常好。在leetcode上找到一个题目,可以进行代码编写验证leetcode-70,题目非常简单,我们很快写出了答案:
class Solution {
public:
int climbStairs(int n) {
if(n == 1 || n == 2)
return n;
return climbStairs(n - 1) + climbStairs(n - 2);
}
};
可是却在计算45时报错,原因是我们重复计算了太多,例如f(6)= f(5) + f(4),计算f(5)=f(4)+f(3),这里可以看到重复计算了f(4),当计算45时存在大量的重复计算,导致超时,一种空间换时间的方法是在计算时缓存已经得到的结果,这样就不会重复计算:
class Solution {
private:
int climbStairs_helper(int n,vector<int> &res)
{
if (n == 1 || n ==2)
res[n] = n;
else if (res[n] == 0)
res[n] = climbStairs_helper(n-1,res) + climbStairs_helper(n-2,res);
return res[n];
}
public:
int climbStairs(int n) {
vector<int> res(n + 1,0);
climbStairs_helper(n,res);
return res[n];
}
};
这个问题最好的解法是使用动态规划DP,从递归到递归加记忆化,这个过程体现了空间换时间,进而更自然的可以使用从底向上递推,引出动态规划算法,这里不再赘述。