服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - 经典实例讲解C#递归算法

经典实例讲解C#递归算法

2022-09-09 14:23雲霏霏 C#

这篇文章主要用实例讲解C#递归算法的概念以及用法,文中代码非常详细,帮助大家更好的参考和学习,感兴趣的朋友可以了解下

一 、递归算法简介

在数学与计算机科学中,递归是指在函数的定义中使用函数自身的方法。

  递归算法是一种直接或者间接地调用自身算法的过程。在计算机编写程序中,递归算法对解决一大类问题是十分有效的,它往往使算法的描述简洁而且易于理解。
递归算法解决问题的特点:

  (1) 递归就是在过程或函数里调用自身。

  (2) 在使用递归策略时,必须有一个明确的递归结束条件,称为递归出口。

  (3) 递归算法解题通常显得很简洁,但递归算法解题的运行效率较低。所以一般不提倡用递归算法设计程序。

  (4) 在递归调用的过程当中系统为每一层的返回点、局部量等开辟了栈来存储。递归次数过多容易造成栈溢出等。所以一般不提倡用递归算法设计程序。在实际编程中尤其要注意栈溢出问题。

  借助递归方法,我们可以把一个相对复杂的问题转化为一个与原问题相似的规模较小的问题来求解,递归方法只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。但在带来便捷的同时,也会有一些缺点,也即:通常用递归方法的运行效率不高。 

二 、fibonacci数列和阶乘

1、 fibonacci数列

提到递归,我们可能会想到的一个实例便是斐波那契数列。斐波那契数列就是如下的数列:

  0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …,总之,就是第n(n > 2)个数等于第(n - 1)个数和(n - 2)个数的和。用递归算法实现如下:

?
1
2
3
4
5
6
7
public static int fibonacci(int n)
  {
   if (n < 0) return -1;
   if (n == 0) return 0;
   if (n == 1) return 1;
   return fibonacci(n - 1) + fibonacci(n - 2);
  }

2、阶乘

还有就是求一个数的阶乘,也会用到递归,这个比较简单,直接给出实现代码,如图:

?
1
2
3
4
5
6
7
8
9
public static int factorial (int n)
  {
  int sum = 0;
  if (0==n)
  return 1;
  else
  sum = n * factorial(n 一1) ;
  return sum;
  }

三 、汉诺塔问题 

汉诺塔是根据一个传说形成的数学问题:

