Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 501|回复: 0

[默认分类] (原創) 簡單的Linked List實現 (C/C++) (C) (Data Structure)

[复制链接]
  • TA的每日心情
    开心
    2021-12-13 21:45
  • 签到天数: 15 天

    [LV.4]偶尔看看III

    发表于 2018-7-12 18:03:05 | 显示全部楼层 |阅读模式

    Abstraction
    使用C語言簡單的實現linked list,並用C++的std::vector實作出相同的功能作比較。
    Introduction
    學習資料結構,第一個要學的就是linked list,本文示範最簡單的linked list實現,包含建立與顯示,可把它當成linked list的標準範本,畢竟步驟都差不多。
    一個基本的問題:為什麼需要linked list?若要將大量資料存到記憶體,你會想到什麼?第一個想到的就是array,但C語言是個靜態語言,array必須事先宣告大小,這樣compiler才能進行最佳化,若到時候沒用這麼多記憶體,就白白浪費記憶體了。或許你會說array可以配合malloc()變成動態array,但前提是你必須告訴malloc()要建立多大的array,若連要建立多大的陣列也不確定,而是在run-time看有多少資料就建立多大,這時連malloc()的動態array也不能用了,此時就得靠linked list。
    linked list是資料結構的基礎,基本上就是靠struct如火車車廂那樣連在一起,run-time有需要時,在動態掛一個struct上去。
    C語言

    1
    /*
      

    2
    (C) OOMusou 2008
    http://oomusou.cnblogs.com


    3


    4
    Filename    : DS_linked_list_simple.c

    5
    Compiler    : Visual C++ 8.0

    6
    Description : Demo how to use malloc for linked list

    7
    Release     : 03/22/2008 1.0

    8

    */


    9
    #include
    <
    stdio.h
    >


    10
    #include
    <
    stdlib.h
    >


    11
    #include
    <
    string
    .h
    >


    12


    13

    #define
      SLEN 255


    14


    15

    struct
      list {

    16
       
    int
       no;

    17
       
    char
      name[SLEN];

    18
       
    struct
      list
    *
    next;

    19
    };

    20


    21

    int
      main() {

    22
       
    int
      no;

    23
       
    char
      s[
    255
    ];

    24
       

    25
       
    struct
      list
    *
    head   
    =
      NULL;

    26
       
    struct
      list
    *
    current
    =
      NULL;

    27
       
    struct
      list
    *
    prev   
    =
      NULL;

    28
       

    29
       
    while
    (
    1
    ) {

    30
         printf(
    "
    No. =
    "
    );

    31
         scanf(
    "
    %d
    "
    ,
    &
    no);

    32
         

    33
         
    if
      (no
    ==
      
    0
    )

    34
          
    break
    ;

    35
       

    36
         printf(
    "
    Name =
    "
    );

    37
         scanf(
    "
    %s
    "
    , s);

    38
         

    39
         current
    =
      (
    struct
      list
    *
    )malloc(
    sizeof
    (
    struct
      list));

    40
         
    if
      (current
    ==
      NULL)

    41
           exit(EXIT_FAILURE);

    42
          

    43
         current
    ->
    next
    =
      NULL;

    44
         

    45
         current
    ->
    no
    =
      no;

    46
         strncpy(current
    ->
    name, s, SLEN
    -
    1
    );

    47
         current
    ->
    name[SLEN
    -
    1
    ]
    =
      
    "
    \0
    "
    ;

    48
         

    49
         
    if
      (head
    ==
      NULL)

    50
           head
    =
      current;

    51
         
    else


    52
           prev
    ->
    next
    =
      current;

    53
          

    54
         prev
    =
      current;

    55
       }

    56
       

    57
       
    //
      display linked list


    58

       current
    =
      head;

    59
       
    while
    (current
    !=
      NULL) {

    60
         printf(
    "
    No. = %d, Name = %s\n
    "
    , current
    ->
    no, current
    ->
    name);

    61
         current
    =
      current
    ->
    next;

    62
       }

    63
       

    64
       
    //
      free linked list


    65

       current
    =
      head;

    66
       
    while
    (current
    !=
      NULL) {

    67
         prev
    =
      current;

    68
         current
    =
      current
    ->
    next;

    69
         free(prev);

    70
       }

    71
    }


    執行結果

    No.
    =
      
    1

    Name
    =
      clare
    No.
    =
      
    2

    Name
    =
      jessie
    No.
    =
      
    0

    No.
    =
      
    1
    ,
      Name
    =
      clare
    No.
    =
      
    2
    ,
      Name
    =
      jessie


    15行

    struct
      list {
      
    int
       no;
      
    char
      name[SLEN];
      
    struct
      list
    *
    next;
    };


    linked list的基礎就是struct,所以先建立一個自訂的struct型別,因為linked list是靠struct串聯起來,所以最後要多一個struct pointer指向下一個struct。
    25行

    struct
      list
    *
    head   
    =
      NULL;

    struct
      list
    *
    current
    =
      NULL;

    struct
      list
    *
    prev   
    =
      NULL;


    建立linked list最基本需要三個指標,head指向linked list的第一個struct,current指向目前剛建立的struct,prev則指向前一個struct,目的在指向下一個struct,對於未使用的pointer,一律指定為NULL,這是一個好的coding style,可以藉由判斷是否為NULL判斷此pointer是否被使用。
    39行

    current
    =
      (
    struct
      list
    *
    )malloc(
    sizeof
    (
    struct
      list));

    if
      (current
    ==
      NULL)
      exit(EXIT_FAILURE);
          
    current
    ->
    next
    =
      NULL;


    每當有新資料,需要建立一個新的struct時,就用malloc()要一塊記憶體,由於malloc()傳回的是void *,所以要手動轉型成struct list *。但malloc()並不是一定會成功,若記憶體不足時,仍然會失敗,所以必須判斷是否傳回NULL。
    由於一個新的node,一定是linked list最後一個node,所以將current->next接null。

    45行

    current
    ->
    no
    =
      no;
    strncpy(current
    ->
    name, s, SLEN
    -
    1
    );
    current
    ->
    name[SLEN
    -
    1
    ]
    =
      
    "
    \0
    "
    ;


    正式將輸入的資料填進struct,至於為什麼要用strncpy()而不用strcpy()呢?雖然strcpy()也可以,但strncpy()比較安全,若輸入的字串大小超過struct所定義的字串大小,則會只接受struct所接受的字串大小,而不會因為找不到"\0"而造成程式錯誤。
    49行

    if
      (head
    ==
      NULL)
      head
    =
      current;

    else

      prev
    ->
    next
    =
      current;
          
    prev
    =
      current;


    判斷若是第一個node,則將目前的node當成head,若不是第一個node,則將前一個node指向目前的node,完成linked list的連接。最後將目前的node當成前一個node,以備指向下一個node。
    58行

    //
      display linked list


    current
    =
      head;

    while
    (current
    !=
      NULL) {
      printf(
    "
    No. = %d, Name = %s\n
    "
    , current
    ->
    no, current
    ->
    name);
      current
    =
      current
    ->
    next;
    }


    要重新顯示linked list,所以將指標再度指向第一個node,每當顯示一個node後,就指向下一個node,直到指到NULL為止。
    64行

    //
      free linked list


    current
    =
      head;

    while
    (current
    !=
      NULL) {
      prev
    =
      current;
      current
    =
      current
    ->
    next;
      free(prev);
    }


    由於malloc()是將記憶體放在heap,而不是放在stack,所以並不會隨著function的結束而釋放,必須要手動使用free()釋放記憶體,否則會造成memory leak。
    再來看C++,由於STL已內建一些容器,所以不需再重新實作linked list,有兩個選擇:std::vector或者std::list。std::vector的優點是non-sequential access超快,新增資料於後端超快,但insert和erase任意資料則超慢;std::list則剛好相反,insert和erase速度超快,但non-sequential access超慢,由於本例只有新增與non-sequential access,所以適合std::vector。不過由於STL使用泛型技術,若將來需求改變,想改用std::list也沒關係,只要將容器改掉即可,剩下的都不用改,因為STL的演算法並不挑容器,這正是泛型偉大之處。
    C++

    1
    /*
      

    2
    (C) OOMusou 2008
    http://oomusou.cnblogs.com


    3


    4
    Filename    : DS_linked_list_simple_vector_class.cpp

    5
    Compiler    : Visual C++ 8.0

    6
    Description : Demo how to use vector instead of linked list

    7
    Release     : 03/22/2008 1.0

    8

    */


    9
    #include
    <
    iostream
    >


    10
    #include
    <
    string
    >


    11
    #include
    <
    vector
    >


    12


    13

    using
      
    namespace
      std;

    14


    15

    class
      List {

    16

    public
    :

    17
       
    int
      no;

    18
       
    string
      name;

    19
    };

    20


    21

    int
      main() {

    22
       vector
    <
    List
    >
      vec;

    23
       

    24
       
    while
    (
    1
    ) {

    25
         List list;

    26
         cout
    <<
      
    "
    No. =
    "
    ;

    27
         cin
    >>
      list.no;

    28
         

    29
         
    if
      (list.no
    ==
      
    0
    )

    30
          
    break
    ;

    31
       

    32
         cout
    <<
      
    "
    Name =
    "
    ;

    33
         cin
    >>
      list.name;

    34
         

    35
         vec.push_back(list);

    36
       }

    37
       

    38
       vector
    <
    List
    >
    ::iterator iter
    =
      vec.begin();

    39
       
    for
    (; iter
    !=
      vec.end();
    ++
    iter)

    40
         cout
    <<
      
    "
    No. =
    "
      
    <<
      iter
    ->
    no
    <<
      
    "
    , Name =
    "
      
    <<
      iter
    ->
    name
    <<
      endl;

    41
    }



    執行結果

    No.
    =
      
    1

    Name
    =
      clare
    No.
    =
      
    2

    Name
    =
      jessie
    No.
    =
      
    0

    No.
    =
      
    1
    ,
      Name
    =
      clare
    No.
    =
      
    2
    ,
      Name
    =
      jessie


    15行由struct改用了class,不過若繼續使用struct亦可,至於其他的程式都很直觀,就不再多做解釋。
    Conclusion
    本文主要是討論使用C語言透過malloc()實現資料結構的linked list,以彌補靜態語言的不足,同時亦討論C++使用STL的替代方案與便利性,C與C++各擅勝場,你可自行決定使用C或C++。
    See Also
    (原創) C/C++哪些地方會用到pointer呢? (C/C++) (C)
    (原創) 如何將輸入的字串存到記憶體後,再一起印出來? (C/C++) (C)
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-4-19 20:58 , Processed in 0.450030 second(s), 37 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表