大家好,这里是小编的博客频道
小编的博客:就爱学编程
很高兴在CSDN
这个大家庭与大家相识,希望能在这里与大家共同进步,共同收获更好的自己!!!
本文目录
- 引言
- 结构体的自引用实现链表
-
-
- 一、链表的基本概念
-
- [1. 单向链表](#1. 单向链表)
- [2. 双向链表](#2. 双向链表)
- [3. 循环链表](#3. 循环链表)
- 二、使用结构体定义链表节点
- 三、创建链表的基本操作
-
- [1. 创建新节点](#1. 创建新节点)
- [2. 在链表头部插入节点](#2. 在链表头部插入节点)
- [3. 在链表尾部插入节点](#3. 在链表尾部插入节点)
- [4. 删除节点](#4. 删除节点)
- [5. 打印链表](#5. 打印链表)
- 四、完整示例代码
-
- 快乐的时光总是短暂,咱们下篇博文再见啦!!!不要忘了,给小编点点赞和收藏支持一下,在此非常感谢!!!
引言
在C语言中,结构体(struct)是一种用户自定义的数据类型,它允许将多个不同类型的数据项组合成一个单一的类型。结构体是编程中组织相关数据的有效方式,尤其在处理复杂数据时显得尤为重要。以下是对C语言结构体进阶知识-------实现链表的介绍,一起来看看吧!!
那接下来就让我们开始遨游在知识的海洋!
结构体的自引用实现链表
一、链表的基本概念
链表是一种线性数据结构,但与数组不同的是,链表中的元素在内存中不必连续存储。链表由一系列的节点(Node)组成,每个节点包含两部分:一部分是存储数据的域(Data Field),另一部分是指向下一个节点的指针(Pointer Field)。根据指针的指向不同,链表可以分为单向链表、双向链表和循环链表等。
1. 单向链表
单向链表是最简单的链表形式,其中每个节点只包含一个指向下一个节点的指针。最后一个节点的指针为NULL,表示链表的结束。
2. 双向链表
双向链表中的每个节点除了包含指向下一个节点的指针外,还包含指向前一个节点的指针。这使得在链表中向前或向后遍历都成为可能。
3. 循环链表
循环链表的特点是最后一个节点的指针不是指向NULL,而是指向链表的第一个节点,从而形成一个环状结构。
二、使用结构体定义链表节点
在C语言中,可以使用结构体来定义链表节点。以下是一个单向链表节点的定义示例:
c
#include <stdio.h>
#include <stdlib.h>
// 定义链表节点结构体
typedef struct Node {
int data; // 数据域
struct Node* next; // 指针域,指向下一个节点
} Node;
在这个例子中,Node
结构体有两个成员:一个是整型变量data
用于存储数据,另一个是指针next
用于指向下一个Node
类型的节点。
三、创建链表的基本操作
1. 创建新节点
要创建一个新的链表节点,需要动态分配内存并初始化其数据和指针。以下是创建新节点的函数示例:
c
// 创建新节点并返回其指针
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node)); // 动态分配内存
if (!newNode) {
printf("Memory allocation error
");
exit(1);
}
newNode->data = data; // 初始化数据域
newNode->next = NULL; // 初始化指针域为空
return newNode;
}
2. 在链表头部插入节点
要在链表的头部插入一个新节点,只需更新新节点的
next
指针使其指向当前的头节点,然后更新头指针指向新节点。以下是该操作的函数示例:
c
// 在链表头部插入新节点
void insertAtHead(Node** head, int data) {
Node* newNode = createNode(data); // 创建新节点
newNode->next = *head; // 新节点的next指向当前头节点
*head = newNode; // 更新头指针指向新节点
}
注意这里使用了双重指针Node** head
,以便能够修改头指针本身的值。
3. 在链表尾部插入节点
要在链表的尾部插入一个新节点,需要遍历到链表的末尾,然后将末尾节点的
next
指针指向新节点。以下是该操作的函数示例:
c
// 在链表尾部插入新节点
void insertAtTail(Node** head, int data) {
Node* newNode = createNode(data); // 创建新节点
if (*head == NULL) { // 如果链表为空,则新节点成为头节点
*head = newNode;
return;
}
Node* temp = *head; // 使用临时指针遍历链表
while (temp->next != NULL) { // 找到最后一个节点
temp = temp->next;
}
temp->next = newNode; // 将最后一个节点的next指向新节点
}
4. 删除节点
删除节点需要根据给定的值找到目标节点,并调整前一个节点的
next
指针使其跳过目标节点。以下是删除节点的函数示例:
c
// 根据值删除节点
void deleteNode(Node** head, int key) {
Node* temp = *head;
Node* prev = NULL;
// 如果头节点就是要删除的节点
if (temp != NULL && temp->data == key) {
*head = temp->next; // 修改头指针
free(temp); // 释放旧头节点内存
return;
}
// 查找要删除的节点,记录前一个节点
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
// 如果没有找到要删除的节点
if (temp == NULL) return;
// 从链表中移除节点
prev->next = temp->next;
free(temp); // 释放被删除节点的内存
}
5. 打印链表
为了验证链表的正确性,通常需要编写一个打印链表的函数:
c
// 打印链表中的所有节点
void printList(Node* head) {
Node* temp = head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL
");
}
四、完整示例代码
以下是一个完整的示例程序,它展示了如何创建和操作一个简单的单向链表:
c
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
} Node;
Node* createNode(int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (!newNode) {
printf("Memory allocation error
");
exit(1);
}
newNode->data = data;
newNode->next = NULL;
return newNode;
}
void insertAtHead(Node** head, int data) {
Node* newNode = createNode(data);
newNode->next = *head;
*head = newNode;
}
void insertAtTail(Node** head, int data) {
Node* newNode = createNode(data);
if (*head == NULL) {
*head = newNode;
return;
}
Node* temp = *head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = newNode;
}
void deleteNode(Node** head, int key) {
Node* temp = *head;
Node* prev = NULL;
if (temp != NULL && temp->data == key) {
*head = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->data != key) {
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp);
}
void printList(Node* head) {
Node* temp = head;
while (temp != NULL) {
printf("%d -> ", temp->data);
temp = temp->next;
}
printf("NULL
");
}
int main() {
Node* head = NULL;
insertAtHead(&head, 10);
insertAtHead(&head, 20);
insertAtTail(&head, 30);
insertAtTail(&head, 40);
printf("Linked List: ");
printList(head);
deleteNode(&head, 20);
printf("After deleting 20: ");
printList(head);
deleteNode(&head, 10);
printf("After deleting 10: ");
printList(head);
return 0;
}
- 通过上述步骤,我们了解了如何在C语言中使用结构体来实现链表,并掌握了基本的链表操作如创建节点、插入节点、删除节点以及打印链表的方法。这些基本操作是实现更复杂链表算法和数据结构