欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

c語言單鏈表尾添加的深入講解

 更新時間:2020年12月22日 10:11:00   作者:24mamba  
這篇文章主要給大家介紹了關(guān)于c語言單項鏈表尾添加的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

猶豫了幾天,看了很多大牛寫的關(guān)于c語言鏈表,感觸很多,終于下定決心,把自己對于鏈表的理解隨之附上,可用與否,自行裁奪。由于作者水平有限也是第一次寫,不足之處,竭誠希望得到各位大神的批評指正。制作不易,不喜勿噴,謝謝?。。?/p>

在正文開始之前,我先對數(shù)組和鏈表進(jìn)行簡單的對比分析。

鏈表也是一種很常見的數(shù)據(jù)結(jié)構(gòu),不同于數(shù)組的是它是動態(tài)進(jìn)行存儲分配的一種結(jié)構(gòu)。數(shù)組存放數(shù)據(jù)時,必須要事先知道元素的個數(shù)。舉個例子,比如一個班有40個人,另一個班有100個人,如果要用同一個數(shù)組先后來存放這兩個班的學(xué)生數(shù)據(jù),那么必須得定義長度為100的數(shù)組。如果事先不確定一個班的人數(shù),只能把數(shù)組定義的足夠大,以能存放任何班級的學(xué)生數(shù)據(jù)。這樣就很浪費(fèi)內(nèi)存,而且數(shù)組對于內(nèi)存的要求必須是是連續(xù)的,數(shù)據(jù)小的話還好說,數(shù)據(jù)大的話內(nèi)存分配就會失敗,數(shù)組定義當(dāng)然也就失敗。還有數(shù)組對于插入以及刪除元素的效率也很低這就不一一介紹了。然而鏈表就相對于比較完美,它很好的解決了數(shù)組存在的那些問題。它儲存數(shù)據(jù)時就不需要分配連續(xù)的空間,對于元素的插入以及刪除效率就很高??梢哉f鏈表對于內(nèi)存就是隨用隨拿,不像數(shù)組要事先申請。當(dāng)然,有優(yōu)點(diǎn)就必然有缺點(diǎn),就比如說鏈表里每一個元素里面都多包含一個地址,或者說多包含一個存放地址的指針變量,所以內(nèi)存開銷就很大。還有因為鏈表的內(nèi)存空間不是連續(xù)的,所以想找到其中的某一個數(shù)據(jù)就沒有數(shù)組那么方便,必須先得到該元素的上一個元素,根據(jù)上一個元素提供的下一元素地址去找到該元素。所以不提供“頭指針”(下文中“頭指針”為“PHead”),那么整個鏈表將無法訪問。鏈表就相當(dāng)于一條鐵鏈一環(huán)扣一環(huán)(這個稍后會詳細(xì)的說)。

鏈表

上面我提到過鏈表是動態(tài)進(jìn)行存儲分配的一種結(jié)構(gòu)。鏈表中的每一個元素稱為“結(jié)點(diǎn)”,每個結(jié)點(diǎn)都包括兩部分:一部分為用戶需要的實(shí)際數(shù)據(jù),另一部分為下一結(jié)點(diǎn)的地址。鏈表有一個“頭指針(PHead)”變量,存放著一個地址,該地址指向第一個結(jié)點(diǎn),第一個結(jié)點(diǎn)里面存放著第二個結(jié)點(diǎn)的地址,第二個結(jié)點(diǎn)又存放著第三個結(jié)點(diǎn)地址。就這樣頭指針指向第一個結(jié)點(diǎn),第一個結(jié)點(diǎn)又指向第二個......直到最后一個結(jié)點(diǎn)。最后一個結(jié)點(diǎn)不再指向其他結(jié)點(diǎn),地址部分存放一個“NULL”。 見下圖:(表中有一個尾指針(PEnd)其作用后面會解釋)

c語言單項鏈表尾添加整體代碼如下:(詳解附后)

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


