zoukankan      html  css  js  c++  java
  • 使用二级指针操作链表

    当然,我学的第一门编程语言是C语言(虽然现在很少使用C语言了,都是用一些抽象做的很高的语言),对于C语言,我是很、非常、及其的认真的学习,因为C是能够让你非常贴切的认识各种东西的语言,通过C语言你可以了解到编译原理的一些知识,可以辅助你读操作系统的源码,可以写一些高效的代码,当你学习汇编语言的时候,你会发现C语言与汇编语言的千丝万缕的联系,当你学习C++的时候的有C的基础是非常必要的。所以如果想学好编程,了解C语言是非常的必要的。

    当然每个学习过C的人都曾被C的指针折磨过(不过俺可没有,因为俺到后面关于指针的本质问题了解了,所以就可以以不变应万变了),虽说指针的原理我是非常的懂了,但是关于指针的一些用法,尤其是一些比较高端的用法,就拿二级指针来说吧,我总是觉得非要间接两次才能取到变量有啥意义,不过今天突然看到了一个使用二级指针的操作,非常好,在此分享一下。

    指针的一个重要的使用点是对于链表的操作。语言链表如果删除一个指定的节点的操作,通常的解决方案如下:

    typedef struct node
    {
        struct node *next;
        //satellite data...
        int data;
    }Node;
    
    
    typdef bool (* rmNode)(const Node *v);
    
    Node * removeIf(Node *head, rmNode rmFunc)
    {
        for(Node *pre=NULL, *current=head; current!=NULL;)
        {
            Node *next=current->next;
            if(rmNode(current))
            {
                if(pre==NULL)
                {
                    head=next;
                }
                else
                {
                    pre->next=next;
                }
                free(current);
            }
            else
            {
                pre=current;
                current=current->next;
            }
        }
    
        return head;
    }

    对于这个解决方案,你需要维护三个指针pre,current,next, 而且需要对head被删除做特殊的考虑,那么每次循环都会有判断的开销。

    而使用二级指针的解决方案可以做成如下的效果:

    void removeIf(Node **head, rmNode rmFunc)
    {
        for(Node** current=head; *current!=NULL)
        {
            Node *entry=(*current)->next;
            if(rmNode(entry))
            {
                (*current)=entry->next;
                free(current);
            }
            else
            {
                current=&(entry->next);
            }
    
        }
    }

    首先使用指针减少为两个了:current,entry ,而且不需要考虑首节点的情况,效率提高了。但是这个代码如果你对二级指针的理解不是很清楚的情况下,那么就不是特别的易读,当然你懂了那就另说了(虽然我懂了,但是感觉不写上一两百遍感觉还是不是特别容易的编程肌肉记忆)。

    附注:这个可以linux内核当中实用的单项,双向链表中经常用到的技巧,而且linus在新闻组还说过的。这个技巧是我从coolshell上面看到的,coolshell(www.coolshell.cn)是一个特别好的技术blog,里面有很多不错的东西,很是值得学习,而且可以放到rss上。

  • 相关阅读:
    BZOJ4039 : 集会
    BZOJ3655 : 神经错乱数
    World Finals 2017爆OJ记
    Petrozavodsk Summer-2016. Ural FU Dandelion Contest
    XVII Open Cup named after E.V. Pankratiev. Grand Prix of America (NAIPC-2017)
    递归的逻辑(3)——递归与分治
    递归的逻辑(2)——特征方程和递归算法
    递归的逻辑(1)——递归关系模型
    整数的故事(4)——Karastuba算法
    整数的故事(3)——最小公倍数与哥德巴赫猜想
  • 原文地址:https://www.cnblogs.com/dongyuanshi/p/3671425.html
Copyright © 2011-2022 走看看