使用 C 實作 Link List

Jay
7 min readMar 2, 2023

--

作為使用非常廣泛,和面試時常常出現的資料結構,有基本的理解和操作非常重要,這篇文章會教大家使用 C 來對 Link List 進行操作。

不使用動態記憶體

我們先來手動建立一個 Link List,而不是用動態建立的方式。

首先建立一個結構體用來表示一個節點。

struct node
{
int data; // 節點中的資料
struct node *next; // 指向下一個節點
};

再來就是手動建立各個節點,並將每個節點串在一起。

#include <stdio.h>

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

typedef struct node NODE; // 定義 NODE 關鍵字代表 node 結構體
typedef struct node *NODEp; // 定義 NODEp 關鍵字代表指向 node 結構體的 pointer

int main(void)
{

NODEp first; // 先建立一個 node 類型的指標,等等要讓他指向第一個節點

NODE node1, node2, node3; // 建立三個節點

// 儲存資料到節點中
node1.data = 1;
node2.data = 2;
node3.data = 3;

// 建立連結
node1.next = &node2;
node2.next = &node3;
node3.next = NULL;

// 將 first 指向第一個節點
first = &node1;

return 0;
}

到這邊我們已經建立了有三個節點的 Link List,示意圖如下。

示意圖

最後就是遍歷 Link List 將每個節點的資料印出來拉。

    NODEp p = first;    // 使用 p 作為遍歷節點的 pointer
while (p != NULL)
{
printf("%d ", p -> data);

p = p -> next; // 更新 p 指向下一個節點
}

我們使用 p 作為遍歷節點的指標,依序印出節點的資料,並更新 p 指向下一個節點的位置,等到 p 是 NULL 時就是遍歷完所有節點了。

完整程式碼

#include <stdio.h>

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

typedef struct node NODE; // 定義 NODE 關鍵字代表 node 結構體
typedef struct node *NODEp; // 定義 NODEp 關鍵字代表指向 node 結構體的 pointer

int main(void)
{

NODEp first; // 先建立一個 node 類型的指標,等等要讓他指向第一個節點

NODE node1, node2, node3; // 建立三個節點

// 儲存資料到節點中
node1.data = 1;
node2.data = 2;
node3.data = 3;

// 建立連結
node1.next = &node2;
node2.next = &node3;
node3.next = NULL;

// 將 first 指向第一個節點
first = &node1;

NODEp p = first; // 使用 p 作為遍歷節點的 pointer
while (p != NULL)
{
printf("%d ", p->data);

p = p->next; // 更新 p 指向下一個節點
}

printf("\n");

return 0;
}

// 1 2 3

使用動態記憶體建立

上面我們手動建立了一個簡單的 Link List,但我們要手動一個一個建立連結,而且因為不是使用動態記憶體的方式,所以沒辦法新增節點,非常不方便,所以我們要來更改一下,變成使用動態的方式建立。

我們將上面的程式改成由動態記憶體的方式建立。

動態建立 Link List

以下的程式就是在做上面動畫中的事

    int arr[] = {1, 2, 3}; // 每個節點的資料

NODEp first; // 要指向第一個節點的 pointer
NODEp current, prev; // 定義兩個 pointer 用來追蹤節點

for (int i = 0; i < 3; i++)
{

current = (NODE *)malloc(sizeof(NODE)); // 建立一個 NODE 類型大小的空間,並讓 current 指向

current->data = arr[i]; // 儲存資料

// 如果是第一個節點,就讓 first 指向該節點
if (i == 0)
{
first = current;
}
else
{
prev->next = current;
}

current->next = NULL;
prev = current;
}

遍歷的邏輯則是跟之前的一樣

    NODEp p = first;

while (p != NULL)
{
printf("%d ", p->data);

p = p->next;
}

最後不能忘記要把動態產生的記憶體釋放

    NODEp pp = first;

while (pp != NULL)
{

first = first->next; // 先將 first 指向下一個節點,不然之後會錯誤
free(pp); // 釋放該節點的記憶體
pp = first;
}

完整程式碼

#include <stdio.h>
#include <stdlib.h> // malloc 函示需要載入這個標題檔

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

typedef struct node NODE; // 定義 NODE 關鍵字代表 node 結構體
typedef struct node *NODEp; // 定義 NODEp 關鍵字代表指向 node 結構體的 pointer

int main(void)
{

int arr[] = {1, 2, 3}; // 每個節點的資料

NODEp first; // 要指向第一個節點的 pointer
NODEp current, prev; // 定義兩個 pointer 用來追蹤節點

for (int i = 0; i < 3; i++)
{

current = (NODE *)malloc(sizeof(NODE)); // 建立一個 NODE 類型大小的空間,並讓 current 指向

current->data = arr[i]; // 儲存資料

// 如果是第一個節點,就讓 first 指向該節點
if (i == 0)
{
first = current;
}
else
{
prev->next = current;
}

current->next = NULL;
prev = current;
}

NODEp p = first;

while (p != NULL)
{
printf("%d ", p->data);

p = p->next;
}

printf("\n");

NODEp pp = first;

while (pp != NULL)
{

first = first->next; // 先將 first 指向下一個節點,不然之後會錯誤
free(pp); // 釋放該節點的記憶體
pp = first;
}

return 0;
}

--

--