转移表简介
在计算机科学中,转移表(Lookup table)是一种数据结构,通常是一个数组或字典,用于存储预先计算的结果,以便在需要时进行快速查找。
转移表的常见用途之一是优化函数的计算过程,特别是在需要频繁执行某个操作或计算昂贵的函数时。通过使用转移表,可以将计算结果预先存储在表中,然后根据输入的值直接查找对应的结果,而不必重复计算。
例如,考虑一个需要计算正弦函数值的程序。正弦函数的计算可能是比较昂贵的操作,特别是当需要精确的结果时。而使用转移表的方法,可以预先计算并存储一系列输入值对应的正弦函数的结果。然后,在需要计算正弦函数的某个特定值时,只需要在转移表中查找相应的结果,而不必重新计算。
转移表还可以用于其他各种问题,例如加密和解密算法、运算符查找、字符映射等。
总而言之,转移表是一种高效的数据结构,可以提高计算效率,避免重复计算,并优化程序性能。
- 而我们今天要使用转移表的对象就是计算器的简易代码
- 在要求上,我们只需要加减乘除四个运算,所以就可以创建四个int函数,返回我们计算的结果
- 然后主体部分需要创建一个菜单,并且初始化输入的字母input和要进行计算的a和b两个数字,以便在后面进行输入输出
- 接下来创建do while循环即可
那么我们先用最简单的方式,switch语句正常写一遍,不使用转移表
#include<stdio.h>
int add(int x, int y)
{
return x + y;//加
}
int sub(int x, int y)
{
return x - y;//减
}
int mul(int x, int y)
{
return x * y;//乘
}
int div(int x, int y)
{
return x / y;//除
}
//菜单
void menu()
{
printf("****************\n");
printf("**1.add 2.sub***\n");
printf("**3.mul 4.div***\n");
printf("****0. exit*****\n");
}
int main()
{
int a = 0, b = 0;
int input = 0;
do
{
menu();
int ret = 0;
input = 0;
printf("请输入操作数:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入两个计算数:");
scanf("%d%d", &a, &b);
ret=add(a, b);
printf("结果为:%d\n", ret);
break;
case 2:
printf("请输入两个计算数:");
scanf("%d%d", &a, &b);
ret = sub(a, b);
printf("结果为:%d\n", ret);
break;
case 3:
printf("请输入两个计算数:");
scanf("%d%d", &a, &b);
ret = mul(a, b);
printf("结果为:%d\n", ret);
break;
case 4:
printf("请输入两个计算数:");
scanf("%d%d", &a, &b);
ret = div(a, b);
printf("结果为:%d\n", ret);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("请重新选择:\n");
break;
}
} while (input);
return 0;
}
- 可以看出,这段代码虽然实现了简易计算器,但是也有一些效率上的问题,比如每个case语句中都包含了重复的printf和scanf语句,而这些就会让代码看上去十分冗余,不够精简
- 而在接下来使用转移表的时候,这些冗余的代码就不会再出现,而是利用一个函数指针数组就可以实现
//上面的函数部分不变
int main()
{
int a = 0, b = 0;
int input = 0;
int(*p[5])(int,int) = {0,add,sub,mul,div};//后面的(函数参数类型)注意不要遗忘,有的话就填进去,没有的话就空括号
//前面加个0是为了符合位置,让add等数跟自己的编号对上
do
{
menu();
printf("请输入操作数:");
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("请输入两个计算数:");
scanf("%d%d", &a, &b);
int ret = (*p[input])(a,b);
printf("结果是:%d\n", ret);
}
else if (input == 0)
{
printf("退出计算器\n");
}
else
{
printf("重新输入:\n");
}
} while (input);
return 0;
}
可以看出,转移表将原来的函数精简了不少,只用三个if语句就完成了本来的目的,让代码看上去一目了然
当然,转移表的应用还不止于此,接下来我再举一个例子,实现小写字母转化为大写字母:
#include <stdio.h>
//在 toUpperCase 函数中,我们定义了一个转移表 table,其中存储了每个小写字母对应的大写字母。这个转移表是一个包含26个字符的数组。
//函数的参数 c 表示要转换的字符。
//我们首先通过在条件语句中检查输入字符 c 是否在 'a' 到 'z' 的范围内,来确保输入的字符是小写字母。
//如果输入字符是小写字母,我们可以通过字符的 ASCII 值与字符 'a' 的 ASCII 值的差来确定它在转移表中的索引位置。例如,'a' 对应的 ASCII 值为 97,'a' - 'a' 的结果为 0,所以它在转移表的索引位置为 0。
//根据输入字符的索引位置,我们可以在转移表中查找到相应的大写字母,并将其返回作为结果。
//如果输入字符不是小写字母,则直接返回原字符。
char toUpperCase(char c) {
// 转移表,将小写字母转换为大写字母
//const char,防止数组里的内容改变
const char table[] = {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
};
if (c >= 'a' && c <= 'z') //c如果是小写字母
{
int index = c - 'a';//如果是小写a,那么就是'a'-'a'=0,返回table[0],也就是'A'
return table[index];
}
else {
return c;//大写字母直接返回自己
}
}
int main() {
char c = 'a';
char upperCase = toUpperCase(c);
printf("%c\n", upperCase);
return 0;
}
如果正常用if语句去写的话,那么就需要加上好几个限制条件限制住元素的类型,才可以使用,由此可见,转移表确实方便
如果大家对转移表还有什么更深刻的理解的话,欢迎大家与我一起探讨!