📅  最后修改于: 2023-12-03 15:10:20.022000             🧑  作者: Mango
循环双链表是一种经典的数据结构。它与普通的双链表类似,每个节点包含两个指针,一个指向前一个节点,一个指向后一个节点。不同之处在于,循环双链表中,头节点的前驱指针指向尾节点,尾节点的后继指针指向头节点。这样可以实现循环遍历。
在实际应用中,循环双链表常用于实现内存池、LRU缓存淘汰算法等高效的数据结构。
循环双链表的创建需要先创建一个头节点,其前驱和后继指针均指向自身:
typedef struct Node {
int data;
struct Node *prev;
struct Node *next;
} Node;
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
head->prev = head;
head->next = head;
return head;
}
插入节点可以分为在头节点之后插入、在尾节点之前插入、在任意位置插入三种情况。具体实现如下:
void insertAfter(Node *prevNode, int newData) {
if (prevNode == NULL) {
return;
}
Node *newNode = (Node *) malloc(sizeof(Node));
newNode->data = newData;
newNode->next = prevNode->next;
prevNode->next->prev = newNode;
newNode->prev = prevNode;
prevNode->next = newNode;
}
void insertBefore(Node *nextNode, int newData) {
if (nextNode == NULL) {
return;
}
Node *newNode = (Node *) malloc(sizeof(Node));
newNode->data = newData;
newNode->prev = nextNode->prev;
nextNode->prev->next = newNode;
newNode->next = nextNode;
nextNode->prev = newNode;
}
void insertAt(Node *head, int index, int newData) {
if (head == NULL) {
return;
}
Node *curNode = head->next;
int i = 0;
while (curNode != head && i < index) {
curNode = curNode->next;
i++;
}
if (curNode == head) {
insertBefore(head, newData);
} else {
insertBefore(curNode, newData);
}
}
其中,insertAfter()
实现在prevNode节点之后插入新节点;insertBefore()
实现在nextNode节点之前插入新节点;insertAt()
实现在第index个节点之前插入新节点。
删除节点可以分为三种情况:删除头节点、删除尾节点、删除任意节点。具体实现如下:
void deleteNode(Node *head, int key) {
if (head == NULL) {
return;
}
Node *curNode = head->next;
while (curNode != head && curNode->data != key) {
curNode = curNode->next;
}
if (curNode == head) {
return;
}
curNode->prev->next = curNode->next;
curNode->next->prev = curNode->prev;
free(curNode);
}
void deleteFirst(Node *head) {
if (head == NULL) {
return;
}
Node *firstNode = head->next;
head->next = firstNode->next;
firstNode->next->prev = head;
free(firstNode);
}
void deleteLast(Node *head) {
if (head == NULL) {
return;
}
Node *lastNode = head->prev;
head->prev = lastNode->prev;
lastNode->prev->next = head;
free(lastNode);
}
其中,deleteNode()
实现删除某个节点;deleteFirst()
实现删除头节点;deleteLast()
实现删除尾节点。
遍历循环双链表可以从头节点开始遍历,一直遍历到头节点即可。具体实现如下:
void traverseList(Node *head) {
if (head == NULL) {
return;
}
Node *curNode = head->next;
while (curNode != head) {
printf("%d ", curNode->data);
curNode = curNode->next;
}
printf("\n");
}
循环双链表作为一种经典的数据结构,具有很多优秀的特性,如高效的插入和删除操作、循环遍历等。在实际应用中,循环双链表可以用来实现内存池、LRU缓存淘汰算法等高效的数据结构。