双向链表的创建、插入和删除、宏定义函数

简介: 双向链表的创建、插入和删除、宏定义函数

摘要:本文介绍双向链表的实现:创建、插入、删除,以及宏定义版本

所谓双链表即每个节点有两个指针:prev指向前一个节点,next指向后一个节点

struct node {
    int data;
    struct node *prev;
    struct node *next;
};

首先需要创建节点:

struct node* create_node(int data) {
    struct node* newnode = (struct node*)malloc(sizeof(struct node));
    if(newnode == NULL) {
        printf("内存分配失败");
        exit(1);
    }
        
    newnode->prev = NULL;
    newnode->next = NULL;
    newnode->data = data;
    
    return newnode;
}

对节点进行插入操作:

1.头插法

void insert(struct node **head, int data) {
    struct node *newnode = create_node(data);
    if (*head == NULL){
        *head = newnode;
        return;
    }
    newnode->next = *head;
    (*head)->prev = newnode;
    *head = newnode;
}

2.尾插法:

void insert(struct node **head, int data) {
    struct node *newnode = create_node(data);
    struct node *current = *head;
    if (current->next != NULL) {
        current = current->next;
    }
    current->next = newnode;
    newnode->prev = current;
}

删除一个节点:分为表头、表中、表尾

void delete(struct node**head, int data) {
    int status = 0;
    struct node *current = *head;
    while (current != NULL) {//从头节点遍历到最后一个节点
        if (current->data == data) {
            status = 1;//找到了
            break;
        }
        current = current->next;
    }
    if (!status) printf("未找到该数据所在节点\n");
    else {//节点在表尾
        if(current->next == NULL) {
            if (current->prev != NULL) // 先判断
              current->prev->next = NULL;
            free(current);
        }
        else if(current->prev == NULL) {//*******节点在表头!需要修改*head!**********
            *head = current->next;
            if(current->next != NULL)
               current->next->prev = NULL;//考虑删除该节点为唯一的节点的情况
            free(current);
        }
        else{//节点在表中
            current->prev->next = current->next;
            current->next->prev = current->prev;
            free(current);
        }
        (current) = NULL; /* 将current置为NULL 避免悬空指针(悬空指针指向一个已经被释放的空间的地址,没有访问权限)*/
        
    }
}

宏定义头插法: list是链表头指针,item是要插入的指针

#define LIST_INSERT(item, list) do {\
    if ((item) != NULL) {\
        (item)->prev = NULL;\
        if ((list) != NULL) {\
            (item)->next = (list);\
            (list)->prev = (item);\
        } else {\
            (item)->next = NULL;\
        }\
        (list) = (item);\ // 更新头指针
    }\
} while(0)

宏定义尾插法:

#define LIST_APPEND(item, list) do {\
    if ((item) != NULL) {\
        if ((list) == NULL) {\
            (list) = (item);\
            (item)->prev = NULL;\
        } else {\
            ListNode *temp = (list);\
            while (temp->next != NULL) {\
                temp = temp->next;\
            }\
            temp->next = (item);\
            (item)->prev = temp;\
        }\
        (item)->next = NULL;\ 
    }\
} while(0)

宏定义删除节点: 提供要删除的指针,进行删除

#define LIST_REMOVE(item, list) do {\
    if ((item) != NULL) {\
        if ((item)->prev != NULL) (item)->prev->next = (item)->next;\
        if ((item)->next != NULL) (item)->next->prev = (item)->prev;\
        if ((list) == (item)) (list) = (item)->next;\
        (item)->prev = (item)->next = NULL;\
    }\
} while(0)

宏定义查找删除节点:根据节点的data数据,先查找后删除:

#define DELETE_NODE(head, data) do {\
    int status = 0;\
    struct node *current = *(head);\
    while (current != NULL) {\
        if (current->data == data) {\
            status = 1;\
            break;\
        }\
        current = current->next;\
    }\
    if (!status) {\
        printf("未找到该数据所在节点\n");\
    } else {\
        struct node *temp = current;\
        if (current->next == NULL) {\
            if (current->prev != NULL)\
                current->prev->next = NULL;\
            free(temp);\
        } else if (current->prev == NULL) {\
            *(head) = current->next;\
            current->next->prev = NULL;\
            free(temp);\
        } else {\
            current->prev->next = current->next;\
            current->next->prev = current->prev;\
            free(temp);\
        }\
        (current) = NULL; /* 将current置为NULL 避免悬空指针*/\
    }\
} while(0)


目录
相关文章
|
5月前
|
算法
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
数据结构和算法学习记录——线性表之双向链表(上)-结点类型定义、初始化函数、创建新结点函数、尾插函数、打印函数、尾删函数
46 0
|
5月前
|
算法
数据结构和算法学习记录——线性表之双向链表(下)-头插函数、头删函数、查找函数、pos位置之前插入结点、pos位置删除结点及其复用、销毁链表函数
数据结构和算法学习记录——线性表之双向链表(下)-头插函数、头删函数、查找函数、pos位置之前插入结点、pos位置删除结点及其复用、销毁链表函数
28 0
|
5月前
|
算法
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
数据结构和算法学习记录——线性表之单链表(下)-头插函数、尾删函数、头删函数、查找函数、pos位置插入&删除数据、单链表销毁
62 0
|
5月前
|
存储 算法
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
数据结构和算法学习记录——线性表之单链表(上)-初始单链表及其尾插函数(顺序表缺陷、单链表优点、链表打印)
38 0
|
6月前
|
存储 缓存 C++
C++链表常用的函数编写(增查删改)内附完整程序
C++链表常用的函数编写(增查删改)内附完整程序
108 0
|
6月前
|
算法 Java C++
数据结构与算法面试题:实现一个函数,判断一个链表是否为回文链表。(提示:反转后半部分链表比对前半部分)
数据结构与算法面试题:实现一个函数,判断一个链表是否为回文链表。(提示:反转后半部分链表比对前半部分)
34 0
双链表(常见的10个函数接口,配图详解每一个函数接口)(下)
双链表(常见的10个函数接口,配图详解每一个函数接口)(下)
113 0
双链表(常见的10个函数接口,配图详解每一个函数接口)(下)
|
存储
双链表(常见的10个函数接口,配图详解每一个函数接口)(上)
双链表(常见的10个函数接口,配图详解每一个函数接口)(上)
128 0
双链表(常见的10个函数接口,配图详解每一个函数接口)(上)
|
算法 Python
python与算法:单链表剖分函数(对链表的元素可以按照是否满足特定功能切分为两个新的链表)
python与算法:单链表剖分函数(对链表的元素可以按照是否满足特定功能切分为两个新的链表)
90 0
|
算法 前端开发 JavaScript
【前端算法】定义一个JS函数,反转单向链表
介绍链表与数组的区别,以及它们之间的联系