//函數(shù)聲明
//尾添加
void wei_tian_jia(struct NODE** PHEAD, struct NODE** PEND, int shu_ju);
//尾添加(沒有尾指針)
void wei_tian_jia_(struct NODE** PHEAD, int shu_ju);
//釋放鏈表
void shi_fang_lian_biao(struct NODE* PHEAD);
//釋放鏈表(并是頭指針(PHead)尾指針(PEnd)指向空)
void shi_fang_lian_biao_free(struct NODE** PHEAD, struct NODE** PEnd);
//輸出鏈表
void shu_chu(struct NODE* PHEAD);


//定義一個鏈表結(jié)構(gòu)體
struct NODE
{
  int shu_ju;      //用戶需要的實(shí)際數(shù)據(jù)
  struct NODE* PNext;  //下一結(jié)點(diǎn)的地址

};


int main(void)
{
  //創(chuàng)建頭尾指針
  struct NODE* PHead = NULL;
  struct NODE* PEnd = NULL;


  //尾添加
  wei_tian_jia(&PHead, &PEnd, 17);
  wei_tian_jia(&PHead, &PEnd, 21);
  wei_tian_jia(&PHead, &PEnd, 34);
  wei_tian_jia(&PHead, &PEnd, 8);
  wei_tian_jia(&PHead, &PEnd, 24);

  //尾添加(沒有尾指針)
  //wei_tian_jia_(&PHead, 23);
  //wei_tian_jia_(&PHead, 17);
  //wei_tian_jia_(&PHead, 11);

  //輸出鏈表
  shu_chu(PHead);

  //釋放鏈表
  //shi_fang_lian_biao(PHead);

  //釋放鏈表(并是頭指針(PHead)尾指針(PEnd)指向空)
  shi_fang_lian_biao_free(&PHead, &PEnd);


  system("pause");
  return 0;
}

//尾添加
void wei_tian_jia(struct NODE** PHEAD, struct NODE** PEND, int SHU_JU)
{
  //創(chuàng)建結(jié)點(diǎn)
  struct NODE* PTEMP = (struct NODE*)malloc(sizeof(struct NODE));
  if (PTEMP != NULL)
  {
    //節(jié)點(diǎn)賦值
    PTEMP->shu_ju = SHU_JU;
    PTEMP->PNext = NULL;

    //把結(jié)點(diǎn)連起來
    if (NULL == *PHEAD) // 因為PHEAD如果是NULL的話 PEND也就是NULL 所以條件里面不必要寫
    {
      *PHEAD = PTEMP;
      *PEND = PTEMP;
    }
    else
    {
      (*PEND)->PNext = PTEMP;
      *PEND = PTEMP;

    }
  }  
}

//尾添加(沒有尾指針)
void wei_tian_jia_(struct NODE** PHEAD1, int SHU_JU)
{
  //創(chuàng)建結(jié)點(diǎn)
  struct NODE* PTEMP = (struct NODE*)malloc(sizeof(struct NODE));

  if (PTEMP != NULL)
  {
      //結(jié)點(diǎn)成員賦值
    PTEMP->shu_ju = SHU_JU;
    PTEMP->PNext = NULL;

    //把結(jié)點(diǎn)連一起
    if (NULL == *PHEAD1)
    {
      *PHEAD1 = PTEMP;
    }
    else 
    {
      struct NODE* PTEMP2 = *PHEAD1;
      while (PTEMP2->PNext != NULL)
      {
        PTEMP2 = PTEMP2->PNext;
      }
      PTEMP2->PNext = PTEMP;
    }

  }

}

//輸出鏈表
void shu_chu(struct NODE* PHEAD)
{
  while (PHEAD != NULL)
  {
    printf("%d\n", PHEAD->shu_ju);
    PHEAD = PHEAD->PNext;

  }

}

