算法导论10.2-8

题目:
说明如何在每个元素仅使用一个指针x.np(而不是通常的两个指针next和prev)的情况下实现双向链表。假设所有的指针的值都可视为k位的整数,且定义x.np=x.next XOR x.prev,即x.next和x.prev的位异或。(Nil的值用0来表示)注意要说明要获取的表头所需的信息,并说明如何在该表上实现SEARCH、INSERT和DELETE操作,以及如何在O(1)时间内实现该表的逆转。
解答:
该题主要利用到了异或运算的自反性。设x.prev的地址为a,x.next的地址为b, r=a XOR b ,则有 a XOR r=a XOR a XOR b=b b XOR r=b XOR a XOR b=a 。以上两式即为求前驱元素和后继元素地址的关键。若想求得链表中元素的后继元素,则需知道链表的x.np以及x.prev。若为第一个元素,则可视其前驱元素地址为NULL。若为最后一个元素,则可视其后继元素地址为NULL。对于该链表的逆转只需交换链表头指针和尾指针即可。
关于该题的一些数据结构的声明如下:

typedef struct SINGLE_POINTER_NODE
{
    struct SINGLE_POINTER_NODE * np;
    item_t item;
} SinglePNode;
typedef struct SINGLE_POINTER_DOUBLE_LINKED_LIST
{
    SinglePNode * head;
    SinglePNode * tail;
} SPDLL;
SinglePNode* XOR(SinglePNode * left, SinglePNode * right);
SinglePNode* single_pointer_double_linked_list_insert(SPDLL * L, item_t item);
SinglePNode* single_pointer_double_linked_list_search(SPDLL * L, item_t item);
int single_pointer_double_linked_list_delete(SPDLL * L, SinglePNode * node);
int single_pointer_double_linked_list_reverse(SPDLL * L);
void single_pointer_double_linked_list_traverse(SPDLL * L);

具体C语言实现如下:

//functions for single pointer linked list
SinglePNode* XOR(SinglePNode * left, SinglePNode * right) {
    return (SinglePNode*)((unsigned long)left ^ (unsigned long)right);
}
SinglePNode* single_pointer_double_linked_list_insert(SPDLL * L, item_t item) {
    SinglePNode * node = (SinglePNode*)malloc(sizeof(SinglePNode));
    node->item = item;
    node->np = XOR(NULL, L->head);
    if (L->head == NULL) {
        L->tail = node;
        L->head = node;
    } else {
        SinglePNode * next = XOR(NULL, L->head->np);
        L->head->np = XOR(node, next);
        L->head = node;
    }
    return node;
}
SinglePNode* single_pointer_double_linked_list_search(SPDLL * L, item_t item) {
    if (L->head == NULL) {
        fprintf(stderr, "Empty single pointer double linked list.\n");
        return NULL;
    }
    SinglePNode * pre = NULL;
    SinglePNode * pos = L->head;
    SinglePNode * next = NULL;
    while (pos != NULL) {
        if (pos->item.key == item.key)
            return pos;
        next = XOR(pre, pos->np);
        pre = pos;
        pos = next;
    }
    fprintf(stderr, "The item cannot be found.\n");
    return NULL;
}
int single_pointer_double_linked_list_delete(SPDLL * L, SinglePNode * node) {
    if (L->head == NULL) {
        fprintf(stderr, "The single pointer double linked linked list is empty.\n");
        return 0;
    }
    if (node == NULL) {
        fprintf(stderr, "The node is NULL.\n");
        return 0;
    }
    SinglePNode * pre = NULL;
    SinglePNode * pos = L->head;
    SinglePNode * next = XOR(pre, pos->np);
    while (pos != node && pos != NULL) {
        pre = pos;
        pos = next;
        next = XOR(pre, pos->np);
    }
    if (pos == NULL) {
        fprintf(stderr, "No such node in linked list.\n");
        return 0;
    }
    if (L->head == L->tail) {
        L->head = NULL;
        L->tail = NULL;
        return 1;
    }
    SinglePNode * NNext = NULL;
    SinglePNode * PPre = NULL;
    if (pre == NULL) {
        NNext = XOR(pos, next->np);
        next->np = XOR(NULL, NNext);
        L->head = next;
        return 1;
    }
    if (next == NULL) {
        PPre = XOR(pre->np, pos);
        pre->np = XOR(PPre, NULL);
        L->tail = pre;
        return 1;
    }
    PPre = XOR(pre->np, pos);
    NNext = XOR(pos, next->np);
    pre->np = XOR(PPre, next);
    next->np = XOR(pre, NNext);
    return 1;
}
int single_pointer_double_linked_list_reverse(SPDLL * L) {
    SinglePNode * temp = L->head;
    L->head = L->tail;
    L->tail = temp;
    return 1;
}
void single_pointer_double_linked_list_traverse(SPDLL * L) {
    if (L->head == NULL) {
        fprintf(stderr, "The single pointer double linked list is empty.\n");
        return;
    }
    SinglePNode * pre = NULL;
    SinglePNode * pos = L->head;
    SinglePNode * next = NULL;
    while (pos != NULL) {
        next = XOR(pre, pos->np);
        printf("%2d prev is %9p. in location:%9p. next is %9p. np is %9p.\n", \
            pos->item.key, pre, pos, next, pos->np);
        pre = pos;
        pos = next;
    }
}
//--------------------------------------------------------------------------

