📜  XOR链表–查找中间节点(1)

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

XOR链表

XOR链表是一种比较特殊且高效的链表,它通过对两个节点地址的异或操作来存储前驱和后继节点的地址,因此每个节点只需要一个指针来指向其前驱和后继节点,相比于传统的双向链表可以节省一半的空间。

实现
struct Node {
    int data;
    Node* XOR; // 存储前驱和后继节点的异或值
};

XOR链表的操作主要有创建、插入和删除三个主要操作,其中插入和删除操作的实现需要考虑指针的异或操作。

创建

XOR链表的创建需要调用malloc动态分配内存,因此需要确保在使用完毕后及时调用free函数释放内存。

Node* head = NULL; // 头节点

Node* createNode(int data) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->data = data;
    node->XOR = NULL;
    return node;
}
插入

在XOR链表中插入一个节点需要注意节点的前驱和后继指针的异或操作,具体实现如下:

void insert(Node** head_ref, int data) {
    Node* node = createNode(data);
    node->XOR = *head_ref;
    if (*head_ref != NULL) {
        // 将原先的 *head_ref->XOR 修改为 (node ^ (*head_ref->XOR))
        (*head_ref)->XOR = (Node*)((uintptr_t)(*head_ref)->XOR ^ (uintptr_t)node);
    }
    *head_ref = node;
}
删除

在XOR链表中删除一个节点,需要先找到待删除节点的前驱和后继节点,并修改其前驱和后继节点的XOR指针。具体实现如下:

void deleteNode(Node** head_ref, Node* del_node) {
    Node* pre_node = NULL;
    Node* cur_node = *head_ref;
    Node* next_node = NULL;

    while (cur_node != NULL) {
        if (cur_node == del_node) {
            // 修改前驱节点的XOR指针
            if (pre_node != NULL) {
                pre_node->XOR = (Node*)((uintptr_t)pre_node->XOR ^ (uintptr_t)cur_node ^ (uintptr_t)cur_node->XOR);
            } else {
                *head_ref = cur_node->XOR;
            }
            
            // 修改后继节点的XOR指针
            next_node = (Node*)((uintptr_t)pre_node ^ (uintptr_t)cur_node->XOR);
            if (next_node != NULL) {
                next_node->XOR = (Node*)((uintptr_t)next_node->XOR ^ (uintptr_t)cur_node ^ (uintptr_t)pre_node);
            }

            free(cur_node);
            return;
        }

        // 查找cur_node节点的后继节点
        next_node = (Node*)((uintptr_t)pre_node ^ (uintptr_t)cur_node->XOR);
        pre_node = cur_node;
        cur_node = next_node;
    }
}
查找中间节点

在XOR链表中查找中间节点需要使用快慢指针的方式,其中慢指针每次移动1个节点,快指针每次移动2个节点。当快指针到达链表尾部时,慢指针正好位于中间节点。

Node* getMiddleNode(Node* head) {
    Node* slow = head;
    Node* fast = head;

    while (fast != NULL && fast->XOR != NULL) {
        fast = (Node*)((uintptr_t)slow->XOR ^ (uintptr_t)fast->XOR);
        slow = (Node*)((uintptr_t)fast->XOR ^ (uintptr_t)slow->XOR);
    }

    return slow; // 返回中间节点
}
总结

XOR链表相比传统的链表可以更高效地利用内存空间,但是其实现相对复杂,需要使用指针的异或操作才能定位前后节点。在实际使用中需要注意内存泄漏和指针操作的正确性。