//釋放鏈表
void shi_fang_lian_biao(struct NODE* PHEAD)
{
  struct NODE* P = PHEAD;
  while (PHEAD != NULL)
  {
    struct NODE* PTEMP = P;
    P = P->PNext;
    free(PTEMP);
  }
  free(PHEAD);

}
//釋放鏈表(并是頭指針(PHead)尾指針(PEnd)指向空)
void shi_fang_lian_biao_free(struct NODE** PHEAD, struct NODE** PEnd)
{
  
    while (*PHEAD != NULL)
    {
      struct NODE* PTEMP = *PHEAD;
       *PHEAD = (*PHEAD)->PNext;
      free(PTEMP);
    }
    *PHEAD = NULL;
    *PHEAD = NULL;


}

部分代碼詳解:(再次申明:由于作者水平有限,所以有的變量名用的拼音。見笑,莫怪?。?!為了簡單明了,方便起見,我定義了一個實(shí)際數(shù)據(jù)。)

“頭指針”(PHead)以及“尾指針”(PEnd):

頭指針很好理解指向首結(jié)點(diǎn)用于遍歷整個數(shù)組,而尾指針呢?我們先看下面兩段代碼一段是有尾指針的一段是沒有尾指針的:

//尾添加
void wei_tian_jia(struct NODE** PHEAD, struct NODE** PEND, int SHU_JU)
{
  //創(chuàng)建一個結(jié)點(diǎn)
  struct NODE* PTEMP = (struct NODE*)malloc(sizeof(struct NODE));
  if (PTEMP != NULL)
  {
    //節(jié)點(diǎn)成員賦值(一定要每個成員都要賦值)
    PTEMP->shu_ju = SHU_JU;
    PTEMP->PNext = NULL;

    //把結(jié)點(diǎn)連起來
    if (NULL == *PHEAD) // 因為PHEAD如果是NULL的話 PEND也就是NULL 所以條件里面不必要寫
    {
      *PHEAD = PTEMP;
      *PEND = PTEMP;
    }
    else
    {
      //把尾指針向后移
      (*PEND)->PNext = PTEMP;
      *PEND = PTEMP;

    }

  }
  
}

那么下面這段代碼是沒有尾指針的。它的思想就是頭指針一直指向第一個結(jié)點(diǎn),然后通過遍歷來找到最后一個結(jié)點(diǎn),從而使最后一個結(jié)點(diǎn)里面的指針指向所要插入的元素。

//尾添加(沒有尾指針)
void wei_tian_jia_(struct NODE** PHEAD1, int SHU_JU)
{
  //創(chuàng)建結(jié)點(diǎn)
  struct NODE* PTEMP = (struct NODE*)malloc(sizeof(struct NODE));

  if (PTEMP != NULL)
  {
    //結(jié)點(diǎn)成員賦值
    PTEMP->shu_ju = SHU_JU;
    PTEMP->PNext = NULL;

    //把結(jié)點(diǎn)連一起  
    if (NULL == *PHEAD1)
    {
      *PHEAD1 = PTEMP;

    }
    else 
    {
      struct NODE* PTEMP2 = *PHEAD1;
      while (PTEMP2->PNext != NULL)
      {
        PTEMP2 = PTEMP2->PNext;
      }
      PTEMP2->PNext = PTEMP;
    }

  }

}

我把上面代碼里面的一段摘出來說明一下。

這段代碼里面可以看到我又定義了一個PTEMP2指針變量,為什么呢?前面我提到過沒有尾指針的時候添加結(jié)點(diǎn)的思想就是要遍歷數(shù)組,從而找到最后一個結(jié)點(diǎn)然后讓它指向我們要插入的結(jié)點(diǎn),如果沒有這個PHEAD2,我們遍歷完鏈表以后我們的頭指針PHEAD1就已經(jīng)指向了最后一個結(jié)點(diǎn)了,單項鏈表如果頭指針移動了,數(shù)據(jù)就會找不到了。所以我定義了一個中間變量裝著頭指針然后去遍歷鏈表,讓頭指針永遠(yuǎn)指向鏈表的頭。

else 
    {
      struct NODE* PTEMP2 = *PHEAD1;
      while (PTEMP2->PNext != NULL)
      {
        PTEMP2 = PTEMP2->PNext;
      }
      PTEMP2->PNext = PTEMP;
    }

