1.头文件

#ifndef _LINKLIST_H_
#define _LINKLIST_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>

typedef struct DLinklist
{
    int data;
    struct DLinklist *next;
    struct DLinklist *prev;
}*DLinklist, DNode;

#define TRAVERSE printf("TRAVERSE: %s-%d\n",traverse(head)?"SUCCESS":"NULL", __LINE__);

/*
双向链表的遍历
@param head 头指针
@return 遍历成功,返回true,否则返回false
*/
bool traverse(DLinklist head);


/*
头插法建立链表
@param head 头指针
@param data 待插入的数据
@return 创建成功,返回true,否则返回false
*/
bool insertHead(DLinklist* head, int data);

/*
尾插法建立链表
@param head 头指针
@param data 待插入的数据
@return 创建成功,返回true,否则返回false
*/
bool insertTail(DLinklist* head, int data);

/*
删除第一个节点(头节点的后一个节点)
@param head 头指针
@return 删除成功,返回true,否则返回false
*/
bool deleteHead(DLinklist* head);

/*
删除最后一个节点
@param head 头指针
@return 删除成功,返回true,否则返回false
*/
bool deleteTail(DLinklist* head);

/*
在某一位置插入节点(默认从1开始,第0个位置为链表的头结点)
@param head 链表头结点
@param data 插入数据
@param index 插入位置
@return 插入成功返回true,失败返回false
*/
bool insertByPos(DLinklist* head, int data, int pos);

/*
删除指定位置的节点(默认从1开始,第0个位置为链表的头结点)
@param head 头指针
@param pos 待删除节点的位置
@return 删除成功,返回true,否则返回false
*/
bool deleteByPos(DLinklist* head, int pos);

/*
删除指定值的节点
@param head 头指针
@param data 待删除节点的值
@param returnArr 返回删除的节点的位置
@return 删除成功,返回true,否则返回false
*/
bool deleteByValue(DLinklist* head, int data, int *returnArr);

/*
修改链表某一位置的元素值(默认从1开始,第0个位置为链表的头结点)
@param head 链表头结点
@param data 目标值
@param index 目标位置
@return 修改成功返回true,失败返回false
*/
bool updateByIndex(DLinklist* head, int data, int index);

/*
修改链表中元素值等于目标值的节点(多个相等全部修改)
@param head 链表头结点
@param data 目标值
@param newData 新值
@return 修改成功返回true,失败返回false
*/
bool updateByValue(DLinklist* head, int data, int newData);

/*
释放链表的所有节点
@param head 链表头结点
@return 释放成功返回true,失败返回false
*/
bool freeLinklist(DLinklist* head);
#endif

2.源文件

#include "DLinklist.h"

int main(int argc, char const *argv[])
{
    DLinklist head = (DLinklist)malloc(sizeof(DNode));
    head->data = 0;
    head->next = NULL;
    head->prev = NULL;

    for(int i = 0; i < 10; i++)
    {
        //insertHead(&head, i);
        insertTail(&head, i);
    }
    TRAVERSE;

    deleteHead(&head);
    TRAVERSE;

    deleteTail(&head);
    TRAVERSE;

    deleteByPos(&head, 2);
    TRAVERSE;

    int *arr;
    if(deleteByValue(&head, 8, arr))
    {
        printf("num:%d\n", arr[0]);
        if(arr[0] != 0)
        {
            for (int i = 0; i < arr[0]; i++)
            {
                printf("%d ", arr[i + 1]);
            }
            puts("");        
        }
    }
    TRAVERSE;

    insertByPos(&head, 8, 2);
    TRAVERSE;

    updateByIndex(&head, 8, 5);
    TRAVERSE;

    updateByValue(&head, 8, 6);
    TRAVERSE;

    printf("%d\n", freeLinklist(&head));
    TRAVERSE;
    return 0;
}

bool traverse(DLinklist head)
{
    if(head == NULL)
        return false;
    else
    {
        int cnt = 0;
        DNode* p = head;
        while(p != NULL)
        {
            cnt++;
            printf("%d ", p->data);
            p = p->next;
        }
        printf("\n");

        if(cnt - 1 == head->data)
            return true;
        return false;
    }
}

