日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

一:鏈表是什么

 

1、鏈表是物理存儲單元上非連續的、非順序的存儲結構,數據元素的邏輯順序是通過鏈表的指針地址實現,有一系列結點(地址)組成,結點可動態的生成。

 

2、結點包括兩個部分:(1)存儲數據元素的數據域(內存空間),(2)存儲指向下一個結點地址的指針域。

 

3、相對于線性表順序結構,操作復雜。

 

4.鏈表分為 (1)單鏈表 (2)雙鏈表 (3)單向循環鏈表 (4)雙向循環鏈表

 

二:鏈表的作用

 

1、實現數據元素的存儲按一定順序儲存,允許在任意位置插入和刪除結點。

 

2、包括單向結點,雙向結點,循環接點

 

三:鏈表與數組的區別

說到鏈表那肯定要聊一下數組,為什么會出現鏈表呢?

 

(1)數組:使用一塊連續的內存空間地址去存放數據,但

 

例如:

int  a[5]={1,2,3,4,5}。突然我想繼續加兩個數據進去,但是已經定義好的數組不能往后加,只能通過定義新的數組

 

int b[7]={1,2,3,4,5,6,7};      ***********這樣就相當不方便比較浪費內存資源,對數據的增刪不好操作。

 

(2)鏈表:使用多個不連續的內存空間去存儲數據, 可以 節省內存資源(只有需要存儲數據時,才去劃分新的空間),對數據的增刪比較方便。

 

四、鏈表的優缺

優點:

(1)插入和刪除速度快,保留原有的物理順序,在插入或者刪除一個元素的時候,只需要改變指針指向即可。(2)沒有空間限制,存儲元素無上限,只與內存空間大小有關。(3)動態分配內存空間,不用事先開辟內存

 

缺點:

(1)占用額外的空間以存儲指針,比較浪費空間,不連續存儲,malloc函數開辟空間碎片比較多) (2) 查找速度比較慢,因為在查找時,只能順序查找,需要循環鏈表

 

五、關于頭指針,頭節點,首元節點的那些事

頭指針:指向鏈表第一個節點的指針(不一定是頭節點,因為……鏈表要是沒有頭節點呢?),沒有實際開辟空間 (即沒有用malloc等動態分配內存) 而且必須存在,因為頭指針不存在,就不便于對鏈表進行操作。

 

頭節點:不是必須存在(若存在則為鏈表的第一個節點)其主要作用是使所有鏈表(包括空表)的頭指針非空,并使對單鏈表的插入、刪除操作不需要區分是否為空表或是否在第一個位置進行(還是挺有用的)。其數據域可以不儲存任何數據,若儲存則通常是鏈表的長度啥的。

 

首元節點:第一個數據域中儲存有效數據的節點 若頭節點不存在 則其為鏈表的第一個節點,是一定要存在的(除非是空表)

 

有關鏈表的一些操作

1.單鏈表 

節點結構默認為:

 

struct ListNode

{

int val;

struct ListNode *next;

}

 

①單鏈表的創建

//創建鏈表 

struct ListNode* createList()

{

    struct ListNode*p=NULL,*tail=NULL,*head=NULL;//p為待開辟的節點指針,tail為指向鏈表尾部的指針,head為指向鏈表頭部的指針。

                                  //筆者喜歡在創建鏈表時 創建head tail 兩個指針 雖然不一定都用得到

    int num;                        //將指針置空是個好習慣 

    scanf("%d",&num);

    //尾插法  順序插法 

    while(num!=-1)//假設以num/val值為-1作為鏈表的結束標志  或者你用定長條件也行 

    {

       p=(struct ListNode*)malloc(sizeof(struct ListNode));//注意此處用sizeof計算大小時在ListNode前要加struct關鍵字

       p->val=num;

       p->next=NULL;

       if(head==NULL)//第一次循環時將頭指針head指向p 

       {

           head=p;    

       } 

       else

       {

          tail->next=p;    

       } 

       tail=p;//此句放else里面也行  筆者更喜歡在第一次循環時就將tail與p與head產生關聯 

       scanf("%d",&num); 

    } 

//    頭插法   逆序插法 

//    while(num!=-1)

//    {

//        p=(struct ListNode*)malloc(sizeof(struct ListNode));

//        p->val=num;

//        if(head==NULL)

//        {

//            head=p;

//        }

//        else

//        {

//           p->next=head;

//           head=p;    

//        }

//    } 

    tail->next=NULL//用p->next也行 這是尾插法 

    return head;//返回鏈表頭指針                              

②鏈表節點的插入

 

struct ListNode *insertList(ListNode *head,int index,int num)//index 表示在鏈表中插入的位置(從1開始)原位置的元素接在其后  num表示要插入的數值

{

    struct ListNode *p=NULL,q;//在此q為虛擬節點 主要方便對鏈表進行操作 

    int cnt=1;//計數器從1開始計數

    if(head==NULL&&head->next==NULL)//鏈表為空 返回一個空指針 

    return NULL; 

    if(index==1)//若插在頭結點(在此特指鏈表的第一個節點)的位置

