📌  相关文章
📜  从双向链表中删除小于给定值的所有节点(1)

📅  最后修改于: 2023-12-03 15:06:34.131000             🧑  作者: Mango

从双向链表中删除小于给定值的所有节点

双向链表是一种链表数据结构的变种,它与普通链表最大的不同在于每个节点有两个指针,分别指向前面一个节点和后面一个节点。删除双向链表中小于给定值的所有节点需要考虑这种数据结构的特点,下面我们就一步步来讲解。

1. 首先要定义双向链表节点的结构体
typedef struct Node {
    int val;
    struct Node* prev;
    struct Node* next;
} Node;

其中,val表示节点的值,prevnext分别表示当前节点的前驱节点和后继节点。

2. 创建双向链表

我们可以用下面的函数来创建一个双向链表。

Node* createList(int arr[], int size) {
    Node* head = NULL;
    Node* tail = NULL;
    Node* cur = NULL;

    for (int i = 0; i < size; i++) {
        cur = (Node*)malloc(sizeof(Node));
        cur->val = arr[i];
        cur->prev = tail;
        cur->next = NULL;

        if (tail == NULL) {
            head = cur;
            tail = cur;
        } else {
            tail->next = cur;
            tail = cur;
        }
    }

    return head;
}

这个函数接收一个整数数组和整数数组的长度作为参数,返回一个双向链表的头节点。

3. 删除小于给定值的节点

删除小于给定值 value 的节点,可以采用以下思路:

  • 从头节点开始遍历双向链表。
  • 如果当前节点的 val 小于 value,则将其从链表中删除。
  • 如果当前节点的 val 大于等于 value,则继续往下遍历。

以下是具体实现:

void removeNodes(Node** head, int value) {
    Node* cur = *head;
    Node* temp = NULL;

    while (cur != NULL) {
        if (cur->val < value) {  // 删除当前节点
            if (cur == *head) {  // 删除头节点
                *head = cur->next;
                if (*head != NULL) {
                    (*head)->prev = NULL;
                }
            } else if (cur->next == NULL) {  // 删除尾节点
                cur->prev->next = NULL;
            } else {  // 删除中间节点
                cur->prev->next = cur->next;
                cur->next->prev = cur->prev;
            }

            temp = cur;
            cur = cur->next;
            free(temp);
        } else {  // 继续往下遍历
            cur = cur->next;
        }
    }
}

这个函数接收一个指向双向链表头节点的指针和一个整数 value 作为参数,没有返回值。需要注意的是,由于我们可能需要修改头节点,所以这里传入了指向指针的指针。

4. 完整代码
#include <stdio.h>
#include <stdlib.h>

typedef struct Node {
    int val;
    struct Node* prev;
    struct Node* next;
} Node;

Node* createList(int arr[], int size) {
    Node* head = NULL;
    Node* tail = NULL;
    Node* cur = NULL;

    for (int i = 0; i < size; i++) {
        cur = (Node*)malloc(sizeof(Node));
        cur->val = arr[i];
        cur->prev = tail;
        cur->next = NULL;

        if (tail == NULL) {
            head = cur;
            tail = cur;
        } else {
            tail->next = cur;
            tail = cur;
        }
    }

    return head;
}

void removeNodes(Node** head, int value) {
    Node* cur = *head;
    Node* temp = NULL;

    while (cur != NULL) {
        if (cur->val < value) {  // 删除当前节点
            if (cur == *head) {  // 删除头节点
                *head = cur->next;
                if (*head != NULL) {
                    (*head)->prev = NULL;
                }
            } else if (cur->next == NULL) {  // 删除尾节点
                cur->prev->next = NULL;
            } else {  // 删除中间节点
                cur->prev->next = cur->next;
                cur->next->prev = cur->prev;
            }

            temp = cur;
            cur = cur->next;
            free(temp);
        } else {  // 继续往下遍历
            cur = cur->next;
        }
    }
}

void printList(Node* head) {
    Node* cur = head;

    while (cur != NULL) {
        printf("%d ", cur->val);
        cur = cur->next;
    }

    printf("\n");
}

int main() {
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int size = sizeof(arr) / sizeof(arr[0]);
    Node* list = createList(arr, size);
    int value = 5;

    printf("Original list: ");
    printList(list);

    removeNodes(&list, value);

    printf("List after removing nodes less than %d: ", value);
    printList(list);

    return 0;
}
5. 总结

本文介绍了如何从双向链表中删除小于给定值的所有节点。我们通过遍历双向链表,删除每个小于给定值的节点,最后得到了一个新的双向链表。需要注意的是,这里需要修改指向指针的指针,以便正确地处理头节点。