您好,登录后才能下订单哦!
链表是一种常见的数据结构,广泛应用于各种编程场景中。与数组不同,链表在内存中不是连续存储的,而是通过指针将各个节点连接起来。链表的主要优势在于其动态性,可以根据需要动态地增加或删除节点,而不需要像数组那样预先分配固定大小的内存空间。
本文将详细介绍如何在C语言中实现单链表、双链表和循环链表,并探讨它们的应用场景、优缺点以及实现细节。
链表是一种线性数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的指针。链表中的节点在内存中不是连续存储的,而是通过指针连接在一起。
链表主要分为以下几种类型:
在C语言中,单链表的结构通常定义如下:
typedef struct Node {
int data; // 数据域
struct Node* next; // 指针域,指向下一个节点
} Node;
创建一个单链表通常需要初始化一个头节点,头节点不存储数据,只用于指向链表的第一个节点。
Node* createLinkedList() {
Node* head = (Node*)malloc(sizeof(Node));
if (head == NULL) {
printf("Memory allocation failed\n");
return NULL;
}
head->next = NULL;
return head;
}
在单链表中插入节点通常有以下几种情况:
void insertAtHead(Node* head, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = head->next;
head->next = newNode;
}
void insertAtTail(Node* head, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = NULL;
Node* current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
void insertAfter(Node* prevNode, int data) {
if (prevNode == NULL) {
printf("Previous node cannot be NULL\n");
return;
}
Node* newNode = (Node*)malloc(sizeof(Node));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = prevNode->next;
prevNode->next = newNode;
}
在单链表中删除节点通常有以下几种情况:
void deleteAtHead(Node* head) {
if (head->next == NULL) {
printf("List is empty\n");
return;
}
Node* temp = head->next;
head->next = temp->next;
free(temp);
}
void deleteAtTail(Node* head) {
if (head->next == NULL) {
printf("List is empty\n");
return;
}
Node* current = head;
while (current->next->next != NULL) {
current = current->next;
}
Node* temp = current->next;
current->next = NULL;
free(temp);
}
void deleteAfter(Node* prevNode) {
if (prevNode == NULL || prevNode->next == NULL) {
printf("Previous node or next node cannot be NULL\n");
return;
}
Node* temp = prevNode->next;
prevNode->next = temp->next;
free(temp);
}
遍历单链表意味着访问链表中的每一个节点,并执行某些操作(如打印节点的数据)。
void traverseLinkedList(Node* head) {
Node* current = head->next;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
在单链表中查找某个特定的值,通常需要遍历链表,直到找到目标值或到达链表末尾。
Node* searchLinkedList(Node* head, int data) {
Node* current = head->next;
while (current != NULL) {
if (current->data == data) {
return current;
}
current = current->next;
}
return NULL;
}
销毁单链表意味着释放链表中所有节点的内存。
void destroyLinkedList(Node* head) {
Node* current = head->next;
while (current != NULL) {
Node* temp = current;
current = current->next;
free(temp);
}
head->next = NULL;
}
在C语言中,双链表的结构通常定义如下:
typedef struct DNode {
int data; // 数据域
struct DNode* prev; // 指向前一个节点的指针
struct DNode* next; // 指向下一个节点的指针
} DNode;
创建一个双链表通常需要初始化一个头节点,头节点不存储数据,只用于指向链表的第一个节点。
DNode* createDoublyLinkedList() {
DNode* head = (DNode*)malloc(sizeof(DNode));
if (head == NULL) {
printf("Memory allocation failed\n");
return NULL;
}
head->prev = NULL;
head->next = NULL;
return head;
}
在双链表中插入节点通常有以下几种情况:
void insertAtHead(DNode* head, int data) {
DNode* newNode = (DNode*)malloc(sizeof(DNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->prev = head;
newNode->next = head->next;
if (head->next != NULL) {
head->next->prev = newNode;
}
head->next = newNode;
}
void insertAtTail(DNode* head, int data) {
DNode* newNode = (DNode*)malloc(sizeof(DNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = NULL;
DNode* current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
newNode->prev = current;
}
void insertAfter(DNode* prevNode, int data) {
if (prevNode == NULL) {
printf("Previous node cannot be NULL\n");
return;
}
DNode* newNode = (DNode*)malloc(sizeof(DNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = prevNode->next;
newNode->prev = prevNode;
if (prevNode->next != NULL) {
prevNode->next->prev = newNode;
}
prevNode->next = newNode;
}
在双链表中删除节点通常有以下几种情况:
void deleteAtHead(DNode* head) {
if (head->next == NULL) {
printf("List is empty\n");
return;
}
DNode* temp = head->next;
head->next = temp->next;
if (temp->next != NULL) {
temp->next->prev = head;
}
free(temp);
}
void deleteAtTail(DNode* head) {
if (head->next == NULL) {
printf("List is empty\n");
return;
}
DNode* current = head;
while (current->next->next != NULL) {
current = current->next;
}
DNode* temp = current->next;
current->next = NULL;
free(temp);
}
void deleteAfter(DNode* prevNode) {
if (prevNode == NULL || prevNode->next == NULL) {
printf("Previous node or next node cannot be NULL\n");
return;
}
DNode* temp = prevNode->next;
prevNode->next = temp->next;
if (temp->next != NULL) {
temp->next->prev = prevNode;
}
free(temp);
}
遍历双链表意味着访问链表中的每一个节点,并执行某些操作(如打印节点的数据)。
void traverseDoublyLinkedList(DNode* head) {
DNode* current = head->next;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
在双链表中查找某个特定的值,通常需要遍历链表,直到找到目标值或到达链表末尾。
DNode* searchDoublyLinkedList(DNode* head, int data) {
DNode* current = head->next;
while (current != NULL) {
if (current->data == data) {
return current;
}
current = current->next;
}
return NULL;
}
销毁双链表意味着释放链表中所有节点的内存。
void destroyDoublyLinkedList(DNode* head) {
DNode* current = head->next;
while (current != NULL) {
DNode* temp = current;
current = current->next;
free(temp);
}
head->next = NULL;
}
在C语言中,循环链表的结构通常定义如下:
typedef struct CNode {
int data; // 数据域
struct CNode* next; // 指向下一个节点的指针
} CNode;
创建一个循环链表通常需要初始化一个头节点,头节点不存储数据,只用于指向链表的第一个节点。
CNode* createCircularLinkedList() {
CNode* head = (CNode*)malloc(sizeof(CNode));
if (head == NULL) {
printf("Memory allocation failed\n");
return NULL;
}
head->next = head; // 头节点指向自己,形成循环
return head;
}
在循环链表中插入节点通常有以下几种情况:
void insertAtHead(CNode* head, int data) {
CNode* newNode = (CNode*)malloc(sizeof(CNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = head->next;
head->next = newNode;
}
void insertAtTail(CNode* head, int data) {
CNode* newNode = (CNode*)malloc(sizeof(CNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = head;
CNode* current = head;
while (current->next != head) {
current = current->next;
}
current->next = newNode;
}
void insertAfter(CNode* prevNode, int data) {
if (prevNode == NULL) {
printf("Previous node cannot be NULL\n");
return;
}
CNode* newNode = (CNode*)malloc(sizeof(CNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
return;
}
newNode->data = data;
newNode->next = prevNode->next;
prevNode->next = newNode;
}
在循环链表中删除节点通常有以下几种情况:
void deleteAtHead(CNode* head) {
if (head->next == head) {
printf("List is empty\n");
return;
}
CNode* temp = head->next;
head->next = temp->next;
free(temp);
}
void deleteAtTail(CNode* head) {
if (head->next == head) {
printf("List is empty\n");
return;
}
CNode* current = head;
while (current->next->next != head) {
current = current->next;
}
CNode* temp = current->next;
current->next = head;
free(temp);
}
void deleteAfter(CNode* prevNode) {
if (prevNode == NULL || prevNode->next == head) {
printf("Previous node or next node cannot be NULL\n");
return;
}
CNode* temp = prevNode->next;
prevNode->next = temp->next;
free(temp);
}
遍历循环链表意味着访问链表中的每一个节点,并执行某些操作(如打印节点的数据)。
”`c void traverseCircularLinkedList(CNode* head) { CNode* current = head->next; while (current != head) { printf(“%d -> “, current
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。