什么是链表?
链表是一种线性数据结构,但它与数组不同,数组在内存中是连续存储的,而链表的元素(称为“节点”)在内存中是非连续存储的。

(图片来源网络,侵删)
每个节点都包含两部分:
- 数据域:存储实际的数据。
- 指针域:存储指向下一个节点的内存地址。
通过指针域,这些节点像一串链条一样连接起来,形成链表,链表的第一个节点称为头节点,最后一个节点的指针域通常指向 NULL,表示链表的结束。
一个简单的节点结构示意图:
+-------+--------+ +-------+--------+ +-------+--------+
| Data | Next |----->| Data | Next |----->| Data | NULL |
+-------+--------+ +-------+--------+ +-------+--------+
Node 1 Node 2 Node 3
创建链表的步骤
创建链表通常有两种方式:

(图片来源网络,侵删)
- 头插法:新节点总是插入到链表的头部,最终链表的节点顺序与输入顺序相反。
- 尾插法:新节点总是插入到链表的尾部,最终链表的节点顺序与输入顺序一致。
下面我们分别用这两种方法来实现 createlink 函数。
准备工作:定义节点结构
在创建链表之前,我们必须先定义节点的结构。
#include <stdio.h>
#include <stdlib.h> // 需要用到 malloc 和 free
// 定义链表节点结构体
typedef struct Node {
int data; // 数据域,这里我们用 int 类型作为示例
struct Node* next; // 指针域,指向下一个节点
} Node;
typedef为struct Node定义了一个别名Node,使得代码更简洁。data用来存储数据。next是一个指向Node结构体的指针,用于连接下一个节点。
方法一:头插法创建链表
思路:
- 创建一个新节点。
- 将新节点的
next指针指向当前的链表头。 - 更新链表头,使其指向这个新节点。
特点:实现简单,效率高(O(1)时间复杂度),但最终链表的顺序与输入顺序相反。

(图片来源网络,侵删)
代码实现:
// 函数:头插法创建链表
// 参数:无
// 返回值:返回创建好的链表的头节点指针
Node* createLinkByHeadInsert() {
Node* head = NULL; // 初始化头节点为 NULL,表示一个空链表
int value;
printf("请输入节点数据(输入-1结束):\n");
while (1) {
scanf("%d", &value);
if (value == -1) {
break; // 输入-1表示结束创建
}
// 1. 创建新节点
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("内存分配失败!\n");
exit(1); // 内存分配失败,退出程序
}
newNode->data = value;
newNode->next = NULL;
// 2. 将新节点插入到链表头部
newNode->next = head; // 新节点的 next 指向原来的头
head = newNode; // 更新头节点为新节点
}
return head; // 返回创建好的链表的头
}
方法二:尾插法创建链表
思路:
- 除了需要一个
head指针指向链表头,还需要一个tail指针始终指向链表的最后一个节点。 - 创建一个新节点。
- 将
tail指针的next指向这个新节点。 - 更新
tail指针,使其指向这个新节点。
特点:能保持输入顺序,但需要额外的 tail 指针来追踪尾部,实现比头插法稍复杂。
代码实现:
// 函数:尾插法创建链表
// 参数:无
// 返回值:返回创建好的链表的头节点指针
Node* createLinkByTailInsert() {
Node* head = NULL; // 链表头
Node* tail = NULL; // 链表尾,初始时为 NULL
int value;
printf("请输入节点数据(输入-1结束):\n");
while (1) {
scanf("%d", &value);
if (value == -1) {
break;
}
// 1. 创建新节点
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("内存分配失败!\n");
exit(1);
}
newNode->data = value;
newNode->next = NULL;
// 2. 将新节点插入到链表尾部
if (head == NULL) {
// 如果是第一个节点,头和尾都指向它
head = newNode;
tail = newNode;
} else {
// 如果不是第一个节点,将当前尾节点的 next 指向新节点
tail->next = newNode;
// 更新尾节点为新节点
tail = newNode;
}
}
return head; // 返回创建好的链表的头
}
完整示例代码
下面是一个完整的 C 程序,它包含了链表的创建、打印和内存释放。
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct Node {
int data;
struct Node* next;
} Node;
// --- 函数声明 ---
Node* createLinkByHeadInsert();
Node* createLinkByTailInsert();
void printLink(Node* head);
void freeLink(Node* head);
int main() {
// 使用头插法创建链表
printf("--- 使用头插法创建链表 ---\n");
Node* head1 = createLinkByHeadInsert();
printf("创建的链表为:");
printLink(head1);
freeLink(head1);
printf("\n---------------------------------\n\n");
// 使用尾插法创建链表
printf("--- 使用尾插法创建链表 ---\n");
Node* head2 = createLinkByTailInsert();
printf("创建的链表为:");
printLink(head2);
freeLink(head2);
return 0;
}
// --- 函数定义 ---
/**
* @brief 头插法创建链表
*/
Node* createLinkByHeadInsert() {
Node* head = NULL;
int value;
while (1) {
scanf("%d", &value);
if (value == -1) break;
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = head;
head = newNode;
}
return head;
}
/**
* @brief 尾插法创建链表
*/
Node* createLinkByTailInsert() {
Node* head = NULL;
Node* tail = NULL;
int value;
while (1) {
scanf("%d", &value);
if (value == -1) break;
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = value;
newNode->next = NULL;
if (head == NULL) {
head = tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
}
return head;
}
/**
* @brief 打印链表
* @param head 链表的头节点
*/
void printLink(Node* head) {
Node* current = head;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
/**
* @brief 释放链表内存
* @param head 链表的头节点
*/
void freeLink(Node* head) {
Node* current = head;
while (current != NULL) {
Node* temp = current; // 临时保存当前节点
current = current->next; // 移动到下一个节点
free(temp); // 释放当前节点的内存
}
printf("链表内存已释放,\n");
}
如何编译和运行
- 将上面的代码保存为
create_list.c文件。 - 打开终端或命令提示符,使用 GCC 进行编译:
gcc create_list.c -o create_list
- 运行生成的可执行文件:
- 在 Windows 上:
create_list.exe - 在 Linux/macOS 上:
./create_list
- 在 Windows 上:
运行示例(以尾插法为例):
--- 使用尾插法创建链表 ---
请输入节点数据(输入-1结束):
10
20
30
-1
创建的链表为:10 -> 20 -> 30 -> NULL
链表内存已释放。
createlink是一个概念,指代创建链表的操作,通常由一个自定义函数实现。- 创建链表的核心是动态分配内存 (
malloc) 来创建节点,并通过指针 (->) 将它们连接起来。 - 头插法简单快速,但顺序会反转。
- 尾插法能保持顺序,但需要维护一个尾指针。
- 非常重要:使用
malloc动态分配的内存在程序结束前不会自动释放,必须使用free函数手动释放,否则会造成内存泄漏。freeLink函数就是用来完成这个任务的。
