鏈表

鏈表結(jié)構(gòu)

鏈表是一種以不連續(xù)的方式存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)腰懂。對(duì)于最基本的單鏈表周叮,其每個(gè)節(jié)點(diǎn)不僅包含值val揩尸,也包含一個(gè)指向下一個(gè)節(jié)點(diǎn)地址的指針next。以C語言實(shí)現(xiàn)為例:

#include<stdio.h>
#include<stdlib.h>

struct ListNode 
{
    int val;
    struct ListNode *next;
};

//判斷鏈表為空
int isEmpty(struct ListNode *head)
{
    return head==NULL;
}

//查找節(jié)點(diǎn),找不到返回NULL
struct ListNode* find(int x, struct  ListNode* head)
{
    while(head && head->val!=x)
    {
        head=head->next;
    }
    return head;
}

//查找前驅(qū)節(jié)點(diǎn)
struct ListNode* findPrevious(int x, struct ListNode *head)
{
    if(head->val==x)
    {
        return NULL;
    }
    struct ListNode* pre = head;
    while(head && head->val!=x)
    {
        pre=head;
        head=head->next;
    }
    return head==NULL?NULL:pre;
}

//插入節(jié)點(diǎn)
void insertNode(int x, struct ListNode*position)
{
    struct ListNode *node = (struct ListNode *)malloc(sizeof(struct ListNode));
    node->val=x;
    struct ListNode *temp=position->next;
    position->next=node;
    node->next=temp;
}

//刪除節(jié)點(diǎn)
void deleteNode(int x, struct ListNode *head)
{

    //頭刪
    if(head->val==x)
    {
        struct ListNode *next = head->next;
        free(head);
        *head=*next;
    }
    struct ListNode *pre = findPrevious(x,head);
    if(pre)
    {
        struct ListNode *cur = pre->next;
        pre->next=cur->next;
        free(cur);
    }
}

void printList(struct ListNode *head)
{
    int idx = 0;
    while(head)
    {
        printf("%d --- element val is %d \n",idx,head->val);
        head=head->next;
    }
}

void main()
{
    struct ListNode *dumpy = (struct ListNode *)malloc(sizeof(struct ListNode));
    dumpy->val=1;
    dumpy->next=NULL;
    printList(dumpy);
    printf("is empty ? %s \n",isEmpty(dumpy)?"yes":"no");
    insertNode(2,find(1,dumpy));
    printf("after insert :\n");
    printList(dumpy);
    deleteNode(2,dumpy);
    printf("after delete :\n");
    printList(dumpy);
}

注意:free()函數(shù)不會(huì)刪除指針,而是將指針指向的內(nèi)存釋放话肖。在刪除節(jié)點(diǎn)的函數(shù)中北秽,如果是頭刪,先獲得后一個(gè)節(jié)點(diǎn)最筒,即第二個(gè)節(jié)點(diǎn)贺氓,然后將頭指針指向的內(nèi)存釋放,再將頭指針指向第二個(gè)節(jié)點(diǎn)床蜘,*head=*next.

鏈表算法題

解決鏈表的問題辙培,一般可以有兩種方法:迭代和遞歸。

題一:反轉(zhuǎn)鏈表

核心思路:讓節(jié)點(diǎn)的next值指向上一個(gè)節(jié)點(diǎn)邢锯,這里需要同時(shí)保存當(dāng)前節(jié)點(diǎn)和前一個(gè)節(jié)點(diǎn)扬蕊,并同時(shí)移動(dòng)。

  1. 雙指針迭代法

遍歷每個(gè)節(jié)點(diǎn)丹擎,并將當(dāng)前節(jié)點(diǎn)的next指向上一個(gè)節(jié)點(diǎn)尾抑。這里需要定義指針變量pre保存前一個(gè)節(jié)點(diǎn)的指針,初始化為NULL(因?yàn)榉崔D(zhuǎn)后的尾節(jié)點(diǎn)就是反轉(zhuǎn)前的首節(jié)點(diǎn)蒂培。),并定義指針變量cur保存遍歷到的節(jié)點(diǎn)再愈。 當(dāng)遍歷完成時(shí),pre保存的是原鏈表的尾節(jié)點(diǎn)护戳,也就是新鏈表的首節(jié)點(diǎn)翎冲。

//反轉(zhuǎn)鏈表
struct ListNode * reverseList(struct ListNode *head)
{
    //如果鏈表為空或者只有一個(gè)節(jié)點(diǎn),直接返回原鏈表
    if(!head || !head->next)
    {
        return head;
    }

    struct ListNode *cur = head;
    struct ListNode *pre = NULL;
    while(head)
    {
        head=head->next;
        cur->next=pre;
        pre=cur;
        cur=head;
    }
    return pre;
}
  1. 遞歸

遞歸函數(shù)的作用是讓節(jié)點(diǎn)的next指向上一節(jié)點(diǎn)媳荒。

//遞歸反轉(zhuǎn)
struct ListNode *reverseList2(struct ListNode *head)
{
    if(!head || !head->next)
    {
        return head;
    }

    struct ListNode *temp = reverseList2(head->next);
    head->next->next=head;
    head->next=NULL;
    return temp;
}
題二:合并連個(gè)有序鏈表