    {

        p=(struct ListNode*)malloc(sizeof(struct ListNode));//給p開辟實際空間 用來儲存操作存入的值 

        p->val=num;

        p->next=head; 

        head=p; 

    } 

    else 

    {

        q=head;

        while(q->next!=NULL&&cnt<=index)//對于鏈表我們通常對當前節點的下一個節點進行操作 

        {

            if(cnt+1<index)//為什么要加一呢?因為表示下一個位置 

            {

                q=q->next; 

            }

            else

            {

                p=(struct ListNode *)malloc(sizeof(struct ListNode));

                p->val=num;

                p->next=q->next;

                q->next=q;    

            }

        }

    }

    if(cnt<index)//如果cnt還是 小于 index 則表明插在鏈表末尾 

    {

        p=(struct ListNode*)malloc(sizeof(struct ListNode));

        p->val=num;

        p->next=NULL;

        q->next=p;

    } 

    return head;

}   

 

③鏈表節點的刪除

 

struct ListNode *deleteList(struct ListNode *head,int num)//執行刪除節點val值為num的操作

{

    struct ListNode *p=NULL,*q=NULL;//p,q均為輔助指針 不給他們開辟實際空間 

    if(head->val==num)//若刪除節點為頭結點 

    {

           p=head;

           head=head->next;

           free(p);

    } 

    else//若刪除節點為除頭結點外的其他節點 

    {

        p=head;

        while(p->next!=NULL)

        {

            if(p->next->val==num)

            {

                q=p->next;

                p->next=p->next->next;

                free(q);    

            } 

            else

            {

                p=p->next;

            }

        }

    }

    return head; 

     

鏈表的遍歷

 

void printList(struct ListNode *head)

{

    struct ListNode *p=head;//p依然為輔助指針

    while(p!=NULL)//因為是遍歷(打印輸出)操作 所以對當前節點進行操作即可 

    {

       printf("%d",p->val);

       p=p->next; 

    } 

}

 

雙向鏈表

雙向鏈表即單鏈表由單向的鏈變成了雙向的鏈(一個指針域(next)變成一前一后兩個指針域(prev,next)) 這里只演示雙向鏈表的創建

另:

節點結構為:

 

struct ListNode

{

int val;

ListNode *prev;

ListNode *next;

};

 

雙向鏈表的創建 

struct ListNode *createDbList()

{

    struct ListNode*p=NULL,*head=NULL,*tail=NULL;

    int num;

    scanf("%d",&num);

    while(num!=-1)//以-1作為創建鏈表結束的標志 

    {

        p=(struct ListNode*)malloc(sizeof(struct ListNode));

        p->val=num;

        if(head==NULL)//這里主要演示尾插法 

        {

           head=p;    

           p->prev=NULL; //就不將雙向鏈表和循環鏈表相互摻和了 

        } 

        else

        {

          tail->next=p;

          p->prev=tail;     

        }

        tail=p;

    } 

    tail->next=NULL;

}

 

循環鏈表

即將鏈表首尾相接 同樣這里只演示循環鏈表的創建

 

struct ListNode *createList()

{

    struct ListNode*p,*head,*tail;

    int num;

    scanf("%d",&num);

    while(num!=-1)

    {

       p=(struct ListNode*)malloc(sizeof(struct ListNode));

       p->val=num;

       if(head==NULL)

       {

          head=p;    

       }    

       else

       {

             tail->next=p;

       }

       tail=p;

    }

    tail->next=head;//創建結束后將鏈表首尾相接    

 

靜態鏈表

靜態鏈表的節點通常用結構體數組表示

 

struct  staticListNode

   int val;

   int cur;//游標cur用來儲存后繼節點的下標

};

 

 

1.Floyd判圈法:判斷鏈表是否有環(快慢指針的應用)

 

 

對于鏈表找環路的問題,有一個通用的解法——快慢指針(Floyd) 。給定兩個指針, 分別命名為 slow 和 fast ,起始位置在鏈表的開頭。每次 fast 前進兩步, slow 前進一步。如果 fast 可以走到盡頭,那么說明沒有環路;如果fast 可以無限走下去,那么說明一定有環路,且一定存 在一個時刻 slow 和 fast 相遇。當 slow 和 fast 第一次相遇時,我們將 fast 重新移動到鏈表開頭,并 讓 slow 和 fast 每次都前進一步。當 slow 和 fast 第二次相遇時,相遇的節點即為環路的開始點。

 

2. 判斷兩個鏈表是否相交

 

 

假設鏈表 A 的頭節點到相交點的距離是 a,鏈表 B 的頭節點到相交點的距離是 b,相交點到鏈表終點的距離為 c。我們使用兩個指針,分別指向兩個鏈表的頭節點,并以相同的速度前進,若到達鏈表結尾,則移動到另一條鏈表的頭節點繼續前進。按照這種前進方法,兩個指針會在a + b + c 次前進后同時到達相交節點

————————————————

版權聲明:本文為CSDN博主「legendarykk」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。

原文鏈接:https://blog.csdn.NET/legendarykk/article/details/125592024

分享到:
標簽:鏈表
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定