c# 课堂总结7--函数

函数:
数据类型-变量类型-运算符号表达式-语句(顺序,分支,循环)-数字

程序里的函数:能完成一个相对独立功能的代码块。
数学里的函数:高度抽象。
函数四要素:函数名,输入(参数),输出(返回值类型),加工(函数体)

函数定义:
[static]返回类型 函数名(输入参数列表)
{
//函数体-加工
}

函数调用:
[数据类型 变量名]=函数(参数);
函数名(参数);---用于无返回类型的函数
数据类型 变量=函数名(参数);---用于有返回类型的函数

1.参数匹配
在调用函数时,调用的参数和函数定义的参数保持一对待:个数,类型,对应。

形参:形式参数。--函数定义的参数。
实参:实际参数。--函数调用的参数。

实参、形参传值的规律--传址,传值。
传值:鉴于整型、浮点、bool、char这几种内建函数传递参数的时候,默认都是传值。
传值是把实参做一个副本(copy)传递给形参。
m=30;
Add(m);
static void Add(int a)
{
a+=20;
}
传址:默认情况下,数组就是传地址。字符串也是传地址。
对于内建的整型、浮点、bool、char这些类型,如果要变成传址的话,需要在前面加ref
m=30;
Add(ref m);
static void Add(ref int a)
{
a+=20;
}
对于传值和传址大家要记住:
1.什么是传值,什么传址?这个要分清楚。
2.默认情况下,哪些类型传值?哪些类型传址?
3.对于默认传值的类型,如何让他们变为传址?ref

以后为了防止因为传值、传址引起的错误,建议采用返回值的形式,明确返回的数据。

例题部分

         eg. 传值的方法
static void Main(string[] args)
{
int m = ;
Console.WriteLine("Main函数第一次打印:"+m);//
Add(m);
Console.WriteLine("Main函数第二次打印:" + m);//
}
static void Add(int a)
{
Console.WriteLine("Add函数第一次打印:"+a);//
a += ;
Console.WriteLine("Add函数第二次打印:"+a);//
} eg. 传址方式,加ref
static void Mainb(string[] args)
{
int m = ;
Console.WriteLine("Main函数第一次打印:" + m);//
Add1( m);
Console.WriteLine("Main函数第二次打印:" + m);//
Console.WriteLine("Main函数第三次打印:" + m);//
Add2(ref m);
Console.WriteLine("Main函数第四次打印:" + m);//
} static void Add1(int a)
{
Console.WriteLine("Add1传值函数第一次打印:" + a);//
a += ;
Console.WriteLine("Add1传值函数第二次打印:" + a);//
} static void Add2(ref int a)
{
Console.WriteLine("Add2传址函数第一次打印:" + a);//
a += ;
Console.WriteLine("Add2传址函数第二次打印:" + a);//
} eg. 传址与传值 数组名 传址,数组元素传值。
static void Main1(string[] args)
{
int[] m = new int[] {,,, }; //打印原值
foreach (int a in m)
{
Console.Write(a+"\t");
} //调用函数,传递整个数组
Add(m);//传得是数组名,传的是地址。 Add9(m[]);//传得是数组的某个元素,是传值。
//打印改变后的值
foreach (int a in m)
{
Console.Write(a+"\t");
}
} static void Add9(int a)
{
Console.WriteLine("Add9被调用了,在Add9中把传进来的" + a + "变成了" + a * );
a = a * ;
} static void Add(int[] b)
{
for (int i = ; i < b.Length; i++)
{
b[i] *= ;
}
}

2、函数重载?

在函数重载时,应包括函数签名的所有方面,例如,有两个不同的函数,他们分别值参数和引用参数。
static void ShowDouble(ref int val)
{
....
}

static void ShowDouble(int val)
{
....
}

选择使用哪个版本纯粹是根据是否包含ref关键字来确定的,下面的代码将调用引用版本:
ShowDouble(ref val);
下面的代码将调用值版本:
ShowDouble(val);
另外还要根据参数的个数来区分函数。

