返回
双向链表与双向循环链表揭秘:数据结构中的关键结构
见解分享
2023-09-21 20:30:40
双向链表与单链表的异同
在单链表中,每个节点只包含一个指向直接后继节点的指针,而在双向链表中,每个节点包含两个指针,分别指向直接前驱节点和直接后继节点。这种结构上的差异导致了双向链表具有以下几个优点:
- 高效的查找操作: 在单链表中,查找一个指定节点需要从链表头开始逐个遍历,而双向链表支持从任意节点开始向前或向后查找,显著提高了查找效率。
- 方便的插入和删除操作: 在单链表中,插入或删除一个节点需要更新其前驱节点的指针,而在双向链表中,只需要更新其前驱节点和后继节点的指针即可,简化了操作。
- 支持循环遍历: 双向链表可以形成一个闭合的环,方便地进行循环遍历,而单链表则不能。
双向循环链表的独特性
双向循环链表是在双向链表的基础上进一步改进而成的,其特点是最后一个节点的下一个节点指向链表头节点,链表头节点的上一个节点指向链表尾节点,形成一个闭合的环。这种结构上的优势使其具有以下特性:
- 高效的循环遍历: 双向循环链表支持从任意节点开始循环遍历,无需考虑边界条件,大大简化了遍历操作。
- 插入和删除操作的便捷性: 双向循环链表中,插入或删除一个节点只需要更新其相邻节点的指针即可,操作更加便捷。
C语言代码实现
为了更好地理解双向链表和双向循环链表,我们使用C语言对其核心功能进行了实现,具体代码如下:
// 双向链表节点结构体
struct node {
int data;
struct node *prev;
struct node *next;
};
// 初始化双向链表
struct node *init_list() {
struct node *head = NULL;
return head;
}
// 在双向链表尾部插入一个节点
void insert_node(struct node **head, int data) {
struct node *new_node = (struct node *)malloc(sizeof(struct node));
new_node->data = data;
new_node->prev = NULL;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
} else {
struct node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = new_node;
new_node->prev = current;
}
}
// 删除双向链表中的一个节点
void delete_node(struct node **head, int data) {
struct node *current = *head;
while (current != NULL) {
if (current->data == data) {
if (current == *head) {
*head = current->next;
} else {
current->prev->next = current->next;
}
if (current->next != NULL) {
current->next->prev = current->prev;
}
free(current);
break;
}
current = current->next;
}
}
// 查找双向链表中的一个节点
struct node *search_node(struct node *head, int data) {
struct node *current = head;
while (current != NULL) {
if (current->data == data) {
return current;
}
current = current->next;
}
return NULL;
}
// 打印双向链表
void print_list(struct node *head) {
struct node *current = head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("\n");
}
// 双向循环链表节点结构体
struct cnode {
int data;
struct cnode *prev;
struct cnode *next;
};
// 初始化双向循环链表
struct cnode *init_clist() {
struct cnode *head = NULL;
return head;
}
// 在双向循环链表尾部插入一个节点
void insert_cnode(struct cnode **head, int data) {
struct cnode *new_node = (struct cnode *)malloc(sizeof(struct cnode));
new_node->data = data;
new_node->prev = NULL;
new_node->next = NULL;
if (*head == NULL) {
*head = new_node;
new_node->next = new_node;
new_node->prev = new_node;
} else {
struct cnode *current = *head;
while (current->next != *head) {
current = current->next;
}
current->next = new_node;
new_node->prev = current;
new_node->next = *head;
(*head)->prev = new_node;
}
}
// 删除双向循环链表中的一个节点
void delete_cnode(struct cnode **head, int data) {
struct cnode *current = *head;
while (current != NULL) {
if (current->data == data) {
if (current == *head) {
*head = current->next;
} else {
current->prev->next = current->next;
}
if (current->next != NULL) {
current->next->prev = current->prev;
}
free(current);
break;
}
current = current->next;
}
}
// 查找双向循环链表中的一个节点
struct cnode *search_cnode(struct cnode *head, int data) {
struct cnode *current = head;
while (current != NULL) {
if (current->data == data) {
return current;
}
current = current->next;
}
return NULL;
}
// 打印双向循环链表
void print_clist(struct cnode *head) {
struct cnode *current = head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
if (current == head) {
break;
}
}
printf("\n");
}
int main() {
// 创建双向链表
struct node *head = init_list();
// 插入一些节点
insert_node(&head, 1);
insert_node(&head, 2);
insert_node(&head, 3);
insert_node(&head, 4);
// 打印双向链表
printf("双向链表:");
print_list(head);
// 删除一个节点
delete_node(&head, 2);
// 查找一个节点
struct node *found_node = search_node(head, 3);
if (found_node != NULL) {
printf("找到节点:%d\n", found_node->data);
} else {
printf("未找到节点\n");
}
// 创建双向循环链表
struct cnode *chead = init_clist();
// 插入一些节点
insert_cnode(&chead, 1);
insert_cnode(&chead, 2);
insert_cnode(&chead, 3);
insert_cnode(&chead, 4);
// 打印双向循环链表
printf("双向循环链表:");
print_clist(chead);
// 删除一个节点
delete_cnode(&chead, 2);
// 查找一个节点
struct cnode *found_cnode = search_cnode(chead, 3);
if (found_cnode != NULL) {
printf("找到节点:%d\n", found_cnode->data);
} else {
printf("未找到节点\n");
}
return 0;
}
总结
双向链表和双向循环链表在数据结构中占有重要地位,它们具有高效查找、