博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
递归再一次让哥震惊了
阅读量:4709 次
发布时间:2019-06-10

本文共 2469 字,大约阅读时间需要 8 分钟。

先说那两个让哥震惊的递归问题:

1:用递归实现单链表的倒序输出

2:从二叉查找树中删除节点,并保证还是二叉查找树

 

同学们可以开始思考这两个问题了,当然你可能N年前就遇到过这两个问题,那么不妨看看,看你是否真的理解了递归。实现这两个问题的代码当然很简单,就在下面。

 

百度百科中递归的名片:递归做为一种算法在程序设计语言中广泛应用.是指函数/过程/子程序在运行过程中直接或间接调用自身而产生的重入现象.递归是计算机科学的一个重要概念,递归的方法是程序设计中有效的方法,采用递归编写程序能使程序变得简洁和清晰。

 

刚开始学习的递归的时候,觉得他好强大,实现某些功能不用递归可能要几十行代码,用递归可能几行就搞定了,而且代码清晰简洁。一直以为递归也就是自己调用自己,有一个出口条件,让他停止递归,退出函数,其实的特点并非就这些。

 

递归还有一个非常重要的特点:先进后出,跟栈类似,先递进去的后递出来。由于递归一直在自己调用自己,有时候我们很难清楚的看出,他的返回值到底是哪个,只要你理解了先进后出这个特点,你就会明白,第一次调用时,作为返回值的那个变量的值就是递归函数的返回值。先进后出吗,他是第一个进来,也就是最后出去的那个,当然就是递归的返回值啦。

 

第一个让哥震惊的问题:用递归实现单链表的倒序输出。

我前段时间写过一篇博客《》,其中一种方法就是用递归实现的,当时看见那位高人用递归实现了这个功能,哥被震住了,他怎么可以这么聪明,他的博客真的是学算法的好地方:。代码如下,这是我那篇博客的源码:

 

//用递归实现         //很诚实的说盗用了别人的思想,真的太妙了,完全能看出你是否真的体会了递归的原理         //正如那位哥们所说,递归就是一个进栈出栈的过程,链表前面的元素先进栈,在栈底,后面的元素后进栈,在栈顶,先出栈,哈哈。。。         void recursion(node* head)         {
if(NULL==head) {
return; } if(head->next!=NULL) {
recursion(head->next); } //如果把这句放在第二个if前面,那就是从头到尾输出链表,曾经的你或许是用while或者用for循环输出链表,现在你又多了一种方式 cout<
data<<"\t"; }

 

这里充分运用了递归的先进后出的特点。

 

最近在博客园中看的一些博客,发现有几篇文章跟树联系得比较紧,前天晚上,我于是把数据结构与算法中树的那一章温习了一下,哥被二叉查找树删除节点的算法给震住了,因为我以前也写过一篇关于二插查找树的博客《》,在这篇博客中,删除节点的那个算法写得很长,以至于叫我自己现在去看都不是很理解,今天会让大家看到看到简洁清晰的代码,递归写的吗,哈哈哈!

先来C++版的吧,好久没写了,都生疏了:

 

View Code

 

 

在来C#版:

 

 现在我们重点来看看,删除节点的算法:

//删除指定节点下的节点
      
public 
TreeNode Delete(
int 
element, TreeNode node)
      
{
          
if 
(node ==
null
)
          
{
              
return 
null
;
          
}
          
if 
(element < node.Element)
          
{
              
node.Left = Delete(element, node.Left);
          
}
          
else 
if 
(element > node.Element)
          
{
              
node.Right = Delete(element, node.Right);
          
}
          
else
          
{
              
if 
(node.Left !=
null 
&& node.Right !=
null
)
              
{
                  
TreeNode tmpNode = FindMin(node.Right);
//查找当前节点有子树的最小节点
                  
node.Element = tmpNode.Element;
//将右子树的最小节点取代当前要删除的节点
                  
node.Right = Delete(node.Element, node.Right);
//这里是亮点,删除当前节点右子树的最小节点
              
}
              
else
              
{
                  
if 
(node.Left ==
null
)
                  
{
                      
node = node.Right;
                  
}
                  
else 
if 
(node.Right ==
null
)
                  
{
                      
node = node.Left;
                  
}
                  
else 
{
                      
node =
null
;
                  
}
              
}
          
}
 
          
return 
node;
      
}

 这里的重点是怎么处理,被删除的那个节点有左右两棵子树,其他的都很好处理,处理方式是:

1:找到要删除节点的右子树的最小节点,用FindMin这个方法就可以搞定;

2:将右子树的最小节点取代当前删除的节点,因为右子树的最小节点比当前节点的左子树中的所有节点都大,比右子树的节点都小,它就是符合条件的那个节点来代替当前要删除的节点

3:由于右子树的最小节点取代了当前节点,所以要在右子树中删除这个最小节点,现在又转换成同一个问题,在一棵二叉查找树中删除一个节点,于是就递归咯。

我当时就是没有想到这里还可以用递归,写了一堆自己现在都不是很懂的代码。

第一个问题让我震惊是以前没有理解递归的先进后出的思想,第二个是因为我没有掌握问题转换的思想,看似两个不同的问题,其实是同一个问题,当然解法也是一样的,既然把两个解法一样的问题放在一起,用递归就再好不过了,他同时把你们搞定

 

 作者:

 博客:

转载于:https://www.cnblogs.com/xumaojun/p/8541351.html

你可能感兴趣的文章
linux下实现keepalived+nginx高可用
查看>>
Html Agility Pack解析Html(C#爬虫利器)
查看>>
GridView中的CheckBox选中 (JQuery)
查看>>
webform(四)简单控件
查看>>
验证码
查看>>
敏捷开发入门教程
查看>>
C#发现之旅(收藏)
查看>>
POJ1125 Stockbroker Grapevine 多源最短路
查看>>
HDU 2126 Buy the souvenirs
查看>>
顺序容器的insert使用方法
查看>>
Markdown的使用
查看>>
销售系统学习.mdl
查看>>
触发器
查看>>
mysql配置默认字符集为UTF8mb4
查看>>
WPF实现3D翻转的动画效果
查看>>
自定义圆环进度条
查看>>
UILayer
查看>>
复杂对象写入文件
查看>>
k8s-高级调度方式-二十一
查看>>
[HDU3555]Bomb
查看>>