3、委托。

eg.1 对战改 函数

 //人人对战

     class class1
{
static void Mainmydemo5(string[] args)
{
string[] jn=new string[];//return 与out 的区别 :out 返回值时,不用规定数组的大小,return返回值是,数组必须创建出多大的。eg买东西!
//int[] sh=new int[10];
int[] sh;
jn = JiNeng(jn, out sh);//数组默认就是传址,不需要加ref,但有的时候不同 //string[] jn;
//int[] sh;
//JiNeng(out jn, out sh); player p1=new player();
player p2=new player();
ShuRu(ref p1.name, ref p2.name); //攻击方数据输出
p1 = PlayerPeiZhi(jn, sh, p1);
PlayerPeiZhiShuChu(p1); //防守方数据输出
p2 = PlayerPeiZhi(jn, sh, p2);
PlayerPeiZhiShuChu(p2); //战斗开始
Console.WriteLine("→→→→→→→→→"); Console.WriteLine("请按空格键开始对战");
ConsoleKeyInfo key = Console.ReadKey();
Console.Clear(); if (key.Key.ToString().ToLower() == "spacebar")
{
while (true)
{
#region 战斗开始
//攻击方攻击
ZhanDou(ref p1, ref p2); Console.WriteLine(p1.name + "的血量为:" + p1.blood + "," + p2.name + "的血量为:" + p2.blood); //退出循环的判断!
bool m = TuiChu(ref p1, ref p2);
if (m)
{
break;
}
else
{ } //防守方攻击
ZhanDou(ref p2, ref p1); Console.WriteLine(p1.name + "的血量为:" + p1.blood + "," + p2.name + "的血量为:" + p2.blood); //退出循环的判断!
bool n = TuiChu(ref p1, ref p2);
if (n)
{
break;
}
else
{ }
#endregion Thread.Sleep();
}
}
} /// <summary>
/// 输出玩家的配置
/// </summary>
/// <param name="t">形参 玩家</param>
private static void PlayerPeiZhiShuChu(player t)
{
player a = new player();
a = t;
Console.WriteLine("攻击方的战斗力如下:");
Console.WriteLine("姓名:" + a.name + ",血量:" + a.blood + ",攻击力:" + a.attack + ",防御力:" + a.defence + ",闪避力:" + a.shanbi);
Console.WriteLine("技能1为:{0},技能2为:{1},技能3为{2} 。", a.jineng[], a.jineng[], a.jineng[]);
} /// <summary>
/// 判断退出条件
/// </summary>
/// <param name="a">玩家1的信息</param>
/// <param name="b">玩家2的信息</param>
/// <returns>为 真 则退出,为 假 则继续。</returns>
private static bool TuiChu(ref player a, ref player b)
{
bool c;
if (b.blood == )
{
Console.WriteLine(a.name + "将" + b.name + "KO!");
c = true;
//break;
}
else if (a.blood == )
{
Console.WriteLine(b.name + "将" + a.name + "KO!");
c = true;
//break;
}
else if (a.blood == && b.blood == )
{
Console.WriteLine("平局!");
c = true;
//break;
}
else
{
c = false;
}
return c;
} /// <summary>
/// 战斗开始
/// </summary>
/// <param name="p1">玩家1的信息</param>
/// <param name="p2">玩家2的信息</param>
private static void ZhanDou(ref player a, ref player b)
{
//普通攻击
Random m1 = new Random();
//int a1 = m1.Next(3);
if (b.shanbi >= m1.Next())
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(a.name + "对" + b.name + "使用普通攻击,但被" + b.name + "躲过了。");
Console.ForegroundColor = ConsoleColor.Red;
//Console.WriteLine(p1.name + "的血量为:" + p1.blood + "," + p2.name + "的血量为:" + p2.blood); Console.WriteLine(p1.name + "的血量为:" + p1.blood + "," + p2.name + "的血量为:" + p2.blood);
//Thread.Sleep(1000);
}
else
{
b.blood = b.blood - a.attack + b.defence;
Console.ForegroundColor = ConsoleColor.Black;
Console.WriteLine(a.name + "使用普通攻击,对" + b.name + "造成了" + (a.attack - b.defence) + "点伤害。");
Console.ForegroundColor = ConsoleColor.Red;
if (b.blood <= )//判断是否为负血量,如果为<0,则让他=0,自己做的时候没想到
{
b.blood = ;
}
//Console.WriteLine(p1.name + "的血量为:" + p1.blood + "," + p2.name + "的血量为:" + p2.blood);
//Thread.Sleep(1000);
} //技能攻击
Random m2 = new Random();
int a1 = m2.Next();
if (m2.Next() >= m2.Next())
{
Console.ForegroundColor = ConsoleColor.Blue;
Console.WriteLine(a.name + "释放了" +a.jineng[a1] + ",对" + b.name + "造成了" + a.shanghai[a1] + "伤害。");
b.blood = b.blood - Convert.ToInt32(a.shanghai[a1]);
Console.ForegroundColor = ConsoleColor.Red;
if (b.blood <= )//判断是否为负血量,如果为<0,则让他=0,自己做的时候没想到
{
b.blood = ;
}
//Console.WriteLine(p1.name + "的血量为:" + p1.blood + "," + p2.name + "的血量为:" + p2.blood);
//Thread.Sleep(1000);
}
}//用ref 的目的就是传的a,b的地址这样才能够输出a,b因为战斗而改变的数据 /// <summary>
/// 战斗力配置
/// </summary>
/// <param name="jn">选择3个技能</param>
/// <param name="sh">对应出3个技能的伤害</param>
/// <param name="p1">对应的玩家</param>
/// <returns>返回玩家配置</returns>
private static player PlayerPeiZhi(string[] jn, int[] sh, player p)
{
int seed1 = ;
if (p.name.Length == )
{
seed1 = (int)(Convert.ToChar(p.name.Substring(, ))) + (int)(Convert.ToChar(p.name.Substring(, )));
}
else if (p.name.Length == )
{
seed1 = (int)(Convert.ToChar(p.name.Substring(, ))) + (int)(Convert.ToChar(p.name.Substring(, ))) +
(int)(Convert.ToChar(p.name.Substring(, )));
}
Random r1 = new Random(seed1); p.blood = r1.Next() + ;//血量
p.attack = r1.Next() + ;//攻击力
p.defence = r1.Next() + ;//防御力
p.shanbi = r1.Next() + ;//闪避
p.jineng = new ArrayList();//具体到当前p1.jineng这样集合。把结构体里的jineng类面对p1创建出p1.jineng的对象。
p.shanghai = new ArrayList(); //技能+伤害
for (int i = ; i < ; i++)
{
Random q = new Random();
int a = q.Next();
if (!p.jineng.Contains(jn[a]))
{
p.jineng.Add(jn[a]);
p.shanghai.Add(sh[a]);
}
else
{
i--;
}
} return p;
} /// <summary>
/// 技能及伤害
/// </summary>
/// <param name="jn">技能</param>
/// <param name="sh">伤害</param>
private static string[] JiNeng(string[] jn,out int[] sh)//或者static void JiNeng(out string[] jn, out int[] sh)
{ jn = new string[] { "横扫千军", "釜底抽薪", "降龙十巴掌", "雷霆一击", "死亡一指", "紧箍咒", "五雷轰顶", "装嫩", "卖萌", "青年2B打法" };
sh = new int[] { , , , , , , , , , };
return jn;
} /// <summary>
/// 输入姓名
/// </summary>
/// <param name="a">玩家1</param>
/// <param name="b">玩家2</param>
private static void ShuRu(ref string a, ref string b)//此处错误,因为a,b传的是值
{
Console.WriteLine("请输入出战方的姓名:");
a = Console.ReadLine();
Console.WriteLine("请输入防守方的姓名:");
b = Console.ReadLine();
} //private static void ShuRu(string a, string b)//此处错误,因为a,b传的是值
//{
// Console.WriteLine("请输入出战方的姓名:");
// a = Console.ReadLine();
// Console.WriteLine("请输入防守方的姓名:");
// b = Console.ReadLine();
//} }