可用如下代码进行测试:

void test_for_single_pointer_double_linked_list() {
    SPDLL * L = (SPDLL*)malloc(sizeof(SPDLL));
    for (int i = 0; i < 10; i++) {
        item_t item = {i, NULL};
        single_pointer_double_linked_list_insert(L, item);
    }
    printf("Single pointer double linked list head is in location:%p\n", L->head);
    single_pointer_double_linked_list_traverse(L);
    for (int i = 11; i >= -1; i--) {
        item_t item = {i, NULL};
        SinglePNode * node = single_pointer_double_linked_list_search(L, item);
        if (node != NULL) {
            printf("Node %2d in location:%9p delete :%d\n", \
                node->item.key, node, single_pointer_double_linked_list_delete(L, node));
        }
    }
    printf("Single pointer double linked list head is in location:%p\n", L->head);
    single_pointer_double_linked_list_traverse(L);
    printf("---------------------------------------------------------------------\n");
    for (int i = 0; i < 10; i++) {
        item_t item = {i, NULL};
        single_pointer_double_linked_list_insert(L, item);
    }
    printf("Single pointer double linked list head is in location:%p\n", L->head);
    single_pointer_double_linked_list_traverse(L);
    for (int i = -1; i < 11; i++) {
        item_t item = {i, NULL};
        SinglePNode * node = single_pointer_double_linked_list_search(L, item);
        if (node != NULL) {
            printf("Node %2d in location:%9p delete :%d\n", \
                node->item.key, node, single_pointer_double_linked_list_delete(L, node));
        }
    }
    printf("Single pointer double linked list head is in location:%p\n", L->head);
    single_pointer_double_linked_list_traverse(L);
    printf("---------------------------------------------------------------------\n");
    for (int i = 0; i < 10; i++) {
        item_t item = {i, NULL};
        single_pointer_double_linked_list_insert(L, item);
    }
    single_pointer_double_linked_list_reverse(L);
    printf("Single pointer double linked list head is in location:%p\n", L->head);
    single_pointer_double_linked_list_traverse(L);
    for (int i = 5; i < 11; i++) {
        item_t item = {i, NULL};
        SinglePNode * node = single_pointer_double_linked_list_search(L, item);
        if (node != NULL) {
            printf("Node %2d in location:%9p delete :%d\n", \
                node->item.key, node, single_pointer_double_linked_list_delete(L, node));
        }
    }
    printf("Single pointer double linked list head is in location:%p\n", L->head);
    single_pointer_double_linked_list_traverse(L);
}

猜你喜欢

转载自blog.csdn.net/sinat_16709955/article/details/77611955