算法

来源:互联网 发布:淘宝盖楼怎么才能中 编辑:程序博客网 时间:2024/05/21 19:11

1、 1!+2!+...

两层循环

long long JC(int n){if(n <= 1) return 1;return n*JC(n-1);}int _tmain(int argc, _TCHAR* argv[]){long long s=0;for(int n=1;n<=10;n++){s+=JC(n);}printf("1+2!+3!...+10!=%lld\n",s);}

利用一层循环

int _tmain(int argc, _TCHAR* argv[]){long long s=0,t=1;for(int n=1;n<=10;n++){t*=n;s+=t;}printf("1+2!+3!...+10!=%lld\n",s);}

2、求二进制中1的个数

unsigned int BitCount(unsigned int n){unsigned int c =0 ;for (c =0; n; ++c){n &= (n -1) ; //清除最低位的1}return c ;}

3、单指针的双向链表

3.1、基础
数学基础: x ^ y ^ y = x ^ ( y ^ y ) = x ^ 0 = x
双指针双向链表结点:
struct Node {  
    struct Node *next;  
    struct Node *prev;   
} head;  
单指针使用的双向链表:   
struct Node {  
    void *np;  
} head;  
两链表之间的关系:
head->np = head->next ^ head->prev
3.2、 搜索
我们通常所用的双指针双向链表head的prev为null,因此有
head->np = head->prev ^ head->next = head->next;  
这样,我们根据链表的头部就可以获得head->next,即链表的第二个结点地址,这样:
node->next = node->np ^ node->prev; // node->np = node->next ^ node->prev  
此处可将node指为head->next,即为head->np,则有:
node->prev = head, node->np = head->np->np,从而获知第三个结点地址。
以此类推,只要在整个搜索过程中跟踪两个连续结点地址,就可以获得第三个结点地址,具体实现:
[cpp] view plaincopy
node = head->np;  
p_node = head; // 假设前两个结点都不是所搜结点  
while ( p_next = node->np ^ p_node ) {  
    if ( p_next->value == x )  
        return p_next;  
    else {  
        p_node = node;  
        node = p_next;  
    }  
}  
return NULL;  
3.3、 插入
在head之后插入node的代码如下(主要用于建表)
nodep = &node;  
nodep->np = head->np ^ head;  
head->np->np = head->np->np ^ head ^ nodep;  
// head->next->np = head->next->np ^ head ^ nodep  
// = head->next->next ^ nodep  
head->np = nodep;  
如果想在任意一个结点之后插入结点,必须先得定位此结点与它之前(或之后)的结点地址(通常使用搜索与备忘)。
3.4、删除
类似于插入,必须先得定位此结点以及它之前或之后的结点,然后:
// nodep = node->prev  
node_n = node->np ^ nodep;  
nodep->np = (nodep->np ^ node) ^ node_n;  
node_n->np = node_n->np ^ node ^ node_p;  
free(node);  
注意: 如果为循环链表的话,如果只知道一个结点信息的话,是不能遍历整个链表的,同时,如果此循环链表只有一个结点时会出现node->prev = node->next的情况,此时node-> = NULL,丢失信息。 而如果不是循环链表的话,由于内存地址的唯一性,这种问题是不会发生的

0 0