eg.2 推箱子

  #region eg 1  推箱子

         static void Main1(string[] args)
{
int a = ;
while (true)
{
int[,] map = new int[, ];
map = Map(a); MapDisplay(map); int x = ZuoBiao(map, , );
int y = ZuoBiao(map, , );
int r = ZuoBiao(map, , );
int s = ZuoBiao(map, , );
while (map[r, s] != )
{
ConsoleKeyInfo key = Console.ReadKey(); #region 向右走
if (key.Key.ToString() == "RightArrow")
{
if (y < )//右移最大不会超过y=8坐标
{
if (map[x, y + ] == )//人的下一步只能是空地,或箱子,或墙,或终点,先判断空地
{
map[x, y + ] = ;
map[x, y] = ;
//走过终点后,再让终点恢复出来!
//if (a[8, 8] != 2)
// a[8, 8] = 3;
if (map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2)
// a[8, 6] = 3;
y++; }
else if (map[x, y + ] == )//人的下一步是终点
{
map[x, y + ] = ;
map[x, y] = ;
y++;
}
else if (map[x, y + ] == && map[x, y + ] == )//人的下一步是箱子
{
map[x, y + ] = ;
map[x, y + ] = ;
map[x, y] = ; //if (a[8, 8] != 2 && a[8, 8] != 1)
// a[8, 8] = 3;
if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2 && a[8, 6] != 1)
// a[8, 6] = 3; y++;
}
else if (map[x, y + ] == && map[x, y + ] == )//人的下一步是箱子,箱子的下一步是终点
{
map[x, y + ] = ;
map[x, y + ] = ;
map[x, y] = ; //if (a[8, 8] != 2)
// a[8, 8] = 3;
if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2)
// a[8, 6] = 3; y++;
}
else //其中包括,人的下一步是墙,箱子的下一步是墙
Console.WriteLine("\a");
}
else
Console.WriteLine("\a");
}
#endregion #region 向左走
if (key.Key.ToString() == "LeftArrow")
{
if (y > )//左移最小不会小于y=1坐标
{
if (map[x, y - ] == )//人的下一步只能是空地,或箱子,或墙,先判断空地
{
map[x, y - ] = ;
map[x, y] = ; //if (a[8, 8] != 2)
// a[8, 8] = 3;
if (map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2)
// a[8, 6] = 3;
y--;
}
else if (map[x, y - ] == )
{
map[x, y - ] = ;
map[x, y] = ;
y--;
}
else if (map[x, y - ] == && map[x, y - ] == )//人的下一步是箱子
{
map[x, y - ] = ;
map[x, y - ] = ;
map[x, y] = ; if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ; y--;
}
else if (map[x, y - ] == && map[x, y - ] == )//人的下一步是箱子,箱子的下一步是终点
{
map[x, y - ] = ;
map[x, y - ] = ;
map[x, y] = ; if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ; y--; }
else //其中包括,人的下一步是墙,箱子的下一步是墙
Console.WriteLine("\a");
}
else
Console.WriteLine("\a");
}
#endregion #region 向上走
if (key.Key.ToString() == "UpArrow")
{
if (x > )//上移不能超过x=8坐标
{
if (map[x - , y] == )//人的下一步只能是空地,或箱子,或墙,先判断空地
{
map[x - , y] = ;
map[x, y] = ; //if (a[8, 8] != 2)
// a[8, 8] = 3;
if (map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2)
// a[8, 6] = 3; x--;
}
else if (map[x - , y] == )//人下一步是终点,走上去的时候照样替换,走之后,就是人下一步是空地的问题了
{
map[x - , y] = ;
map[x, y] = ;
x--;
}
else if (map[x - , y] == && map[x - , y] == )//人的下一步是箱子,箱子的下一步是空地
{
map[x - , y] = ;
map[x - , y] = ;
map[x, y] = ; //if (a[8, 8] != 2 && a[8, 8] != 1)
// a[8, 8] = 3;
if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2 && a[8, 6] != 1)
// a[8, 6] = 3; x--;
}
else if (map[x - , y] == && map[x - , y] == )//人的下一步是箱子,箱子的下一步是终点
{
map[x - , y] = ;
map[x - , y] = ;
map[x, y] = ; //if (a[8, 8] != 2)
// a[8, 8] = 3;
if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2)
// a[8, 6] = 3; x--;
}
else //其中包括,人的下一步是墙,箱子的下一步是墙
Console.WriteLine("\a");
}
else
Console.WriteLine("\a");
}
#endregion #region 向下走
if (key.Key.ToString() == "DownArrow")
{
if (x < )//下移不能超过x=8坐标,只能下走增大,给个上限就可以
{
if (map[x + , y] == )//人的下一步只能是空地,或箱子,或墙,先判断空地
{
map[x + , y] = ;
map[x, y] = ;
//if (a[8, 8] != 2)
// a[8, 8] = 3;
if (map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2)
// a[8, 6] = 3;
x++;
}
else if (map[x + , y] == )//解决人不能通过终点坐标问题
{
map[x + , y] = ;
map[x, y] = ;
x++;
}
else if (map[x + , y] == && map[x + , y] == )//人的下一步是箱子,箱子的下一步是空地
{
map[x + , y] = ;
map[x + , y] = ;
map[x, y] = ; //if (a[8, 8] != 2 && a[8, 8] != 1)
// a[8, 8] = 3;
if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子,而且人在终点上的,就让显示人,而不是终点
map[r, s] = ;
//if (a[8, 6] != 2 && a[8, 6] != 1)
// a[8, 6] = 3; x++;
}
else if (map[x + , y] == && map[x + , y] == )//人的下一步是箱子,箱子的下一步是终点
{
map[x + , y] = ;
map[x + , y] = ;
map[x, y] = ; //if (a[8, 8] != 2)
// a[8, 8] = 3;
if (map[r, s] != && map[r, s] != )//当箱子推入终点后,如果人的下一步是空地的话,此时就不能让终点的坐标还显示,而是显示箱子
map[r, s] = ;
//if (a[8, 6] != 2)
// a[8, 6] = 3; x++;
}
else //其中包括,人的下一步是墙,箱子的下一步是墙
Console.WriteLine("\a");
}
else
Console.WriteLine("\a");
}
#endregion MapDisplay(map);
} Console.Write("恭喜你过关!按回车键进入下一关:");
ConsoleKeyInfo key1 = Console.ReadKey();
if (key1.Key.ToString().ToLower() == "enter")
{
a += ;
}
else
{
Console.WriteLine("你输入的有错!");
break;
}
}
} /// <summary>
/// 构造地图
/// </summary>
/// <param name="a">关数</param>
/// <returns>相应关数的地图</returns>
static int[,] Map(int a)
{
int[,] d = new int[, ];
if (a == )
{
int[,] map1 = new int[, ]{
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,}}; return map1;
}
else if (a == )
{
int[,] map1 = new int[, ]{
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,}}; return map1;
}
else if (a == )
{
int[,] map1 = new int[, ]{
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,}}; return map1;
}
else
{
int[,] map1 = new int[, ]{
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,},
{,,,,,,,,,}}; return map1;
}
} /// <summary>
/// 显示地图
/// </summary>
/// <param name="a">传入每一关的地图</param>
static void MapDisplay(int[,] a)
{
Console.Clear();
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
//Console.ForegroundColor = ConsoleColor.White; if (a[i, j] == )
Console.Write("♀");
else if (a[i, j] == )
Console.Write(" ");
else if (a[i, j] == )
{
//Console.ForegroundColor = ConsoleColor.Red;
Console.Write("☆");
// Console.ForegroundColor = ConsoleColor.White;
}
else if (a[i, j] == )
Console.Write("■");
else
Console.Write("□");
}
Console.WriteLine();
}
}//显示地图 /// <summary>
/// 计算人和终点的坐标
/// </summary>
/// <param name="map">每一关的地图</param>
/// <param name="a">a=1 人的坐标,a=2是终点的坐标</param>
/// <param name="b">b=1 x的坐标,b=2 y的坐标</param>
/// <returns>坐标值</returns>
static int ZuoBiao(int[,] map, int a, int b)
{
int m = ;
int[,] aa = map;
if (a == )
{
if (b == )
{
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
if (aa[i, j] == )
m = i;
}
}
}
else
{
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
if (aa[i, j] == )
m = j;
}
}
}
}
else
{
if (b == )
{
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
if (aa[i, j] == )
m = i;
}
}
}
else
{
for (int i = ; i < ; i++)
{
for (int j = ; j < ; j++)
{
if (aa[i, j] == )
m = j;
}
}
}
} return m;
}

