• 单链表的递归与非递归实现


    一:递归版本

    复制代码
     1 class LinkList
     2     {
     3         public class LinkNode
     4         {
     5             public int data;
     6 
     7             public LinkNode next;
     8         }
     9 
    10         private LinkNode head;
    11 
    12         public void Add(int data)
    13         {
    14             if (head == null)
    15             {
    16                 head = new LinkNode() { data = data };
    17             }
    18             else
    19             {
    20                 Add(head, data);
    21             }
    22         }
    23 
    24         public void Add(LinkNode node, int data)
    25         {
    26             if (node.next == null)
    27             {
    28                 node.next = new LinkNode() { data = data };
    29                 return;
    30             }
    31 
    32             Add(node.next, data);
    33         }
    34     }
    复制代码


    二:非递归版本

    复制代码
     1    class LinkList
     2     {
     3         public class LinkNode
     4         {
     5             public int data;
     6 
     7             public LinkNode next;
     8         }
     9 
    10         private LinkNode head;
    11 
    12         public void Add(int data)
    13         {
    14             LinkNode node = new LinkNode() { data = data };
    15 
    16             if (head == null)
    17             {
    18                 head = node;
    19             }
    20             else
    21             {
    22                 LinkNode temp = head;
    23 
    24                 while (temp.next != null)
    25                 {
    26                     temp = temp.next;
    27                 }
    28 
    29                 temp.next = node;
    30             }
    31         }
    32     }
    复制代码


    这个非递归不理解的地方在于临时变量temp,提出的问题就是为什么:“temp.next=node” 之后,head的值发生了改变?我想之所以不能理解,绝逼是对

    引用类型的内存分配不了解,而这个非递归版本恰恰就是用引用类型这个内存分配技巧来实现 ”非递归构建单链表“。。。为了不让别人踩上这个坑,我还是大

    概说一下流程,大概是这样的,当我们在new一个引用类型的时候,CLR就要计算实例字段和所有基类上的实例字段的大小,然后再在堆上分配合理的内存块,

    最后把堆上的内存块的首地址保存在栈上面。

    为了方便理解,现在假如LinkList里面有三个结点:instance1 -> instance2 -> instance3, 

    第一句:

    1 LinkNode temp = head;

    这个句子不难理解吧,把head的地址赋给temp,那么栈上temp的地址也就是head的地址,head的地址就是指向instacnce1内存块地址。

    第二句: 从这句while中可以看到,一直在找instance的next,可以看出之后把instance2的内存地址给了temp,再next之后就把instance3的内存地址给

                了temp,然后就发现instance3的next为null,然后就跳出循环。

    1                 while (temp.next != null)
    2                 {
    3                     temp = temp.next;
    4                 }

    第三句:从上一句可以看到,instance3的next已经为null了,这时候就把新构建的结点:LinkNode node = new LinkNode() { data = data };赋

               给temp的next指针上来继续构建链表。

    1 temp.next = node;

    可以看到这时候instance4就构造到了instance3之后,同时temp.next已经是保存instance4的内存地址,这一些操作对head来说都是透明的,它也不管

    后面怎么操作,当你遍历head的时候会惊奇的发现居然我的链表中多了一个instance4,这个也就是朋友疑惑的地方,如果看到这个内存分配图的话,

    也许会豁然开朗,当然这篇博文没什么技术含量,也是自己一时有感而发。

    http://www.cnblogs.com/huangxincheng/p/4025525.html

  • 相关阅读:
    软件测试面试题(一)
    测试面试题
    测试
    测试理论
    软件测试的认识
    理论知识
    H5页面的测试方式
    mysql数据库,linux,面试理论等
    登录设计点
    ATM境外取款测试点
  • 原文地址:https://www.cnblogs.com/pengkunfan/p/4031059.html
Copyright © 2020-2023  润新知