提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
提示:这里可以添加本文要记录的大概内容:
双向链表:可选支持带多线程锁
链表可以实现 队列和栈等常用数据结构
提示:以下是本篇文章正文内容,下面案例可供参考
一、双向链表是什么?
双向链表(Doubly Linked List)是一种数据结构,它是链表的一种形式,其中的每个节点包含三个部分:数据、一个指向前一个节点的引用(前驱节点)和一个指向后一个节点的引用(后继节点)。这种结构允许在链表中向前和向后遍历,提供了比单向链表更多的灵活性。
双向链表的主要优点包括:
双向遍历:由于每个节点都有前后两个方向的引用,因此可以从链表的任一端开始遍历,这在某些情况下可以提高效率。
易于插入和删除:与单向链表相比,双向链表在插入或删除节点时,可以同时更新前驱和后继节点的引用,使操作更加高效。
灵活的操作:双向链表支持在列表的任意位置进行快速插入和删除,而无需遍历整个链表。
二、代码示例
不需要支持多线程可以注释 #define USE_MUTEX,可以省去锁的开销
double_list.h
#ifndef _DOUBLE_LIST_H_
#define _DOUBLE_LIST_H_
#define USE_MUTEX
#define MYTYPE int
typedef struct DoublyListNode {
MYTYPE data;
struct DoublyListNode* prev;
struct DoublyListNode* next;
} DoublyListNode;
typedef struct DoublyLinkedList {
DoublyListNode* head;
DoublyListNode* tail;
#ifdef USE_MUTEX
pthread_mutex_t lock; // 添加互斥锁
#endif
} DoublyLinkedList;
void initDoublyList(DoublyLinkedList* list);
void clearDoublyList(DoublyLinkedList* list);
void printDoublyList(DoublyLinkedList* list);
int insertAtHead(DoublyLinkedList *list, MYTYPE value);
int insertAtTail(DoublyLinkedList *list, MYTYPE value);
int deleteAtHead(DoublyLinkedList *list, MYTYPE *value);
int deleteAtTail(DoublyLinkedList *list, MYTYPE *value);
#endif
double_list.c
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include "double_list.h"
#include <string.h>
void initDoublyList(DoublyLinkedList* list) {
list->head = NULL;
list->tail = NULL;
#ifdef USE_MUTEX
pthread_mutex_init(&list->lock, NULL); // 初始化互斥锁
#endif
}
//清空链表
void clearDoublyList(DoublyLinkedList* list) {
DoublyListNode* current = list->head;
while (current != NULL) {
DoublyListNode* next = current->next;
//printf("clearDoublyList free\n");
free(current);
current = next;
}
list->head = NULL;
list->tail = NULL;
#ifdef USE_MUTEX
pthread_mutex_destroy(&list->lock);
#endif
}
//遍历并打印链表
void printDoublyList(DoublyLinkedList* list) {
#ifdef USE_MUTEX
pthread_mutex_lock(&list->lock);
#endif
DoublyListNode* current = list->head;
while (current != NULL) {
printf("%d <-> ", current->data);
current = current->next;
}
printf("NULL\n");
#ifdef USE_MUTEX
pthread_mutex_unlock(&list->lock);
#endif
}
//向链表头部插入元素
int insertAtHead(DoublyLinkedList *list, MYTYPE value) {
int ret = 0;
#ifdef USE_MUTEX
pthread_mutex_lock(&list->lock);
#endif
if(list == NULL)
{
printf("invalid parameter\n");
ret = -1;
goto error;
}
DoublyListNode *newNode = (DoublyListNode *)malloc(sizeof(DoublyListNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
ret = -1;
goto error;
}
memcpy(&(newNode->data), &value, sizeof(MYTYPE));
newNode->prev = NULL;
newNode->next = list->head;
if (list->head != NULL)
list->head->prev = newNode;
else
list->tail = newNode;
list->head = newNode;
error:
#ifdef USE_MUTEX
pthread_mutex_unlock(&list->lock);
#endif
return 0;
}
//向链表尾部插入元素
int insertAtTail(DoublyLinkedList *list, MYTYPE value) {
int ret = 0;
#ifdef USE_MUTEX
pthread_mutex_lock(&list->lock);
#endif
if(list == NULL)
{
printf("invalid parameter\n");
ret = -1;
goto error;
}
DoublyListNode *newNode = (DoublyListNode *)malloc(sizeof(DoublyListNode));
if (newNode == NULL) {
printf("Memory allocation failed\n");
ret = -1;
goto error;
}
memcpy(&(newNode->data), &value, sizeof(MYTYPE));
newNode->next = NULL;
newNode->prev = list->tail;
if (list->tail != NULL)
list->tail->next = newNode;
else
list->head = newNode;
list->tail = newNode;
error:
#ifdef USE_MUTEX
pthread_mutex_unlock(&list->lock);
#endif
return 0;
}
//从链表头部删除元素
int deleteAtHead(DoublyLinkedList *list, MYTYPE * value) {
int ret = 0;
if(list == NULL || value == NULL)
{
printf("invalid parameter\n");
return -1;
}
#ifdef USE_MUTEX
pthread_mutex_lock(&list->lock);
#endif
if (list->head == NULL) {
printf("List is empty\n");
list->tail = NULL;
ret = -1;
goto error;
}
// 头和尾指针指向一个node,只有一个元素
if(list->head == list->tail)
{
list->tail = NULL;
list->head->next = NULL;
}
DoublyListNode *nodeToDelete = list->head;
memcpy(value, &(nodeToDelete->data), sizeof(MYTYPE));
list->head = nodeToDelete->next;
if (list->head != NULL)
list->head->prev = NULL;
// else
// list->tail = NULL;
//printf("deleteAtHead free\n");
free(nodeToDelete);
error:
#ifdef USE_MUTEX
pthread_mutex_unlock(&list->lock);
#endif
return 0;
}
//从链表末尾删除元素
int deleteAtTail(DoublyLinkedList *list, MYTYPE * value) {
int ret = 0;
if(list == NULL || value == NULL)
{
printf("invalid parameter\n");
return -1;
}
#ifdef USE_MUTEX
pthread_mutex_lock(&list->lock);
#endif
if (list->tail == NULL) {
printf("List is empty\n");
list->head = NULL;
ret = -1;
goto error;
}
// 头和尾指针指向一个node,只有一个元素
if(list->head == list->tail)
{
list->head = NULL;
list->tail->prev = NULL;
}
DoublyListNode *nodeToDelete = list->tail;
memcpy(value, &(nodeToDelete->data), sizeof(MYTYPE));
list->tail = nodeToDelete->prev;
if (list->tail != NULL)
list->tail->next = NULL;
// else
// list->head = NULL;
//printf("deleteAtTail free\n");
free(nodeToDelete);
error:
#ifdef USE_MUTEX
pthread_mutex_unlock(&list->lock);
#endif
return ret;
}
总结
双线链表c实现,可以多线程运行