在我们采用链表结构对于数据进行存储的时候,我们往往优先想到的是简单单链表结构。但是在实际使用过程中,双向链表往往具有更好的执行效率,我们以链表的简单增删查改为例:
include <stdio.h>
#include <stdlib.h>
typedef char DLinkType;
typedef struct DLinkNode {
DLinkType data;
struct DLinkNode* next;
struct DLinkNode* prev;
} DLinkNode;
void DLinkListInit(DLinkNode** head){
if (head == NULL)
return;
if (*head == NULL)
return;
(*head)->next = NULL;
(*head)->prev = NULL;
return;
}
DLinkNode* DLinkListPushBack(DLinkNode* head, DLinkType value){//尾插
if (head == NULL)
return NULL;
DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
l->data = value;
l->next = head;
l->prev = head->prev;
head->prev->next = l;
head->prev = l;
return l;
}
void DLinListPopBack(DLinkNode* head){//尾删
if (head == NULL)
return;
DLinkNode* to_delete = head->prev;
head->prev->prev->next = head;
head->prev = head->prev->prev;
free(to_delete);
return;
}
void DLinkListPushFront(DLinkNode* head, DLinkType value){
if (head == NULL)
return;
DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
l->data = value;
l->prev = head;
l->next = head->next;
head->next->prev = l;
head->next = l;
return;
}
void DLinkListPopFront(DLinkNode* head){
if (head == NULL)
return;
DLinkNode* to_delete = head->next;
head->next = head->next->next;
head->next->prev = head;
free(to_delete);
return;
}
DLinkNode* DLinkListFind(DLinkNode* head, DLinkType to_find){
if (head == NULL)
return NULL;
DLinkNode* p =head->next;
while (p != head){
if (p->data = to_find)
return p;
p = p->next;
}
return NULL;
}
/**
* @brief 往指定位置之前插入一个元素
*/
void DLinkListInsert(DLinkNode* pos, DLinkType value){
if (pos == NULL)
return;
DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
l->next = pos;
l->prev = pos->prev;
pos->prev->next = l;
pos->prev = l;
return;
}
/**
* @brief 往指定位置之后插入一个元素
*/
void DLinkListInsertAfter(DLinkNode* pos, DLinkType value){
if (pos == NULL)
return;
DLinkNode* l = (DLinkNode*)malloc(sizeof(DLinkNode));
l->next = pos->next;
l->prev = pos;
pos->next->prev = l;
pos->next = l;
return;
}
void DLinkListErase(DLinkNode* pos){//删除指定节点
if (pos == NULL)
return;
pos->prev->next = pos->next;
pos->next->prev = pos->prev;
free(pos);
return;
}
void DLinkListEraseAll(DLinkNode** head){//删除所有节点
if (head == NULL)
return;
if (*head == NULL)
return;
DLinkNode* p =*head;
(*head)->prev = NULL;
DLinkNode* to_delete =*head;
while(p){
p = p->next;
free(to_delete);
to_delete = p;
}
return;
}
void DLinkListRemove(DLinkNode* head,DLinkType value){//删除指定值的节点
if (head == NULL)
return;
DLinkNode* p =head->next;
while(p != head){
if (p->data == value){
DLinkListErase(p);
return;
}
p = p->next;
}
}
void DLinkListRemoveAll(DLinkNode* head,DLinkType value){//删除指定值得所有节点
if (head == NULL)
return;
DLinkNode* p =head->next;
while(p != head){
if (p->data == value){
DLinkListErase(p);
}
p = p->next;
}
return;
}
size_t DLinkListSize(DLinkNode* head){//判断链表长度
if (head == NULL)
return 0;
DLinkNode* p = head->next;
size_t count = 1;
while (p != head){
++count;
p = p->next;
}
return count;
}
int main() {
printf("Hello, World!\n");
return 0;
}
对比上文的
单向链表的增删查改,我们可以看到,由于双向链表可以方便的查找到上一个节点,所以省去了很多的遍历过程。这也是一种使用空间来换时间的方法。