双向链表实现

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

提示:这里可以添加本文要记录的大概内容:

双向链表:可选支持带多线程锁
链表可以实现 队列和栈等常用数据结构


提示:以下是本篇文章正文内容,下面案例可供参考

一、双向链表是什么?

双向链表(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实现,可以多线程运行

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值