bool insertHead(DLinklist* head, int data)
{
    if((*head) == NULL)
        return false;

    DNode* new = (DNode *)malloc(sizeof(DNode));
    if(new == NULL)
        return false;
    
    new->next = NULL;
    new->prev = NULL;
    new->data = data;
    if((*head)->next == NULL)
    {
        (*head)->next = new;
        new->prev = (*head);
        (*head)->data++;
        return true;
    }
    else
    {
        DNode* p = (*head)->next;
        new->prev = (*head);
        (*head)->next = new;
        new->next = p;
        p->prev = new;
        (*head)->data++;
        return true;
    }
}

bool insertTail(DLinklist* head, int data)
{
    if((*head) == NULL)
        return false;

    DNode* new = (DNode *)malloc(sizeof(DNode));
    if(new == NULL)
        return false;
    
    new->next = NULL;
    new->prev = NULL;
    new->data = data;

    DNode* p = (*head);
    while(p->next != NULL)
    {
        p = p->next; // 遍历到尾部
    }
    p->next = new;
    new->prev = p;
    (*head)->data++;
    return true;
}

bool deleteHead(DLinklist* head)
{
    if((*head) == NULL)
        return false;

    if((*head)->next == NULL)
        return true;
    
    DNode* p = (*head)->next;
    (*head)->next = p->next;
    p->next->prev = (*head);
    free(p); p = NULL;
    (*head)->data--;
    return true;
}

bool deleteTail(DLinklist* head)
{
    if((*head) == NULL)
        return false;
    
    DNode* p = (*head);
    while(p->next != NULL)
    {
        p = p->next;
    }

    p->prev->next = NULL;
    p->prev = NULL;
    free(p); p = NULL;
    (*head)->data--;
    return true;
}

bool deleteByPos(DLinklist* head, int pos)
{
    if((*head) == NULL || (*head)->next == NULL)
        return false;

    if(pos < 1 || pos > (*head)->data)
        return false;
    
    DNode* p = (*head)->next;
    for(int i = 1; i < pos; i++)
    {
        p = p->next;
    }
    p->prev->next = p->next;
    p->next->prev = p->prev;
    free(p); p = NULL;
    (*head)->data--;
    return true;
}

bool deleteByValue(DLinklist* head, int data, int *returnArr) {
    if (*head == NULL || (*head)->next == NULL)
        return false;
    
    int pos = 1, count = 0;
    DNode* p = (*head)->next;
    while (p != NULL) 
    {
        DNode* q = p->next;
        if (p->data == data) {
            if (p->prev) p->prev->next = q;
            if (q) q->prev = p->prev;
            returnArr[++count] = pos;  // 存储已删除节点的位置
            free(p); p = NULL;
            (*head)->data--;  // 更新头节点数据
        }
        p = q;
        pos++;
    }
    
    if (count == 0)
        return false;
    
    returnArr[0] = count;
    return true;
}

bool insertByPos(DLinklist* head, int data, int pos)
{
    if(*head == NULL)
        return false;
    
    if(pos < 1 || pos > (*head)->data)
        return false;
    
    DNode* new = (DLinklist)malloc(sizeof(DNode));
    if(new == NULL)
        return false;

    new->data = data;
    new->next = NULL;
    new->prev = NULL;
    (*head)->data++;

    DNode* p = (*head)->next;
    for(int i = 1; i < pos - 1; i++)
    {
        p = p->next;
    }
    new->next = p->next;
    p->next->prev = new;
    p->next = new;
    new->prev = p;
    return true;
}

bool updateByIndex(DLinklist* head, int data, int index)
{
    if(*head == NULL || (*head)->next == NULL)
        return false;

    if(index < 1 || index > (*head)->data)
        return false;

    DNode* p = (*head)->next;
    for(int i = 1; i < index; i++)
    {
        p = p->next;
    }
    p->data = data;
    return true;
}

bool updateByValue(DLinklist* head, int data, int newData)
{
    if(*head == NULL || (*head)->next == NULL)
        return false;
    
    int cnt = 0;
    DNode* p = (*head)->next;
    while(p != NULL)
    {
        if(p->data == data)
        {
            p->data = newData;
            cnt++;
        }
        p = p->next;
    }
    if(cnt == 0)
        return false;
    return true;
}

bool freeLinklist(DLinklist* head)
{
    if((*head) == NULL) 
        return true;
        
    DNode* p = (*head);
    while(p != NULL)
    {
        DNode* q = p->next;
        free(p); p = NULL;
        p = q;
    }

    *head = NULL; // 将头指针设置为 NULL 防止悬挂指针
    return true;
}