C語言---鏈表(包括學習過程中的思想活動)

寫鏈表想法的由來:

  鏈表---重要的數據結構,工作了這麼長時間,再也沒有寫過鏈表,可能是由於工作中沒有使用的原因,也可能是我太懶了,還可能是因爲玩遊戲玩過頭了吧!總之我知道有鏈表,但是鏈表是什麼好想就天馬行空了,所以決定寫一下,哈哈,雖然我很菜,但是再菜我也要它跑起來,萬一哪天要用那麼一下子呢!好了廢話不多說,來滿足一下自己的小小的一個期望(它跑起來)。

特簡單的:

  首先呢!先碼一個特別簡單的,主要是爲了先了解一下嘛!然後在一點點深入嘛!畢竟這麼長時間沒有寫過了,不是嘛?

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

struct node {
    int number;
    struct node *next;
};

typedef struct node Node;

int main(void)
{
    Node *head, *b, *c; 

    head = (Node *)malloc(sizeof(Node));   
    b = (Node *)malloc(sizeof(Node));   
    c = (Node *)malloc(sizeof(Node));   

    b->number = 20; 
    c->number = 30; 

    head->next = b;
    b->next = c;

    while (head) {
        printf("---->%d", head->number);

        head = head->next;
    }   
    printf("\n");

    free(head);
    free(b);
    free(c);

    return 0;
}
// 執行結果

  [root@yuan misc]# gcc link_list.c
  [root@yuan misc]# ./a.out
  ---->0---->20---->30

  鏈表從表面的意思上就是鏈狀的表,就像一根線上繫了很多一樣的結,這些結就是我們定義的結構體,而鏈就是我們定義的結構體中的指針next。next中存放着下一個節點的地址,這樣我們就把所有的節點串聯了起來,就像我們上邊執行的結果一樣。其實就是指針將數據串聯。

稍微有點複雜的:

  (我覺得上邊碼的那個並不算是真正意義上的鏈表,我們只是把三個結構體變量串聯了起來)寫一個稍微複雜點的鏈表:  

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 
  5 struct node {
  6     char name[16];
  7     char number[16];
  8     // long long number;
  9     struct node *next;
 10 };
 11 
 12 typedef struct node Node;
 13 
 14 Node *createList(int num)
 15 {
 16     Node *head = NULL;
 17     Node *tmp = NULL;
 18     Node *node = NULL;
 19     int i = 0;
 20     // int count = 0;
 21     // long long tmpNum;
 22 
 23     head = (Node *)malloc(sizeof(Node));
 24     if (!head) {
 25         printf("malloc Node(head) error!\n");
 26         goto err;
 27     }   
 28 
 29     head->next = NULL;
 30 
 31     tmp = head;
 32 
 33     for(i = 1; i <= num; i++) {
 34         printf("create [%d] node!\n", i); 
 35         node = (Node *)malloc(sizeof(Node));
 36         if (!node) {
 37             printf("malloc Node(node) error!\n");
 38         }   
 39     
 40         printf("Please enter your name :\n");
 41         scanf("%s", &node->name);
 42         if (!node->name) {
 43             printf("enter the name error! Please enter again!\n");
 44             goto err;
 45         }   
 46 
 47         printf("Please enter yout number :\n");
 48         // scanf("%d", &node->number);
 49         scanf("%s", &node->number);
 50         if (strlen(node->number) != 11) {
 51             printf("enter the number error! Please enter again!\n");
 52             goto err;
 53         }   
 54 
 55         // tmpNum = node->number;
 56         // while(tmpNum) {
 57         //  tmpNum /= 10;
 58         //  count++;
 59         // }
 60 
 61         // if (count != 10) {
 62         //  printf("enter the number error! Please enter again!\n");
 63         //  goto err;
 64         // }
 65 
 66         tmp->next = node;
 67         tmp = node;
 68     }   
 69     node->next = NULL;
 70     return head;
 71 
 72 err:
 73     return NULL;
 74 }
 75 
 76 void printList(Node *node)
 77 {
 78     Node *tmp = NULL;
 79 
 80     tmp = node->next;
 81 
 82     while(tmp) {
 83         printf("name : %s, number : %s\n", tmp->name, tmp->number);
 84         tmp = tmp->next;
 85     }   
 86 }
 87 
 88 void freeList(Node *node)
 89 {
 90     Node *tmp = NULL;
 91     int i = 1;
 92 
 93     tmp  = node->next;
 94 
 95     while(tmp) {
 96         free(tmp);
 97         printf("clean up [%d] node!\n", i); 
 98         tmp = tmp->next;
 99         i++;
100     }   
101     tmp = NULL;
102 
103     free(node);
104     node = NULL;
105 
106     printf("clear finish!\n");
107 }
108 
109 int main(void)
110 {
111     Node *node = NULL;
112     int num;
113 
114     printf("Please enter the number of nodes int the link_list :\n");
115     scanf("%d", &num);
116     node = createList(num);
117     printList(node);
118     freeList(node);
119 
120     return 0;
121 }
// 執行結果

