题目:
说明如何在每个元素仅使用一个指针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,
关于该题的一些数据结构的声明如下:
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);
}