算法导论10.2-8

来源:互联网 发布:金林钣金放样软件 编辑:程序博客网 时间:2024/05/16 16:08

题目:
说明如何在每个元素仅使用一个指针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=bb 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 listSinglePNode* 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);}