关于链表的一些逻辑思维

写这个东西的原因

  • 大学也即将毕业了,很多算法和数据结构的东西可能在iOS开发中并不能用得上,曾经有颗去BAT的心,错过了校招,希望厚积薄发,两三年后或许还有机会。记录下,那些大学里为之痴迷的东西。

什么是链表?

  • 对于计算机而言,大多数数据和信号的存储方式是离散的。那么今天要介绍的链表,就是一种离散结构的数据结构。与之对应的数组,是一种连续的数据结构。
  • 先来看一张相对形象的图。


    list.jpg

定义链表的节点

  • 由于链表是由多个链表节点,连接而成。先看看如何定义一个节点吧,其实就是个结构体。
typedef struct Node {
     int val;                  //数据域
     struct Node *next;        //指针域
}pNode;
  • 一个节点中包含数据域和指针域,数据域用于存储节点的数据信息,而指针next则指向下一个节点的地址。从内存的角度来看,它便是离散的,因为指向的下一块内存不是连续的。

如何创建单链表

  • 一条单链表中,必不可少的是头节点,相当于一个标记。个人习惯在头节点保存链表节点的个数
//creat a list
inline Node *creat() {
     Node *head = (Node *)malloc(sizeof(Node *));
     head->next = NULL; //防止野指针
     return head;
}
  • 关于malloc(),我们可以通过这个函数对头节点分配堆上的内存空间用于存储节点信息。而sizeof关键字就是计算需要分配多少的空间了。这个地方存在一个<strong>字节对齐</strong>的问题。感兴趣的同学可以深入理解。

链表的插入

  • 头插法,效率高,也是C++ STL中使用的一种方式。
  • 尾插法,效率低,只是介绍下,毕竟还是有区别的。

头插法
  • 我们可以猜测,既然是头部插入,那我们插入的元素顺序就是逆序的。
//头插法,时间复杂度O(1)
inline void push_front(Node *head, const int _val) {
    if (!head) return ;  //判断链表是否存在,通过头指针是否为空
    Node *nNode = (Node *)malloc(sizeof(Node *));
    nNode->val = _val;
    Node *pNode = head->next;
    nNode->next = pNode;
    head->next = nNode;
    ++head->val;//统计节点个数
}
尾插法
  • 既然是尾部插入,那我们插入的元素顺序就是顺序的。
27 //尾插法,时间复杂度O(n)
 inline void push_back(Node *head, const int _val) {
     if (!head) return ;
     Node *nNode = (Node *)malloc(sizeof(Node *));
     nNode->val = _val;
     Node *pNode = head;
     while (pNode->next) {
         pNode = pNode->next;
     }
     pNode->next = nNode;
     nNode->next = NULL;
     ++head->val;//统计节点个数
 }
  • 我们不难发现,之所以时间复杂度为O(n),是因为,每次比头插法多花了一个while循环来遍历链表,直到找到链表的最后一个节点。

链表删除节点

  • 任何一种数据结构,必不可少的都包含增删查改的功能。删除也是链表操作中较为复杂的一个操作。时间复杂度即为查找删除节点的遍历的复杂度。
//删除链表中第一个值为_val的节点
inline void remove(Node *head, const int _val) {
    if (!head || !head->next) return ;
    Node *pNode = head;
    while (pNode->next) {
        if (pNode->next->val == _val) {
            //找到要删除的元素
            Node *dNode = pNode->next;
            pNode->next = dNode->next;
            if (!dNode->next) {
                 pNode->next = NULL;
            }
            free(dNode);
            --head->val;//更新节点统计
            break;
        }
        pNode = pNode->next;
    }
}

关于链表的一些巧妙应用

  • 偷懒:至于什么判断链表是不是为空,链表节点个数,或者查找链表中某个元素是否存在的函数,我就懒得介绍了。接下来看几个有趣的应用。

如何判断单链表是否存在自环
  • 这是前两年大公司非常喜欢问的一道题目,何谓自环?就是在链表中形成了一个循环。
  • 对于这个问题,有一个很棒的思路, <strong>那就是采用两个指针,一个指针从head开始,另一个从head->next开始,第一个指针每次只走一步,第二个指针每次走两步。正常不存在环的情况下,以第二个指针到达尾节点作为判断的依据,若是存在环,那必定这两个指针会相遇,那么指针相遇便能作为判断单链表中存在环的依据。</strong>
//判断单链表中是否存在自环 1代表存在,0则反之。
inline int judge_circle(Node *head) {
    if (!head || !head->next) return 0;
    Node *first = head->next, *second = head->next->next;
    while (second && first) {
        if (first == second) return 1;
        second = second->next->next;
        first = first->next;
    }
    return 0;
}

翻转整条单链表

//翻转整条链表,时间复杂度为O(n)
inline Node *reverse(Node *head) {
    if (!head || !head->next) return head;
    Node *pNode = head, *qNode = pNode->next;
    pNode->next = NULL;
    if (!qNode->next) {
        head = qNode;
        qNode->next = pNode;
        return head;
    }
    while (qNode->next) {
        head = qNode->next;
        qNode->next = pNode;
        pNode = qNode;
        qNode = head;
    }
    head->next = pNode;
    return head;
}

总结:先记录这么多吧,还有些题目暂时还没时间去整理出来。接下来有时间会持续更新。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • //leetcode中还有花样链表题,这里几个例子,冰山一角 求单链表中结点的个数----时间复杂度O(n)这是最...
    暗黑破坏球嘿哈阅读 1,471评论 0 6
  • 作为一个资深的新手程序员😂,链表这些既基础又深奥的东西是日常工作中并不常见,但是却非常重要,所以就总结一下链表的简...
    Clark_new阅读 4,140评论 4 12
  • 本文内容取自于小甲鱼的数据结构与算法。http://www.jianshu.com/p/230e6fde9c75 ...
    阿阿阿阿毛阅读 2,764评论 0 7
  • LeetCode 刷题随手记 - 第一部分 前 256 题(非会员),仅算法题,的吐槽 https://leetc...
    蕾娜漢默阅读 16,519评论 2 36
  • 1 序 2016年6月25日夜,帝都,天下着大雨,拖着行李箱和同学在校门口照了最后一张合照,搬离寝室打车去了提前租...
    RichardJieChen阅读 5,016评论 0 12