eg.3

4、函数递归

递归的几个特点

a、递归式,就是如何将原问题划分成子问题。

b、递归出口,递归终止的条件,即最小子问题的求解,可以允许多个出口。

c、界函数,问题规模变化的函数,它保证递归的规模向出口条件靠拢。

引入非递归

从用户使用角度来说,递归真的很简便,对程序宏观上容易理解。递归程序的时间复杂度虽然可以根据T(n)=T(n-1)*f(n)递归求出,其中f(n)是递归式的执行时间复杂度,一般来说,时间复杂度和对应的非 递归差不多,但是递归的效率是相当低的它主要发费在反复的进栈出栈,各种中断等机制上(具体的可 以参考操作系统)更有甚者,在递归求解过程中,某些解会重复的求好几次,这是不能容忍的,这些也 是引入非递归机制的原因之一。

递归转非递归的两种方法

1.一般根据是否需要回朔可以把递归分成简单递归和复杂递归,简单递归一般就是根据递归式来找出递推公式(这也就引申出分治思想和动态规划)。

2.而复杂递归一般就是模拟系统处理递归的机制,使用栈 或队列等数据结构保存回朔点来求解。

例题:

1.求解阶乘

阶乘的定义就是n!=n*(n-1)! 0!=1 1!=1

根据定义我们很容易就想到递归方法,做法如下

int Fact(int n)

{
if(n==) return ; //递归出口
return n*Fact(n-) //n*Fact(n-1)就是递归式,其中n-1就是界函数
}

2.再看Fibonacci的例子

定义:某项的值等于前两项的和,其中第一和第二项为1。

根据定义我们很容易写出程序,这里就不写出来了,当我们用笔划几下的时候我们是否会发现有很多解是重复求出的。举个例子要求F(5)

F(5)=F(4)+F(3);

F(4)=F(3)+F(2);

F(3)=F(2)+F(1);

其中F(3)求解2次。这显然就是时间的浪费。下面我们用递推技术来转化成非递归从例子可以发现我们可以倒过来求解,即从底到顶把F(n)之前要计算的东西保存下来。

程序就是:

int Fibona(int n)
{
int p1=,p2=;
//int a[100]={0};
//a[1]=1,a[2]=1;
for(int i=;i<=n;i++) //从三开始就可以了,后面的return包括1,2
两种情况
{
int r=p1;
//递推,可以使用数组全部保存
p1=p2;
p2+=r;
//a=a[i-1]+a[i-2]
}
return p2;
//return a[n]; }
上一篇:python爬虫+数据可视化项目(关注、持续更新)


下一篇:git基本语法