学习 Linux 单链表 数据结构

1. 什么是单链表

单链表是一种常见的基本数据结构,它由一系列称为节点的元素组成,每个节点包含了数据和一个指向下一个节点的指针。单链表中的节点按顺序链接在一起,每个节点只能访问其后继节点,而不能访问前驱节点。

单链表的特点

单链表具有以下特点:

节点之间通过指针链接,在内存中非连续存储。

每个节点包含两部分数据,即存储的数据和指向下一个节点的指针。

单链表中只能从头节点开始遍历,逐个访问后续节点,无法直接访问前驱节点。

尾节点的指针指向空值(NULL)。

2. 单链表的基本操作

2.1 新建链表

要创建一个单链表,需要先创建一个头节点,并把头节点赋值给链表的头指针。头节点不存储数据,只作为链表的入口。

struct ListNode

{

int data;

struct ListNode* next;

};

struct ListNode* createLinkedList()

{

struct ListNode* head = (struct ListNode*)malloc(sizeof(struct ListNode));

head->next = NULL;

return head;

}

在上述代码中,使用了一个结构体 ListNode 来表示单链表的节点,包含了一个整型数据 data 和一个指向下一个节点的指针 next。通过 createLinkedList 函数可以创建一个空链表并返回链表的头指针。

2.2 添加元素

要向单链表中添加元素,可以分为两种情况:

在链表的头部插入元素。

在链表的尾部插入元素。

以下是分别实现这两种情况的代码:

void insertAtHead(struct ListNode* head, int data)

{

struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));

newNode->data = data;

newNode->next = head->next;

head->next = newNode;

}

void insertAtTail(struct ListNode* head, int data)

{

struct ListNode* newNode = (struct ListNode*)malloc(sizeof(struct ListNode));

newNode->data = data;

newNode->next = NULL;

struct ListNode* p = head;

while (p->next != NULL) {

p = p->next;

}

p->next = newNode;

}

insertAtHead 函数中,我们先创建一个新的节点,将要插入的数据存入新节点的 data 字段中。然后,将新节点的 next 指针设置为原头节点的 next 指针,再将头节点的 next 指针指向新节点。

insertAtTail 函数中,我们先创建一个新的节点,并将要插入的数据存入新节点的 data 字段中。接着,从头节点开始遍历,直到找到尾节点(即 next 指针为 NULL 的节点),将该节点的 next 指针指向新节点。

2.3 删除元素

要从单链表中删除元素,我们可以根据元素的位置来删除:

删除链表的头节点。

删除链表的尾节点。

删除链表中的某个特定元素。

以下是相应操作的代码:

void deleteAtHead(struct ListNode* head)

{

if (head->next != NULL) {

struct ListNode* temp = head->next;

head->next = temp->next;

free(temp);

}

}

void deleteAtTail(struct ListNode* head)

{

struct ListNode* p = head;

while (p->next != NULL && p->next->next != NULL) {

p = p->next;

}

if (p->next != NULL) {

struct ListNode* temp = p->next;

p->next = NULL;

free(temp);

}

}

void deleteElement(struct ListNode* head, int data)

{

struct ListNode* p = head;

while (p->next != NULL && p->next->data != data) {

p = p->next;

}

if (p->next != NULL) {

struct ListNode* temp = p->next;

p->next = temp->next;

free(temp);

}

}

deleteAtHead 函数中,我们先判断头节点的 next 指针是否为空,如果不为空,则将头节点的 next 指针指向下一个节点,并释放原头节点。

deleteAtTail 函数中,我们找到倒数第二个节点,将其 next 指针设置为 NULL,并释放尾节点。

deleteElement 函数中,我们找到要删除的节点的前驱节点,将其 next 指针指向要删除节点的下一个节点,并释放要删除的节点。

3. 单链表的应用场景

单链表的应用场景非常广泛,以下是几个常见的应用场景:

3.1 链表作为栈

单链表可以用来实现栈的数据结构。栈是一种后进先出(LIFO)的数据结构,只能从一端添加和取出元素。我们可以使用头节点作为栈顶指针,每次在头节点之后添加或删除节点来实现栈的入栈和出栈操作。

3.2 链表作为队列

单链表也可以用来实现队列的数据结构。队列是一种先进先出(FIFO)的数据结构,只能从一端添加元素,从另一端删除元素。我们可以使用头节点作为队列的队头指针,尾节点作为队尾指针,每次在尾节点之后添加节点,从头节点后面删除节点来实现队列的入队和出队操作。

3.3 链表作为哈希表

哈希表是一种常用的数据结构,用于存储键值对。每个键值对通过哈希函数计算出一个唯一的哈希码,并根据哈希码存储在对应的槽位中。哈希表可以使用单链表解决哈希冲突的问题,即多个键值对计算得到相同的哈希码的情况。

4. 总结

本文介绍了单链表的定义、特点和基本操作,包括新建链表、添加元素和删除元素等操作。单链表是一种灵活的数据结构,适用于多种场景,如栈、队列和哈希表等。在实际应用中,根据具体需求和场景,可以选择合适的操作来处理单链表。

操作系统标签