异或形式的双向链表

来源:互联网 发布:常用的特征提取算法 编辑:程序博客网 时间:2024/06/06 03:52

算法导论的一个习题,使用一个存储空间来表示双向链表的prev next两个指针,存储这两个指针的异或。原理是“异或运算符合交换律、结合律”


这种方式最大好处是节省存储空间,而且可以在O(1) 的时间内反序链表。链表头结点需要保存第一个结点的指针,如此才可能遍历链表


struct xor_node {    void *np;    union {        int key;        struct xor_node *head_next; /* next node of the head */    };};
链表结点结构,即可以表示链表中间结点,又可以表示链表头结点。如果需要反序链表时,直接将头结点的head_next 域指向最后一个结点即可


struct xor_node* xor_list_search(struct xor_node *head, int key, struct xor_node **prev_pp){    struct xor_node *next = NULL, *p = NULL, *prev = NULL;    for (p = head->head_next;p != NULL;p = next) {        if (p->key == key) {            *prev_pp = prev;            break;        }        next = (void *)((long)p->np ^ (long)prev);        prev = p;    }    return p;}
链表search 函数,返回key对应的结点指针及基prev 指针

void xor_list_add(struct xor_node *head, struct xor_node *node){    struct xor_node *next = head->head_next;    node->np = next;    head->head_next = node;    if (next) {        next->np = (void *)((long)(next->np) ^ (long)node);        head->np = (void *)((long)head->np ^ (long)next ^ (long)node);    }}
链表结点添加函数,添加到链表头

static void __xor_list_del(struct xor_node *head, struct xor_node *node, struct xor_node *prev){    struct xor_node *next;    next = (struct xor_node *)((long)node->np ^ (long)prev);    if (prev && next) {        prev->np = (void *)((long)prev->np ^ (long)node ^ (long)next);        next->np = (void *)((long)next->np ^ (long)node ^ (long)prev);    }    else if (prev) {        prev->np = (void *)((long)prev->np ^ (long)node);        head->np = (void *)((long)head->np ^ (long)node ^ (long)prev);    }    else if (next) {        next->np = (void *)((long)next->np ^ (long)node);        head->np = (void *)((long)head->np ^ (long)node ^ (long)next);        head->head_next = next;    }    else {        head->np = NULL;        head->head_next = NULL;    }}void xor_list_del(struct xor_node *head, struct xor_node *node){    struct xor_node *p, *prev;    p = xor_list_search(head, node->key, &prev);    if (p == NULL) {        printf("No such node for key(%d) in the list\r\n", node->key);        return;    }    __xor_list_del(head, node, prev);}
链表结点删除函数,由于没有prev指针,因此需要首先获取删除结点的prev 结点,才能进行删除



这类链表虽然可以节省空间,但复杂度相对增大,search 操作的时间也较长,故使用上不方便,但作为思维锻炼还是相当有好处的