经典实例讲解C#递归算法

        汉诺塔示意图(图片来自网络)

 有三根杆子a,b,c。a杆上有n个(n>1)穿孔圆盘,盘的尺寸由下到上依次变小。要求按下列规则将所有圆盘移至c杆:

  1、每次只能移动一个圆盘;

  2、大盘不能叠在小盘上面。

  提示:可将圆盘临时置于b杆,也可将从a杆移出的圆盘重新移回a杆,但都必须遵循上述两条规则。

  问:如何移?最少要移动多少次?

 下面是汉诺塔的递归求解实现(c#代码):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void hannoi(int n, string from, string buffer, string to)
  {
   if (n == 1)
   {
   console.writeline("move disk " + n + " from " + from + " to " + to);
   }
   else
   {
   hannoi(n - 1, from, to, buffer);
   console.writeline("move disk " + n + " from " + from + " to " + to);
   hannoi(n - 1, buffer, from, to);
   }
  }

其运行结果如图(大家可以跟上面的gif图片对比一下):

经典实例讲解C#递归算法

四 、排列组合

1、输出任意个数字母、数字的全排列

  对于一个长度为n的串或者n个字符(数字、节点)组成的字符串数组,它的全排列共有a(n, n)=n!种。这个问题也是一个递归的问题。如1,2,3,全排列可得到:{123,132,213,231,312,321}。

用递归算法实现代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void permutation(string[] nums, int m, int n)
  {
   string t;
   if (m < n - 1)
   {
   permutation(nums, m + 1, n);
   for (int i = m + 1; i < n; i++)
   {
    //可抽取swap方法
    t = nums[m];
    nums[m] = nums[i];
    nums[i] = t;
    
    permutation(nums, m + 1, n);
 
    //可抽取swap方法
    t = nums[m];
    nums[m] = nums[i];
    nums[i] = t;
   }
   }
   else
   {for (int j = 0; j < nums.length; j++)
   {
    console.write(nums[j]);
   }
   console.writeline();
   }
  }

调用代码如下:

?
1
2
3
4
5
6
static void main(string[] args)
  {
   nums = new string[] { "a", "b", "c" };
   permutation(nums, 0, nums.length);
   console.readkey();
  }

这里传入一个string数组,abc三个字母来测试,输出如下图:

经典实例讲解C#递归算法

2、将全排列结果保存到链表中

  有时候,我们需要将全排列的结果保存,然后做其他的处理,我们可以将结果保存到一个链表中。我们定义如下类作为链表的节点,代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
public class node
 {
  public string value { get; set; }
  public node nextnode { get; set; }
 
  public node(string value)
  {
   this.value = value;
   this.nextnode = null;
  }
 }

 此时声明全局变量,如下:

?
1
public static list<node> nodelist = new list<node>();

这个时候,我们修改permutation方法,如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public static void permutation(string[] nums, int m, int n)
  {
   string t;
   if (m < n - 1)
   {
   permutation(nums, m + 1, n);
   for (int i = m + 1; i < n; i++)
   {
    //可抽取swap方法
    t = nums[m];
    nums[m] = nums[i];
    nums[i] = t;
    
    permutation(nums, m + 1, n);
 
    //可抽取swap方法
    t = nums[m];
    nums[m] = nums[i];
    nums[i] = t;
   }
   }
   else
   {
   node root = null;
   node currentnode;
   for (int j = 0; j < nums.length; j++)
   {
    currentnode = new node(nums[j]);
    currentnode.nextnode = root;
    root = currentnode;
   }
   nodelist.add(root);
   }
  }

这样,我们执行了permutation方法后,就将结果保存到链表中了。用的时候,我们只要遍历nodelist就可以了。如图:

经典实例讲解C#递归算法

 递归算法就先说到这里了。谈到算法,就必需提数据结构,看来真的要“学到老了”~~

以上就是经典实例讲解c#递归算法的详细内容,更多关于c#递归算法的资料请关注服务器之家其它相关文章!

原文链接:https://www.cnblogs.com/yunfeifei/p/4272912.html

延伸 · 阅读

精彩推荐
  • C#C#实现的pdf生成图片文字水印类实例

    C#实现的pdf生成图片文字水印类实例

    这篇文章主要介绍了C#实现的pdf生成图片文字水印类,结合完整实例形式分析了C#针对pdf文件的创建、添加文字、水印等相关操作技巧,需要的朋友可以参考下...

    Metal110432022-01-24
  • C#C#中的delegate委托类型基本学习教程

    C#中的delegate委托类型基本学习教程

    这篇文章主要介绍了C#中的delegate委托类型基本学习教程,委托是C#语言所具有的一个重要特性,需要的朋友可以参考下...

    C#教程网9162021-11-11
  • C#C# 日历类功能的实例代码

    C# 日历类功能的实例代码

    本文通过实例代码给大家介绍了C# 日历类的相关知识,非常不错,具有参考借鉴价值,需要的朋友参考下吧...

    孤者自清6212022-01-11
  • C#如何解决hash冲突

    如何解决hash冲突

    上篇文章 为什么哈希存取比较快?使用它需要付出什么代价 只是简单介绍了使用hash所带来的利与弊。并未涉及hash的技术细节,本文则着重学习一下如何解...

    Robin8882021-11-26
  • C#C#使用Selenium的实现代码

    C#使用Selenium的实现代码

    这篇文章主要介绍了C#使用Selenium的实现代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着...

    zhaotianff7792022-08-30
  • C#vs 中C#项目读取JSON配置文件的方法

    vs 中C#项目读取JSON配置文件的方法

    这篇文章主要介绍了vs中 C#项目读取JSON配置文件的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要...

    z1784430854522022-09-05
  • C#C#使用InstallerProjects打包桌面应用程序的完整步骤

    C#使用InstallerProjects打包桌面应用程序的完整步骤

    这篇文章主要给大家介绍了关于C#使用InstallerProjects打包桌面应用程序的完整步骤,文中通过示例代码介绍的非常详细,对大家学习或者使用C#具有一定的参...

    kiba5186722022-07-28
  • C#C#程序异常关闭时的捕获

    C#程序异常关闭时的捕获

    这篇文章主要为大家详细介绍了C# Winform程序异常关闭时,进行捕获并记录日志,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    Alan.hsiang7642022-02-27