輸入兩個(gè)遞增排序的鏈表抗悍,合并這兩個(gè)鏈表并使新鏈表中的節(jié)點(diǎn)仍然是遞增排序的。

  1. 迭代法

定義一個(gè)新鏈表钳枕,一次比較兩個(gè)鏈表的值缴渊,取小的值加到新鏈表上,直到一個(gè)鏈表遍歷完畢么伯,將另一個(gè)鏈表的剩余部分加到新鏈表上疟暖。

//合并有序鏈表
struct ListNode *mergeList(struct ListNode * l1,struct ListNode* l2)
{
    struct ListNode* l3 = (struct ListNode *)malloc(sizeof(struct ListNode));
    struct ListNode* dumpy = l3;
    while(l1 && l2)
    {
        if(l1->val<l2->val)
        {
            l3->next=l1;
            l1=l1->next;
        }
        else
        {
            l3->next=l2;
            l2=l2->next;
        }
        l3=l3->next;
    }
    l3->next=l1==NULL?l2:l1;
    return dumpy->next;
}
  1. 遞歸

遞歸函數(shù)的作用是創(chuàng)建一個(gè)節(jié)點(diǎn),依次比較兩個(gè)鏈表值田柔,取小的值作為新節(jié)點(diǎn)的值俐巴,next指向的值也是通過比較所得。

struct ListNode* mergeList2(struct ListNode* l1,struct ListNode* l2)
{
    if(l1==NULL)
    {
        return l2;
    }
    if(l2==NULL)
    {
        return l1;
    }
    struct ListNode *node =  (struct ListNode *)malloc(sizeof(struct ListNode));
    if(l1->val<l2->val)
    {
        node->val=l1->val;
        node->next=mergeList2(l1->next,l2);
    }
    else
    {
        node->val=l2->val;
        node->next=mergeList2(l1,l2->next);
    }
    return node;
}

迭代法和遞歸法是處理鏈表問題的常見方法硬爆,迭代相對(duì)更好理解欣舵。
更多習(xí)題,詳見我的github

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缀磕,一起剝皮案震驚了整個(gè)濱河市缘圈,隨后出現(xiàn)的幾起案子劣光,更是在濱河造成了極大的恐慌,老刑警劉巖糟把,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绢涡,死亡現(xiàn)場離奇詭異,居然都是意外死亡遣疯,警方通過查閱死者的電腦和手機(jī)雄可,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缠犀,“玉大人数苫,你說我怎么就攤上這事”嬉海” “怎么了虐急?”我有些...
    開封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長滔迈。 經(jīng)常有香客問我止吁,道長,這世上最難降的妖魔是什么燎悍? 我笑而不...
    開封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任赏殃,我火速辦了婚禮,結(jié)果婚禮上间涵,老公的妹妹穿的比我還像新娘。我一直安慰自己榜揖,他們只是感情好勾哩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著举哟,像睡著了一般思劳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上妨猩,一...
    開封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天潜叛,我揣著相機(jī)與錄音,去河邊找鬼壶硅。 笑死威兜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的庐椒。 我是一名探鬼主播椒舵,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼约谈!你這毒婦竟也來了笔宿?” 一聲冷哼從身側(cè)響起犁钟,我...
    開封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎泼橘,沒想到半個(gè)月后涝动,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炬灭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年醋粟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片担败。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡昔穴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出提前,到底是詐尸還是另有隱情吗货,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布狈网,位于F島的核電站宙搬,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拓哺。R本人自食惡果不足惜勇垛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望士鸥。 院中可真熱鬧闲孤,春花似錦、人聲如沸烤礁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脚仔。三九已至勤众,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鲤脏,已是汗流浹背们颜。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留猎醇,地道東北人窥突。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像姑食,于是被迫代替她去往敵國和親波岛。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 搞懂單鏈表常見面試題 Hello 繼上次的 搞懂基本排序算法音半,這個(gè)一星期则拷,我總結(jié)了贡蓖,我所學(xué)習(xí)和思考的單鏈表基礎(chǔ)知識(shí)...
    醒著的碼者閱讀 4,579評(píng)論 1 45
  • 代碼GitHub地址 鏈表概述 數(shù)組和鏈表都是線性存儲(chǔ)結(jié)構(gòu)的基礎(chǔ)實(shí)現(xiàn),棧和隊(duì)列都是線性存儲(chǔ)結(jié)構(gòu)的應(yīng)用 數(shù)組優(yōu)缺點(diǎn) ...
    HikariCP閱讀 1,368評(píng)論 0 0
  • LeetCode-鏈表 鏈表(Linked List)是一種常見的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)煌茬,是一種線性表斥铺,但是并不會(huì)按線性的順...
    raincoffee閱讀 1,182評(píng)論 0 6
  • 一、前言 4月份報(bào)名參加了極客時(shí)間舉辦的第一期「算法訓(xùn)練營」坛善,兩天線下大課晾蜘,一個(gè)月線上課。 在做線上課程作業(yè)的過程...
    李眼鏡閱讀 680評(píng)論 0 0
  • 轉(zhuǎn)載請(qǐng)注明出處:http://www.reibang.com/p/c65d9d753c31 在上一篇博客《數(shù)據(jù)結(jié)構(gòu)...
    Alent閱讀 3,500評(píng)論 4 74