不使用動態記憶體
我們先來手動建立一個 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,但我們要手動一個一個建立連結,而且因為不是使用動態記憶體的方式,所以沒辦法新增節點,非常不方便,所以我們要來更改一下,變成使用動態的方式建立。
我們將上面的程式改成由動態記憶體的方式建立。
以下的程式就是在做上面動畫中的事
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;
}
有關新增節點、刪除節點、反轉 Link List 的操作可以參考這篇文章