zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    Linkerd 2.10(Step by Step)—将 GitOps 与 Linkerd 和 Argo CD 结合使用
    Linkerd 2.10(Step by Step)—多集群通信
    Linkerd 2.10(Step by Step)—使用 Kustomize 自定义 Linkerd 的配置
    Linkerd 2.10(Step by Step)—控制平面调试端点
    Linkerd 2.10(Step by Step)—配置超时
    Linkerd 2.10(Step by Step)—配置重试
    Linkerd 2.10(Step by Step)—配置代理并发
    本地正常运行,线上环境诡异异常原因集合
    Need to invoke method 'xxx' declared on target class 'yyy', but not found in any interface(s) of the exposed proxy type
    alpine 安装常用命令
  • 原文地址:https://www.cnblogs.com/marsggbo/p/6622940.html
Copyright © 2011-2022 走看看