可以看到有尾指針的代碼和沒有尾指針的代碼里面,有尾指針的鏈表里面我每次添加完數(shù)據(jù)都讓尾指針指向最后一個結(jié)點(diǎn),然后通過尾指針來添加數(shù)據(jù)。而沒有尾指針的鏈表里面每次添加數(shù)據(jù)都要通過循環(huán)來遍歷鏈表找到最后一個結(jié)點(diǎn)然后指向所添加的結(jié)點(diǎn)。如果一個鏈表里面有幾萬個結(jié)點(diǎn),每次都通過循環(huán)遍歷鏈表來添加數(shù)據(jù),那么速度就相對于有尾指針的鏈表慢很多??偠灾?,還是看個人愛好吧。不管黑貓還是白貓能抓到耗子都是好貓。

總結(jié)

到此這篇關(guān)于c語言單鏈表尾添加的文章就介紹到這了,更多相關(guān)c語言單鏈表尾添加內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 淺談c++11閉包的實(shí)現(xiàn)

    淺談c++11閉包的實(shí)現(xiàn)

    閉包有很多種定義,一種說法是,閉包是帶有上下文的函數(shù)。說白了,就是有狀態(tài)的函數(shù)。更直接一些,不就是個類嗎?換了個名字而已。本文將介紹c++11閉包的實(shí)現(xiàn),感興趣的同學(xué),可以參考下。
    2021-06-06
  • C語言實(shí)現(xiàn)簡單的推箱子小游戲

    C語言實(shí)現(xiàn)簡單的推箱子小游戲

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)簡單的推箱子小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • C語言16進(jìn)制與ASCII字符相互轉(zhuǎn)換

    C語言16進(jìn)制與ASCII字符相互轉(zhuǎn)換

    大家好,本篇文章主要講的是C語言16進(jìn)制與ASCII字符相互轉(zhuǎn)換,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • c++中cin/cout與scanf/printf的區(qū)別比較

    c++中cin/cout與scanf/printf的區(qū)別比較

    這篇文章主要介紹了c++中cin/cout與scanf/printf的區(qū)別比較,需要的朋友可以參考下
    2017-06-06
  • 解決Qt設(shè)置QTextEdit行高的問題

    解決Qt設(shè)置QTextEdit行高的問題

    這篇文章介紹了Qt設(shè)置QTextEdit行高的方法,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • C語言實(shí)現(xiàn)簡單的通訊錄管理系統(tǒng)

    C語言實(shí)現(xiàn)簡單的通訊錄管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • C語言實(shí)現(xiàn)單鏈表逆序與逆序輸出實(shí)例

    C語言實(shí)現(xiàn)單鏈表逆序與逆序輸出實(shí)例

    這篇文章主要介紹了C語言實(shí)現(xiàn)單鏈表逆序與逆序輸出,是數(shù)據(jù)結(jié)構(gòu)與算法中比較基礎(chǔ)的重要內(nèi)容,有必要加以牢固掌握,需要的朋友可以參考下
    2014-08-08
  • C++泛型編程函(數(shù)模板+類模板)

    C++泛型編程函(數(shù)模板+類模板)

    這篇文章主要介紹了C++泛型編程函(數(shù)模板+類模板),類模板與函數(shù)模板一樣也會經(jīng)過兩次編譯,在此文中重點(diǎn)區(qū)分一下類模板與模板類,函數(shù)模板與模板函數(shù)的概念,泛型編程是C++開發(fā)的一大精髓,靈活地運(yùn)用泛型編程,需要的朋友可以參考一下
    2022-02-02
  • C語言 聯(lián)合(union)用法案例詳解

    C語言 聯(lián)合(union)用法案例詳解

    這篇文章主要介紹了C語言 聯(lián)合(union)用法案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • 通過“回文字算法”復(fù)習(xí)C++語言

    通過“回文字算法”復(fù)習(xí)C++語言

    這篇文章主要介紹了通過“回文字算法”復(fù)習(xí)C++語言的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-10-10

最新評論