[root@localhost address_list]# ./a.out 
Please enter the number of nodes int the link_list :
2
create [1] node!
Please enter your name :
test
Please enter your number :
12345678901
create [2] node!
Please enter your name :
test2
Please enter your number :
12345678902
name : test, number : 12345678901
name : test2, number : 12345678902
clean up [1] node!
clean up [2] node!
clear finish!

  代碼中有部分注掉的,那部分是因爲數字長度的問題,我試了%ll,%l64d, %lld,%ld輸出的結果都不是期望值,所以就改用了字符串,這個問題有時間我在查一下吧!

  逐句分析:

    首先我們定義了一個結構體Node,結構體成員有三個,用來存儲一個人名和其對應的電話號碼(11位),next指針用來指向下一個節點;

    在main函數中,先要輸入一個數字,來確定我們的鏈表的長度,然後創建鏈表,將其存儲的內容打印出來,最後釋放各個節點。

      createList函數中:

      生成一個頭節點,根據num確定需要生成節點的個數,並對其各個節點進行賦值。

      createList函數中我們定義了三個結構體變量,一個是頭節點head,一個是節點node,還有一個臨時結構體變量tmp。我們將頭節點head賦值給中間變量tmp,然後分配一個新的節點node,將node賦值給中間變量tmp結構體成員變量中的next指針變量(也就是頭節點head結構體成員變量中的next指針變量),這樣頭節點就和新分配的節點node串聯起來了。其中有一句tmp = node,這句話表示將新生成的節點node賦值給了中間變量tmp,這樣做是爲了在下一次循環中中間變量tmp表示的是上一次分配的node節點,再次分配新的節點後和現在的中間變量tmp(也就是上一次分配的節點)串聯。描述的有點亂,仔細想一下也不是那麼亂。

      當循環結束後,將最後分配的節點node結構體成員中的next指針變量指向NULL。

      返回頭節點head。

    printList函數中:

      剛開始是這樣寫的:

void printList(Node *node)
{
    while(node) {
        printf("name : %s, number : %s\n", node->name, node->number);
        node = node->next;
    }   
}
// 執行結果

[root@localhost address_list]# ./a.out
Please enter the number of nodes int the link_list :
2
create [1] node!
Please enter your name :
test
Please enter your number :
12345678901
create [2] node!
Please enter your name :
test2
Please enter your number :
12345678902
name : , number :
name : test, number : 12345678901
name : test2, number : 12345678902
clean up [1] node!
clean up [2] node!
clear finish!

    從執行結果中可以看出,我們鏈表長度是2,但是在打印的出來的結果中去出現三個,只是因爲其中空的那個是頭節點。

  freeList函數:

    由於使用了malloc函數動態分配就需要free函數掉,防止內存泄漏,其中有一句tmp  = NULL;這句是爲了防止野指針,但是NULL也是一個地址,只不過這個地址是確定的(void *)0;但是這句話加到循環裏就會出現問題,因爲在free掉tmp後這個指針還是存在的,可能就是野指針吧(這裏我不確定),但是這時的tmp確確實實是存在的,所以纔有了下面的操作。而當我們將tmp制空後,它的地址也就不存在了,我們在進行後邊的操作的時候就操作非法地址,就會出現段錯誤。

    還需將頭節點free掉。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章