zoukankan      html  css  js  c++  java
  • 簡單的Linked List實現

     

    Abstraction

    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++。


    使用C語言簡單的實現linked list,並用C++的std::vector實作出相同的功能作比較。

  • 相关阅读:
    犀牛书学习笔记(2):对象和数组
    犀牛书学习笔记(1):语法结构、数据类型和值、表达式和运算符
    小学了一下css hack
    git学习系列--六分之一
    稍览了一下CommonJS
    意识流_六分之一
    两升的心思系列之-----粒子的预备
    mybatis_延迟加载
    mybatis_动态SQL
    mybatis_mapper动态代理
  • 原文地址:https://www.cnblogs.com/lzjsky/p/1861783.html
Copyright © 2011-2022 走看看