数据结构与算法之链表 双向链表边界 头节点无前驱

数据结构与算法阿木 发布于 2025-07-11 6 次阅读


摘要:

双向链表是一种常见的线性数据结构,它由一系列节点组成,每个节点包含数据域和两个指针域,分别指向前一个节点和后一个节点。本文将围绕双向链表边界(头节点无前驱)这一主题,通过代码实现来深入解析双向链表的基本操作,包括初始化、插入、删除、遍历等。

一、

双向链表是一种具有两个指针域的链表,每个节点包含数据域和两个指针域,分别指向前一个节点和后一个节点。与单向链表相比,双向链表提供了更灵活的操作,可以在任意位置快速插入或删除节点。本文将重点介绍双向链表边界(头节点无前驱)的代码实现。

二、双向链表的基本结构

在实现双向链表之前,首先定义双向链表的节点结构体:

c

typedef struct DoublyLinkedListNode {


int data; // 数据域


struct DoublyLinkedListNode prev; // 前驱指针


struct DoublyLinkedListNode next; // 后继指针


} DoublyLinkedListNode;


三、双向链表的初始化

初始化双向链表时,通常需要一个头节点,头节点不存储数据,仅作为链表的起点。以下是初始化双向链表的代码实现:

c

DoublyLinkedListNode createDoublyLinkedList() {


DoublyLinkedListNode head = (DoublyLinkedListNode)malloc(sizeof(DoublyLinkedListNode));


if (head == NULL) {


return NULL;


}


head->data = 0; // 头节点不存储数据,可以设置为0或其他标记值


head->prev = NULL; // 头节点无前驱


head->next = NULL; // 初始化时,链表为空,无后继节点


return head;


}


四、双向链表的插入操作

插入操作包括在链表头部、尾部和中间位置插入节点。以下是插入操作的代码实现:

c

// 在链表头部插入节点


void insertAtHead(DoublyLinkedListNode head, int data) {


DoublyLinkedListNode newNode = (DoublyLinkedListNode)malloc(sizeof(DoublyLinkedListNode));


if (newNode == NULL) {


return;


}


newNode->data = data;


newNode->next = head->next;


newNode->prev = head;


if (head->next != NULL) {


head->next->prev = newNode;


}


head->next = newNode;


}

// 在链表尾部插入节点


void insertAtTail(DoublyLinkedListNode head, int data) {


DoublyLinkedListNode newNode = (DoublyLinkedListNode)malloc(sizeof(DoublyLinkedListNode));


if (newNode == NULL) {


return;


}


newNode->data = data;


newNode->next = NULL;


newNode->prev = head->prev;


if (head->prev != NULL) {


head->prev->next = newNode;


}


head->prev = newNode;


}

// 在链表中间位置插入节点


void insertAfterNode(DoublyLinkedListNode prevNode, int data) {


if (prevNode == NULL) {


return;


}


DoublyLinkedListNode newNode = (DoublyLinkedListNode)malloc(sizeof(DoublyLinkedListNode));


if (newNode == NULL) {


return;


}


newNode->data = data;


newNode->next = prevNode->next;


newNode->prev = prevNode;


if (prevNode->next != NULL) {


prevNode->next->prev = newNode;


}


prevNode->next = newNode;


}


五、双向链表的删除操作

删除操作包括删除链表头部、尾部和中间位置的节点。以下是删除操作的代码实现:

c

// 删除链表头部节点


void deleteAtHead(DoublyLinkedListNode head) {


if (head->next == NULL) {


free(head);


return;


}


DoublyLinkedListNode temp = head->next;


head->next = temp->next;


if (temp->next != NULL) {


temp->next->prev = head;


}


free(temp);


}

// 删除链表尾部节点


void deleteAtTail(DoublyLinkedListNode head) {


if (head->prev == NULL) {


free(head);


return;


}


DoublyLinkedListNode temp = head->prev;


head->prev = temp->prev;


if (temp->prev != NULL) {


temp->prev->next = head;


}


free(temp);


}

// 删除链表中间位置的节点


void deleteAfterNode(DoublyLinkedListNode prevNode) {


if (prevNode == NULL || prevNode->next == NULL) {


return;


}


DoublyLinkedListNode temp = prevNode->next;


prevNode->next = temp->next;


if (temp->next != NULL) {


temp->next->prev = prevNode;


}


free(temp);


}


六、双向链表的遍历操作

遍历操作用于遍历链表中的所有节点,并打印或处理节点数据。以下是遍历操作的代码实现:

c

// 遍历双向链表


void traverseDoublyLinkedList(DoublyLinkedListNode head) {


DoublyLinkedListNode current = head->next; // 从头节点的下一个节点开始遍历


while (current != NULL) {


printf("%d ", current->data);


current = current->next;


}


printf("");


}


七、总结

本文通过代码实现深入解析了双向链表边界(头节点无前驱)的相关操作,包括初始化、插入、删除和遍历。双向链表作为一种灵活的数据结构,在实际应用中具有广泛的应用场景。通过掌握双向链表的基本操作,可以更好地理解和应用这一数据结构。

注意:以上代码仅为示例,实际应用中可能需要根据具体需求进行调整和优化。