• 2015年09月12日


    异或运算特性 a ^ b = c 则 c ^ b = a , c ^ a = b, 双向链表需要两个指针,一个指向前一个结点,一个指向后一个结点, 异或双向链表只用一个指针,该指针等于 前后两两个结点指针的异或的结果,这样节省了空间,但增加了计算。

    一般的双向链表节点中包含两个指针,分别指向前驱和后继。异或指针双向链表的节点只有一个“指针”,这个指针是另外两个指针的“异或”值,并利用以下运算得到其前驱和后继的指针:

    a^(a^b)=b
    (a^b)^b=a

    在C语言中,可以先把指针转换为无符号整型数然后进行异或,另外还应保存指向链表头尾节点的指针。

    按照这种思路,节点中的这一个指针还可以是“加法”值,或者其他指针运算得到的值。如果是加法,可以利用以下运算得到其前驱和后继指针:

    (x+y)-x=y
    (x+y)-y=x

    需要注意的是,这样的“加法”运算或“异或”运算都是针对指针的值本身的,即指针转换为无符号整型后的运算。不能跟指针运算(如两个指针相减)混淆。

    异或指针双向链表的建立、遍历等参考如下实现。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    //main.cpp 
    #include <iostream>
    using namespace std;
    #include "xorp.h"
    int main(int argc, char *argv[])
    {
        XorLinkedList list;
        char value[NUM+1]="abcdef";
        if(!initList(&list, value)){
          cout<<"initList error ";
          exit(-1);
        }
        traverse(&list, 'l');//从左到右的遍历
        traverse(&list, 'r');//从右到左的遍历
        destroy(&list);
        
        system("PAUSE");
        return true;
    }
    //xorp.h
    #define NUM 6
    typedef struct XorNode{
        char data;
        struct XorNode *LRPtr;      
    }XorNode, *XorPointer;
     
    typedef struct{
        XorPointer l, r;//分别指向双向链表的左端和右端
    }XorLinkedList;
     
    //异或运算
    XorPointer XorP(XorPointer p, XorPointer q);
    //建立双向链表
    bool initList(XorLinkedList *pList, char value[NUM]);
    //销毁链表
    void destroy(XorLinkedList *pList);
    //遍历
    void traverse(const XorLinkedList *pList, char direction);
     
    //xorp.cpp
     
    #include <iostream>
    #include "xorp.h"
    using namespace std; 
    //异或运算
    XorPointer XorP(XorPointer p, XorPointer q){
        return (XorPointer)((unsigned)p^(unsigned)q);         
    }  
    //建立异或指针双向链表
    bool initList(XorLinkedList *pList, char value[NUM]){
         if(NUM<1)
           return false;
           
         XorPointer pl, p, pr;
         int i=0;
         
         p=(XorPointer)malloc(sizeof(XorPointer));
         if(!p)
           return false;
         pl=p;
         p->data=value[i++];
         pList->l=p;
         pr=NULL;   
         for(; i<NUM; ++i){
           pr=(XorPointer)malloc(sizeof(XorPointer));
           if(!p)
             return false;
           pr->data=value[i];
           p->LRPtr=XorP(pl, pr);
           pl=p;
           p=pr;
         }
         pList->r=p;
         if(pr!=NULL)
           p->LRPtr=XorP(pl, pr);
         return true;
    //销毁异或指针双向链表
    void destroy(XorLinkedList *pList){
         XorPointer m, n, p;   
         XorPointer head=pList->l;
         XorPointer tail=pList->r;
         
         m=n=head;
         cout<<"free:";
         while(n!=tail){
           p=XorP(m, n->LRPtr);
           cout<<n->data<<" ";
           free(n);//释放n指向的内容,但n的值本身不变
           m=n;
           n=p;
         }
         cout<<n->data<<" ";
         free(n);
         cout<<endl;
    }
    //遍历异或指针双向链表
    void traverse(const XorLinkedList *pList, char direction){
         XorPointer m, n, p;
         XorPointer head=(direction=='l')?pList->l:pList->r;
         XorPointer tail=(direction=='r')?pList->l:pList->r;
         
         cout<<"traverse:";
         m=n=head;
         cout<<m->data;
         while(n!=tail){
           p=XorP(m, n->LRPtr);
           cout<<p->data;
           m=n;
           n=p;
         }
         cout<<endl;
    }
  • 相关阅读:
    adb命令
    linux常用命令(2)
    Cisco路由器配置基本命令
    linux常用命令
    跨站脚本攻击xss
    选择合适的索引列顺序
    索引的选择性
    mysql索引类型(按存储结构划分)
    mysql数据类型优化
    vim基本命令总结
  • 原文地址:https://www.cnblogs.com/marsggbo/p/6622940.html
Copyright © 2020-2023  润新知