专栏名称: 程序猿
本微信公众号:imkuqin,为程序员提供最新最全的编程学习资料的查询。目前已经开通PHP、C/C++函数库、.NET Framework类库、J2SE API查询功能。
目录
相关文章推荐
程序员小灰  ·  为什么小时候上电脑课要穿鞋套? ·  3 天前  
码农翻身  ·  云开发时代,前端程序员太幸福了! ·  2 天前  
OSC开源社区  ·  树莓派完全从X11迁移到Wayland,所有 ... ·  4 天前  
OSC开源社区  ·  2024年度郑州软件产业市场分布报告 ·  3 天前  
程序员的那些事  ·  Linux ... ·  6 天前  
51好读  ›  专栏  ›  程序猿

我的一个朋友过来面试引发我要说的一个小话题

程序猿  · 公众号  · 程序员  · 2016-09-07 18:09

正文

来自:一线码农 - 博客园

作者微博@米铺高级架构师

链接:http://www.cnblogs.com/huangxincheng/p/4025525.html(点击尾部阅读原文前往)

已获转载授权


在很多家公司面试,也包括在携程,大多都会被问到一些算法的问题,其中机票事业部的面试,基本上算是算法问题的重灾区,没办法,有几个领导喜欢用数据结构来考人家,其中包括一些常见数据结构的复杂度以及手写一些算法,比如快排,单链表等等,前几天我一个推荐过来的朋友膝盖就被中了一箭。


题目就不方便具体说了,第一小问就是用非递归来构建一个单链表,我们知道构建单链表可以说是学数据结构的基本功,一说到用链式结构,它跟递归又有了千丝万缕的联系,很多链式的问题,我们用递归就可以轻轻松松的解决,几乎不需要动一下脑子,但是如果用非递归的话,那就稍微比递归要复杂一点了,起码会多考一个引用类型内存分配的问题。


后来QQ上我就用递归和非递归的形式构建单链表回复了他,先给了一个递归的版本,这个没问题,可以消化,然后给了一个非递归的版本,看了之后就扛不住了。


一:递归版本

class LinkList   
    {   
        public class LinkNode   
        {   
            public int data;   

            public LinkNode next;   
        }   

        private LinkNode head;   

        public void Add(int data)   
        {   
            if (head == null)   
            {   
                head = new LinkNode() { data = data };   
            }   
            else   
            {   
                Add(head, data);   
            }   
        }   

        public void Add(LinkNode node, int data)   
        {   
            if (node.next == null)   
            {   
                node.next = new LinkNode() { data = data };   
                return;   
            }   

            Add(node.next, data);   
        }   
    }

二:非递归版本

class LinkList   
    {   
        public class LinkNode   
        {   
            public int data;   

            public LinkNode next;   
        }   

        private LinkNode head;   

        public void Add(int data)   
        {   
            LinkNode node = new LinkNode() { data = data };   

            if (head == null)   
            {   
                head = node;   
            }   
            else   
            {   
                LinkNode temp = head;   

                while (temp.next != null)   
                {   
                    temp = temp.next;   
                }   

                temp.next = node;   
            }   
        }   
    }

这个非递归不理解的地方在于临时变量temp,提出的问题就是为什么:“temp.next=node” 之后,head的值发生了改变?我想之所以不能理解,绝逼是对引用类型的内存分配不了解,而这个非递归版本恰恰就是用引用类型这个内存分配技巧来实现 ”非递归构建单链表“。。。为了不让别人踩上这个坑,我还是大概说一下流程,大概是这样的,当我们在new一个引用类型的时候,CLR就要计算实例字段和所有基类上的实例字段的大小,然后再在堆上分配合理的内存块,最后把堆上的内存块的首地址保存在栈上面。

 

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


第一句:

LinkNode temp = head;

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




第二句: 从这句while中可以看到,一直在找instance的next,可以看出之后把instance2的内存地址给了temp,再next之后就把instance3的内存地址给了temp,然后就发现instance3的next为null,然后就跳出循环。

while (temp.next != null)   
                 {   
                    temp = temp.next;   
                 }



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

temp.next = node;



可以看到这时候instance4就构造到了instance3之后,同时temp.next已经是保存instance4的内存地址,这一些操作对head来说都是透明的,它也不管后面怎么操作,当你遍历head的时候会惊奇的发现居然我的链表中多了一个instance4,这个也就是朋友疑惑的地方,如果看到这个内存分配图的话,也许会豁然开朗,当然这篇博文没什么技术含量,也是自己一时有感而发。



本文编号1917,以后想阅读这篇文章直接输入1917即可。

●本文分类“算法搜索分类名可以获得相关文章。

●输入m可以获取到文章目录

本文内容的相关公众号推荐

算法与数据结构

DotNet程序员


更多推荐请看15个技术类公众微信


涵盖:程序人生、算法与数据结构、黑客技术与网络安全、大数据技术、前端开发、Java、Python、Web开发、安卓开发、iOS开发、C/C++、.NET、Linux、数据库、运维等。传播计算机学习经验、推荐计算机优秀资源:点击前往《值得关注的15个技术类微信公众号