| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1826 人关注过本帖
标题:二叉平衡树,大神帮忙找找虫子
只看楼主 加入收藏
xyzdwf
Rank: 2
等 级:论坛游民
威 望:1
帖 子:52
专家分:10
注 册:2017-1-9
结帖率:88.89%
收藏
已结贴  问题点数:20 回复次数:9 
二叉平衡树,大神帮忙找找虫子
最新想弄个动态属性保存的二叉树结构,想网上移植个标准c红黑树实现,结果都没成功。自己实现红黑树都要晕了,情况判断太多了,还费力不讨好。
由于我对插入属性速度要求低就想自己实现个简单的平衡树
思路就是在树节点中维护 左深度ld 和 右深度rd 两个属性来调整树的平衡
当ld和rd的差值大于2就对该节点进行左旋或右旋操作(为什么是大于二呢?就是左右旋转操作的最小深度都达到了2,小2就矛盾了)
因此插入删除操作的时间复杂度就会是O(2lg(n)),查询操作的复杂度为O(lg(n)+2)
自己测了好多数据,也没发现问题,大家帮忙测测,有问题提一下,谢谢了
下面就上代码了
ztl_tree.h
程序代码:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

typedef unsigned char byte;

typedef struct ztl_tree_node ztl_tree_node_t;
typedef ztl_tree_node_t* ztl_tree_node_p;
struct ztl_tree_node{
    unsigned long k;
    size_t v;
    ztl_tree_node_p l;
    ztl_tree_node_p r;
    ztl_tree_node_p p;
    byte ld;
    byte rd;
};

typedef struct ztl_tree ztl_tree_t;
typedef ztl_tree_t* ztl_tree_p;
struct ztl_tree{
    int size;
    ztl_tree_node_p root;
};

ztl_tree_p ztl_tree_init();

void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node);
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_add(ztl_tree_p tree, unsigned long key, size_t value);

ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node);
size_t ztl_tree_remove(ztl_tree_p tree, unsigned long key);

ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, unsigned long key);
size_t ztl_tree_get(ztl_tree_p tree, unsigned long key);

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node);
void ztl_tree_destory(ztl_tree_p tree);

/** fun impl **/

ztl_tree_p ztl_tree_init()
{
    ztl_tree_p tree = calloc(1,sizeof(ztl_tree_t));
    tree->size=0;
    tree->root=0;
    return tree;
}

/**节点深度值维护*/
void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(!node)return;
    if(node->l){
        byte mxd = node->l->ld > node->l->rd ? node->l->ld : node->l->rd;
        node->ld = mxd+1;
    }else{
        node->ld = 0;
    }
    if(node->r){
        byte mxd = node->r->ld > node->r->rd ? node->r->ld : node->r->rd;
        node->rd = mxd+1;
    }else{
        node->rd = 0;
    }
}

/**节点调整*/
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node)
{    //printf("ztl_tree_adjust.......\n");
    if(!node)return;
    ztl_tree_deep(tree, node);
    
    int dif = node->ld - node->rd;
    if(dif > 2){//右旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->l;
            }else{
                node->p->r = node->l;
            }
            node->l->p = node->p;
        }else{
            node->l->p = 0;
            tree->root = node->l;
        }
        ztl_tree_node_p nlr = node->l->r;
        node->l->r = node;
        node->p = node->l;
        node->l = nlr;
        if(nlr) nlr->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }else if(dif < -2){//左旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->r;
            }else{
                node->p->r = node->r;
            }
            node->r->p = node->p;
        }else{
            node->r->p = 0;
            tree->root = node->r;
        }
        ztl_tree_node_p nrl = node->r->l;
        node->r->l = node;
        node->p = node->r;
        node->r = nrl;
        if(nrl)nrl->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }

    ztl_tree_adjust(tree, node->p);
}

void ztl_tree_add(ztl_tree_p tree, unsigned long key, size_t value)
{
    ztl_tree_node_p nnod = calloc(1, sizeof(ztl_tree_node_t));
    nnod->k = key;
    nnod->v = value;
    if(tree->root){    //printf("11111111111.......start \n");
        ztl_tree_node_p node = tree->root;
        while(node){
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node->l = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, nnod);
                    tree->size++;
                    return;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node->r = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, nnod);
                    tree->size++;
                    return;
                }
            }else{
                node->v = value;
                return;
            }
        }
        //printf("11111111111.......end\n");
    }else{    //printf("222222222.......start\n");
        tree->root = nnod;
        tree->size = 1;
    }
    
}

/**后继节点*/
ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node){
    if(!node) return 0;
    ztl_tree_node_p cnod = node->r;
    while(cnod){
        if(cnod->l)cnod = cnod->l;
        else break;
    }
    return cnod;
}

size_t ztl_tree_remove(ztl_tree_p tree, unsigned long key)
{
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(!node) return -1;
    ztl_tree_node_p bnod = ztl_tree_behind_node(tree, node);
    if(bnod){//删除节点有右分支
        ztl_tree_node_p bpnod = bnod->p;
        //父关系维护
        if(node->p){
            if(node == node->p->l){
                node->p->l = bnod;
            }else{
                node->p->r = bnod;
            }
            bnod->p =  node->p;
        }else{
            bnod->p = 0;
            tree->root = bnod;
        }
        //左边关系维护
        bnod->l = node->l;
        if(node->l)node->l->p = bnod;
        //右边关系维护
        if(bnod != node->r){//后继节点不等于右节点
            bnod ->r = node->r;
            node->r->p = bnod;
            bpnod->l = 0;//后继节点父关系(后继结点必是左节点)
            ztl_tree_adjust(tree, bpnod);
        }else{//后继节点等于右节点(不需要维护右边的关系)
            ztl_tree_adjust(tree, node->r);
        }

    }else{//删除节点没有右分支
        if(node->l){//删除节点没有右分支,但有左分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = node->l;
                }else{
                    node->p->r = node->l;
                }
                node->l->p = node->p;
            }else{
                node->l->p = 0;
                tree->root = node->l;
            }
            ztl_tree_adjust(tree, node->l);
        }else{//删除节点没有左右分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = 0;
                }else{
                    node->p->r = 0;
                }
                ztl_tree_adjust(tree, node->p);
            }else{
                tree->root = 0;
            }
        }
    }
    size_t nv = node->v;
    free(node);
    tree->size--;
    return nv;
}

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(node){
        printf("key: %d, value: %d, deep: %d, %d\n", (int)node->k, (int)node->v, node->ld, node->rd);
        ztl_tree_iterate(tree, node->l);
        ztl_tree_iterate(tree, node->r);
    }
}

int get_num = 0;
ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, unsigned long key)
{
    ztl_tree_node_p node = 0;
    if(tree->root){
        node = tree->root;
        while(node){get_num++;
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node = 0;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node = 0;
                }
            }else{
                break;
            }
        }
    }
    return node;
}

size_t ztl_tree_get(ztl_tree_p tree, unsigned long key){
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(node) return node->v;
    return -1;
}

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(node){
        ztl_tree_destory_it(tree, node->l);
        ztl_tree_destory_it(tree, node->r);
        free(node);
    }
}

void ztl_tree_destory(ztl_tree_p tree)
{
    ztl_tree_destory_it(tree, tree->root);
    free(tree);
}



main.c
程序代码:
#include "ztl_tree.h"

int main(int argc, char ** argv)
{
//    int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80, 110,
//        11, 41, 31, 61, 91, 71, 21, 51, 81, 111,
//        12, 42, 32, 62, 92, 72, 22, 52, 82, 112,
//        13, 43, 33, 63, 93, 73, 23, 53, 83, 113,
//        14, 44, 34, 64, 94, 74, 24, 54, 84, 114
//        15, 45, 35, 65, 95, 75, 25, 55, 85, 115,
//        16, 46, 36, 66, 96, 76, 26, 56, 86, 116,
//        17, 47, 37, 67, 97, 77, 27, 57, 87, 117,
//        18, 48, 38, 68, 98, 78, 28, 58, 88, 118,
//        19, 49, 39, 69, 99, 79, 29, 59, 89, 119
//        };
    
    ztl_tree_p tree = ztl_tree_init();
    for(int i=0; i<2; i++){
        //printf("add to tree... %d\n", i);
//        ztl_tree_add(tree, a[i], i);
        ztl_tree_add(tree, i, i+1);
//        ztl_tree_add(tree, rand()%200, i);
    }
    //ztl_tree_add(tree, 17, 999);
    
    printf("tree Size: %d \n", tree->size);
//    ztl_tree_iterate(tree, tree->root);
    int dv = ztl_tree_remove(tree, 1);
    printf("tree Size: %d, deleteVal: %d, treeRoot:%d \n", tree->size, dv, (int)tree->root);
    
    int maxnum = 0;
    for(int i=0; i<3; i++){
        get_num = 0;
        int gv = ztl_tree_get(tree,  i);
        maxnum = get_num>maxnum?get_num:maxnum;
        printf("get Num: %d, value: %d \n", get_num, gv);
    }

    printf("\nmaxnum: %d\n", maxnum);
    
    ztl_tree_destory(tree);
    return 0;
}


搜索更多相关主题的帖子: return tree key 节点 node 
2021-08-26 13:19
xyzdwf
Rank: 2
等 级:论坛游民
威 望:1
帖 子:52
专家分:10
注 册:2017-1-9
收藏
得分:0 
两文件合在一起,可以在论坛中在线运行
程序代码:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

typedef unsigned char byte;

typedef struct ztl_tree_node ztl_tree_node_t;
typedef ztl_tree_node_t* ztl_tree_node_p;
struct ztl_tree_node{
    unsigned long k;
    size_t v;
    ztl_tree_node_p l;
    ztl_tree_node_p r;
    ztl_tree_node_p p;
    byte ld;
    byte rd;
};

typedef struct ztl_tree ztl_tree_t;
typedef ztl_tree_t* ztl_tree_p;
struct ztl_tree{
    int size;
    ztl_tree_node_p root;
};

ztl_tree_p ztl_tree_init();

void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node);
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_add(ztl_tree_p tree, unsigned long key, size_t value);

ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node);
size_t ztl_tree_remove(ztl_tree_p tree, unsigned long key);

ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, unsigned long key);
size_t ztl_tree_get(ztl_tree_p tree, unsigned long key);

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node);
void ztl_tree_destory(ztl_tree_p tree);

/** fun impl **/

ztl_tree_p ztl_tree_init()
{
    ztl_tree_p tree = calloc(1,sizeof(ztl_tree_t));
    tree->size=0;
    tree->root=0;
    return tree;
}

/**节点深度值维护*/
void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(!node)return;
    if(node->l){
        byte mxd = node->l->ld > node->l->rd ? node->l->ld : node->l->rd;
        node->ld = mxd+1;
    }else{
        node->ld = 0;
    }
    if(node->r){
        byte mxd = node->r->ld > node->r->rd ? node->r->ld : node->r->rd;
        node->rd = mxd+1;
    }else{
        node->rd = 0;
    }
}

/**节点调整*/
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node)
{    //printf("ztl_tree_adjust.......\n");
    if(!node)return;
    ztl_tree_deep(tree, node);
    
    int dif = node->ld - node->rd;
    if(dif > 2){//右旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->l;
            }else{
                node->p->r = node->l;
            }
            node->l->p = node->p;
        }else{
            node->l->p = 0;
            tree->root = node->l;
        }
        ztl_tree_node_p nlr = node->l->r;
        node->l->r = node;
        node->p = node->l;
        node->l = nlr;
        if(nlr) nlr->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }else if(dif < -2){//左旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->r;
            }else{
                node->p->r = node->r;
            }
            node->r->p = node->p;
        }else{
            node->r->p = 0;
            tree->root = node->r;
        }
        ztl_tree_node_p nrl = node->r->l;
        node->r->l = node;
        node->p = node->r;
        node->r = nrl;
        if(nrl)nrl->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }

    ztl_tree_adjust(tree, node->p);
}

void ztl_tree_add(ztl_tree_p tree, unsigned long key, size_t value)
{
    ztl_tree_node_p nnod = calloc(1, sizeof(ztl_tree_node_t));
    nnod->k = key;
    nnod->v = value;
    if(tree->root){    //printf("11111111111.......start \n");
        ztl_tree_node_p node = tree->root;
        while(node){
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node->l = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, node);
                    tree->size++;
                    return;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node->r = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, node);
                    tree->size++;
                    return;
                }
            }else{
                node->v = value;
                return;
            }
        }
        //printf("11111111111.......end\n");
    }else{    //printf("222222222.......start\n");
        tree->root = nnod;
        tree->size = 1;
    }
    
}

/**后继节点*/
ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node){
    if(!node) return 0;
    ztl_tree_node_p cnod = node->r;
    while(cnod){
        if(cnod->l)cnod = cnod->l;
        else break;
    }
    return cnod;
}

size_t ztl_tree_remove(ztl_tree_p tree, unsigned long key)
{
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(!node) return -1;
    ztl_tree_node_p bnod = ztl_tree_behind_node(tree, node);
    if(bnod){//删除节点有右分支
        ztl_tree_node_p bpnod = bnod->p;
        //父关系维护
        if(node->p){
            if(node == node->p->l){
                node->p->l = bnod;
            }else{
                node->p->r = bnod;
            }
            bnod->p =  node->p;
        }else{
            bnod->p = 0;
            tree->root = bnod;
        }
        //左边关系维护
        bnod->l = node->l;
        if(node->l)node->l->p = bnod;
        //右边关系维护
        if(bnod != node->r){//后继节点不等于右节点
            bnod ->r = node->r;
            node->r->p = bnod;
            bpnod->l = 0;//后继节点父关系(后继结点必是左节点)
            ztl_tree_adjust(tree, bpnod);
        }else{//后继节点等于右节点(不需要维护右边的关系)
            ztl_tree_adjust(tree, node->r);
        }

    }else{//删除节点没有右分支
        if(node->l){//删除节点没有右分支,但有左分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = node->l;
                }else{
                    node->p->r = node->l;
                }
                node->l->p = node->p;
            }else{
                node->l->p = 0;
                tree->root = node->l;
            }
            ztl_tree_adjust(tree, node->l);
        }else{//删除节点没有左右分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = 0;
                }else{
                    node->p->r = 0;
                }
                ztl_tree_adjust(tree, node->p);
            }else{
                tree->root = 0;
            }
        }
    }
    size_t nv = node->v;
    free(node);
    tree->size--;
    return nv;
}

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(node){
        printf("key: %d, value: %d, deep: %d, %d\n", (int)node->k, (int)node->v, node->ld, node->rd);
        ztl_tree_iterate(tree, node->l);
        ztl_tree_iterate(tree, node->r);
    }
}

int get_num = 0;
ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, unsigned long key)
{
    ztl_tree_node_p node = 0;
    if(tree->root){
        node = tree->root;
        while(node){get_num++;
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node = 0;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node = 0;
                }
            }else{
                break;
            }
        }
    }
    return node;
}

size_t ztl_tree_get(ztl_tree_p tree, unsigned long key){
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(node) return node->v;
    return -1;
}

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(node){
        ztl_tree_destory_it(tree, node->l);
        ztl_tree_destory_it(tree, node->r);
        free(node);
    }
}

void ztl_tree_destory(ztl_tree_p tree)
{
    ztl_tree_destory_it(tree, tree->root);
    free(tree);
}

int main(int argc, char ** argv)
{
//    int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80, 110,
//        11, 41, 31, 61, 91, 71, 21, 51, 81, 111,
//        12, 42, 32, 62, 92, 72, 22, 52, 82, 112,
//        13, 43, 33, 63, 93, 73, 23, 53, 83, 113,
//        14, 44, 34, 64, 94, 74, 24, 54, 84, 114
//        15, 45, 35, 65, 95, 75, 25, 55, 85, 115,
//        16, 46, 36, 66, 96, 76, 26, 56, 86, 116,
//        17, 47, 37, 67, 97, 77, 27, 57, 87, 117,
//        18, 48, 38, 68, 98, 78, 28, 58, 88, 118,
//        19, 49, 39, 69, 99, 79, 29, 59, 89, 119
//        };
    
    ztl_tree_p tree = ztl_tree_init();
    for(int i=0; i<71; i++){
        //printf("add to tree... %d\n", i);
//        ztl_tree_add(tree, a[i], i);
        ztl_tree_add(tree, i, i+1);
//        ztl_tree_add(tree, rand()%200, i);
    }
    //ztl_tree_add(tree, 17, 999);
    
    printf("tree Size: %d \n", tree->size);
//    ztl_tree_iterate(tree, tree->root);
    int dv = ztl_tree_remove(tree, 39);
    printf("tree Size: %d, deleteVal: %d, treeRoot:\n", tree->size, dv);
    
    int maxnum = 0;
    for(int i=0; i<71; i++){
        get_num = 0;
        int gv = ztl_tree_get(tree,  i);
        maxnum = get_num>maxnum?get_num:maxnum;
        printf("get Num: %d, value: %d \n", get_num, gv);
    }

    printf("\nmaxnum: %d\n", maxnum);
    
    ztl_tree_destory(tree);
    return 0;
}




[此贴子已经被作者于2021-8-29 12:03编辑过]

2021-08-26 14:47
xyzdwf
Rank: 2
等 级:论坛游民
威 望:1
帖 子:52
专家分:10
注 册:2017-1-9
收藏
得分:0 
论坛的服务器还是挺给力的,10w个元素插入无压力,再大还是别试了。10w树的深度达到了17-18,符合这个数量级的树深度,暂时还没发现问题
图片附件: 游客没有浏览图片的权限,请 登录注册


[此贴子已经被作者于2021-8-26 15:32编辑过]

2021-08-26 15:28
自由而无用
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:14
帖 子:61
专家分:1456
注 册:2021-8-9
收藏
得分:10 
程序代码:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>

typedef unsigned char byte;

typedef struct ztl_tree_node ztl_tree_node_t;
typedef ztl_tree_node_t* ztl_tree_node_p;
struct ztl_tree_node{
    unsigned long k;
    size_t v;
    ztl_tree_node_p l;
    ztl_tree_node_p r;
    ztl_tree_node_p p;
    byte ld;
    byte rd;
};

typedef struct ztl_tree ztl_tree_t;
typedef ztl_tree_t* ztl_tree_p;
struct ztl_tree{
    int size;
    ztl_tree_node_p root;
};

ztl_tree_p ztl_tree_init();

void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node);
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_add(ztl_tree_p tree, unsigned long key, size_t value);

ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node);
size_t ztl_tree_remove(ztl_tree_p tree, unsigned long key);

ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, unsigned long key);
size_t ztl_tree_get(ztl_tree_p tree, unsigned long key);

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node);
void ztl_tree_destory(ztl_tree_p tree);

/** fun impl **/

ztl_tree_p ztl_tree_init()
{
    ztl_tree_p tree = calloc(1,sizeof(ztl_tree_t));
    tree->size=0;
    tree->root=0;
    return tree;
}

/**节点深度值维护*/
void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(!node)return;
    if(node->l){
        byte mxd = node->l->ld > node->l->rd ? node->l->ld : node->l->rd;
        node->ld = mxd+1;
    }else{
        node->ld = 0;
    }
    if(node->r){
        byte mxd = node->r->ld > node->r->rd ? node->r->ld : node->r->rd;
        node->rd = mxd+1;
    }else{
        node->rd = 0;
    }
}

/**节点调整*/
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node)
{    //printf("ztl_tree_adjust.......\n");
    if(!node)return;
    ztl_tree_deep(tree, node);
    
    int dif = node->ld - node->rd;
    if(dif > 2){//右旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->l;
            }else{
                node->p->r = node->l;
            }
            node->l->p = node->p;
        }else{
            node->l->p = 0;
            tree->root = node->l;
        }
        ztl_tree_node_p nlr = node->l->r;
        node->l->r = node;
        node->p = node->l;
        node->l = nlr;
        if(nlr) nlr->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }else if(dif < -2){//左旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->r;
            }else{
                node->p->r = node->r;
            }
            node->r->p = node->p;
        }else{
            node->r->p = 0;
            tree->root = node->r;
        }
        ztl_tree_node_p nrl = node->r->l;
        node->r->l = node;
        node->p = node->r;
        node->r = nrl;
        if(nrl)nrl->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }

    ztl_tree_adjust(tree, node->p);
}

void ztl_tree_add(ztl_tree_p tree, unsigned long key, size_t value)
{
    ztl_tree_node_p nnod = calloc(1, sizeof(ztl_tree_node_t));
    nnod->k = key;
    nnod->v = value;
    if(tree->root){    //printf("11111111111.......start \n");
        ztl_tree_node_p node = tree->root;
        while(node){
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node->l = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, nnod);
                    tree->size++;
                    return;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node->r = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, nnod);
                    tree->size++;
                    return;
                }
            }else{
                node->v = value;
                return;
            }
        }
        //printf("11111111111.......end\n");
    }else{    //printf("222222222.......start\n");
        tree->root = nnod;
        tree->size = 1;
    }
    
}

/**后继节点*/
ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node){
    if(!node) return 0;
    ztl_tree_node_p cnod = node->r;
    while(cnod){
        if(cnod->l)cnod = cnod->l;
        else break;
    }
    return cnod;
}

size_t ztl_tree_remove(ztl_tree_p tree, unsigned long key)
{
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(!node) return -1;
    ztl_tree_node_p bnod = ztl_tree_behind_node(tree, node);
    if(bnod){//删除节点有右分支
        ztl_tree_node_p bpnod = bnod->p;
        //父关系维护
        if(node->p){
            if(node == node->p->l){
                node->p->l = bnod;
            }else{
                node->p->r = bnod;
            }
            bnod->p =  node->p;
        }else{
            bnod->p = 0;
            tree->root = bnod;
        }
        //左边关系维护
        bnod->l = node->l;
        if(node->l)node->l->p = bnod;
        //右边关系维护
        if(bnod != node->r){//后继节点不等于右节点
            bnod ->r = node->r;
            node->r->p = bnod;
            bpnod->l = 0;//后继节点父关系(后继结点必是左节点)
            ztl_tree_adjust(tree, bpnod);
        }else{//后继节点等于右节点(不需要维护右边的关系)
            ztl_tree_adjust(tree, node->r);
        }

    }else{//删除节点没有右分支
        if(node->l){//删除节点没有右分支,但有左分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = node->l;
                }else{
                    node->p->r = node->l;
                }
                node->l->p = node->p;
            }else{
                node->l->p = 0;
                tree->root = node->l;
            }
            ztl_tree_adjust(tree, node->l);
        }else{//删除节点没有左右分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = 0;
                }else{
                    node->p->r = 0;
                }
                ztl_tree_adjust(tree, node->p);
            }else{
                tree->root = 0;
            }
        }
    }
    size_t nv = node->v;
    free(node);
    tree->size--;
    return nv;
}

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(node){
        printf("key: %d, value: %d, deep: %d, %d\n", (int)node->k, (int)node->v, node->ld, node->rd);
        ztl_tree_iterate(tree, node->l);
        ztl_tree_iterate(tree, node->r);
    }
}

int get_num = 0;
ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, unsigned long key)
{
    ztl_tree_node_p node = 0;
    if(tree->root){
        node = tree->root;
        while(node){get_num++;
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node = 0;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node = 0;
                }
            }else{
                break;
            }
        }
    }
    return node;
}

size_t ztl_tree_get(ztl_tree_p tree, unsigned long key){
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(node) return node->v;
    return -1;
}

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(node){
        ztl_tree_destory_it(tree, node->l);
        ztl_tree_destory_it(tree, node->r);
        free(node);
    }
}

void ztl_tree_destory(ztl_tree_p tree)
{
    ztl_tree_destory_it(tree, tree->root);
    free(tree);
}
//<<patch to line 297
void find_symbol(void)
{
    system("grep ELF *dmp");
    system("grep linux *dmp");
    system("grep libc *dmp");
    system("grep system *dmp");
    system("grep BUGS *dmp");
}

void v_dmp_bin(void)
{
    system("gcc *.c -o v.out");
    system("/usr/bin/xxd v.out > v.dmp");
    //system("cat v.dmp");
    find_symbol();

    exit(0);
}
//<<patch end of line 316

int main(int argc, char ** argv)
{
//    int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80, 110,
//        11, 41, 31, 61, 91, 71, 21, 51, 81, 111,
//        12, 42, 32, 62, 92, 72, 22, 52, 82, 112,
//        13, 43, 33, 63, 93, 73, 23, 53, 83, 113,
//        14, 44, 34, 64, 94, 74, 24, 54, 84, 114
//        15, 45, 35, 65, 95, 75, 25, 55, 85, 115,
//        16, 46, 36, 66, 96, 76, 26, 56, 86, 116,
//        17, 47, 37, 67, 97, 77, 27, 57, 87, 117,
//        18, 48, 38, 68, 98, 78, 28, 58, 88, 118,
//        19, 49, 39, 69, 99, 79, 29, 59, 89, 119
//        };
    //<<patch line 331
    v_dmp_bin();
    
    ztl_tree_p tree = ztl_tree_init();
    for(int i=0; i<71; i++){
        //printf("add to tree... %d\n", i);
//        ztl_tree_add(tree, a[i], i);
        ztl_tree_add(tree, i, i+1);
//        ztl_tree_add(tree, rand()%200, i);
    }
    //ztl_tree_add(tree, 17, 999);
    
    printf("tree Size: %d \n", tree->size);
//    ztl_tree_iterate(tree, tree->root);
    int dv = ztl_tree_remove(tree, 39);
    printf("tree Size: %d, deleteVal: %d, treeRoot:\n", tree->size, dv);
    
    int maxnum = 0;
    for(int i=0; i<71; i++){
        get_num = 0;
        int gv = ztl_tree_get(tree,  i);
        maxnum = get_num>maxnum?get_num:maxnum;
        printf("get Num: %d, value: %d \n", get_num, gv);
    }

    printf("\nmaxnum: %d\n", maxnum);
    
    ztl_tree_destory(tree);
    return 0;
}
2021-08-26 19:39
我善治鬼
Rank: 5Rank: 5
等 级:贵宾
威 望:17
帖 子:107
专家分:181
注 册:2015-2-16
收藏
得分:10 
必应小冰帮你回答
图片附件: 游客没有浏览图片的权限,请 登录注册

图片附件: 游客没有浏览图片的权限,请 登录注册



[此贴子已经被作者于2021-8-26 22:20编辑过]

2021-08-26 22:17
xyzdwf
Rank: 2
等 级:论坛游民
威 望:1
帖 子:52
专家分:10
注 册:2017-1-9
收藏
得分:0 
回复 4楼 自由而无用
windowns 下运行不了
2021-08-27 12:37
xyzdwf
Rank: 2
等 级:论坛游民
威 望:1
帖 子:52
专家分:10
注 册:2017-1-9
收藏
得分:0 
回复 5楼 我善治鬼
2021-08-27 12:37
xyzdwf
Rank: 2
等 级:论坛游民
威 望:1
帖 子:52
专家分:10
注 册:2017-1-9
收藏
得分:0 
以平衡二叉树为基础,加上一个fnv1a哈希函数做成一个map
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>

typedef unsigned char byte;

typedef struct ztl_tree_node ztl_tree_node_t;
typedef ztl_tree_node_t* ztl_tree_node_p;
struct ztl_tree_node{
    uint64_t k;
    size_t v;
    ztl_tree_node_p l;
    ztl_tree_node_p r;
    ztl_tree_node_p p;
    byte ld;
    byte rd;
};

typedef struct ztl_tree ztl_tree_t;
typedef ztl_tree_t* ztl_tree_p;
struct ztl_tree{
    int size;
    ztl_tree_node_p root;
};

ztl_tree_p ztl_tree_init();

void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node);
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_add(ztl_tree_p tree, uint64_t key, size_t value);

ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node);
size_t ztl_tree_remove(ztl_tree_p tree, uint64_t key);

ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, uint64_t key);
size_t ztl_tree_get(ztl_tree_p tree, uint64_t key);

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node);

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node, void (*cb)(ztl_tree_node_p node));
void ztl_tree_destory(ztl_tree_p tree);

/** fun impl **/

ztl_tree_p ztl_tree_init()
{
    ztl_tree_p tree = calloc(1,sizeof(ztl_tree_t));
    tree->size=0;
    tree->root=0;
    return tree;
}

/**节点深度值维护*/
void ztl_tree_deep(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(!node)return;
    if(node->l){
        byte mxd = node->l->ld > node->l->rd ? node->l->ld : node->l->rd;
        node->ld = mxd+1;
    }else{
        node->ld = 0;
    }
    if(node->r){
        byte mxd = node->r->ld > node->r->rd ? node->r->ld : node->r->rd;
        node->rd = mxd+1;
    }else{
        node->rd = 0;
    }
}

/**节点调整*/
void ztl_tree_adjust(ztl_tree_p tree, ztl_tree_node_p node)
{    //printf("ztl_tree_adjust.......\n");
    if(!node)return;
    ztl_tree_deep(tree, node);
    
    int dif = node->ld - node->rd;
    if(dif > 2){//右旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->l;
            }else{
                node->p->r = node->l;
            }
            node->l->p = node->p;
        }else{
            node->l->p = 0;
            tree->root = node->l;
        }
        ztl_tree_node_p nlr = node->l->r;
        node->l->r = node;
        node->p = node->l;
        node->l = nlr;
        if(nlr) nlr->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }else if(dif < -2){//左旋
        if(node->p){
            if(node == node->p->l){
                node->p->l = node->r;
            }else{
                node->p->r = node->r;
            }
            node->r->p = node->p;
        }else{
            node->r->p = 0;
            tree->root = node->r;
        }
        ztl_tree_node_p nrl = node->r->l;
        node->r->l = node;
        node->p = node->r;
        node->r = nrl;
        if(nrl)nrl->p = node;
        ztl_tree_deep(tree, node);
        ztl_tree_deep(tree, node->p);
        node = node->p;
    }

    ztl_tree_adjust(tree, node->p);
}

void ztl_tree_add(ztl_tree_p tree, uint64_t key, size_t value)
{
    ztl_tree_node_p nnod = calloc(1, sizeof(ztl_tree_node_t));
    nnod->k = key;
    nnod->v = value;
    if(tree->root){
        ztl_tree_node_p node = tree->root;
        while(node){
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node->l = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, node);
                    tree->size++;
                    return;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node->r = nnod;
                    nnod->p = node;
                    ztl_tree_adjust(tree, node);
                    tree->size++;
                    return;
                }
            }else{
                node->v = value;
                return;
            }
        }
        
    }else{
        tree->root = nnod;
        tree->size = 1;
    }
    
}

/**后继节点*/
ztl_tree_node_p ztl_tree_behind_node(ztl_tree_p tree, ztl_tree_node_p node){
    if(!node) return 0;
    ztl_tree_node_p cnod = node->r;
    while(cnod){
        if(cnod->l)cnod = cnod->l;
        else break;
    }
    return cnod;
}

size_t ztl_tree_remove(ztl_tree_p tree, uint64_t key)
{
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(!node) return -1;
    ztl_tree_node_p bnod = ztl_tree_behind_node(tree, node);
    if(bnod){//删除节点有右分支
        ztl_tree_node_p bpnod = bnod->p;
        //父关系维护
        if(node->p){
            if(node == node->p->l){
                node->p->l = bnod;
            }else{
                node->p->r = bnod;
            }
            bnod->p =  node->p;
        }else{
            bnod->p = 0;
            tree->root = bnod;
        }
        //左边关系维护
        bnod->l = node->l;
        if(node->l)node->l->p = bnod;
        //右边关系维护
        if(bnod != node->r){//后继节点不等于右节点
            bnod ->r = node->r;
            node->r->p = bnod;
            bpnod->l = 0;//后继节点父关系(后继结点必是左节点)
            ztl_tree_adjust(tree, bpnod);
        }else{//后继节点等于右节点(不需要维护右边的关系)
            ztl_tree_adjust(tree, node->r);
        }

    }else{//删除节点没有右分支
        if(node->l){//删除节点没有右分支,但有左分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = node->l;
                }else{
                    node->p->r = node->l;
                }
                node->l->p = node->p;
            }else{
                node->l->p = 0;
                tree->root = node->l;
            }
            ztl_tree_adjust(tree, node->l);
        }else{//删除节点没有左右分支
            if(node->p){
                if(node == node->p->l){
                    node->p->l = 0;
                }else{
                    node->p->r = 0;
                }
                ztl_tree_adjust(tree, node->p);
            }else{
                tree->root = 0;
            }
        }
    }
    size_t nv = node->v;
    free(node);
    tree->size--;
    return nv;
}

void ztl_tree_iterate(ztl_tree_p tree, ztl_tree_node_p node)
{
    if(node){
        printf("key: %d, value: %d, deep: %d, %d\n", (int)node->k, (int)node->v, node->ld, node->rd);
        ztl_tree_iterate(tree, node->l);
        ztl_tree_iterate(tree, node->r);
    }
}

int get_num = 0;
ztl_tree_node_p ztl_tree_get_node(ztl_tree_p tree, uint64_t key)
{
    ztl_tree_node_p node = 0;
    if(tree->root){
        node = tree->root;
        get_num = 0;
        while(node){get_num++;
            if(key < node->k){
                if(node->l){
                    node = node->l;
                }else{
                    node = 0;
                }
            }else if(key > node->k){
                if(node->r){
                    node = node->r;
                }else{
                    node = 0;
                }
            }else{
                break;
            }
        }
    }
    printf("ztl_tree get num: %d\n", get_num);
    return node;
}

size_t ztl_tree_get(ztl_tree_p tree, uint64_t key){
    ztl_tree_node_p node =  ztl_tree_get_node(tree, key);
    if(node) return node->v;
    return -1;
}

void ztl_tree_destory_it(ztl_tree_p tree, ztl_tree_node_p node, void (*cb)(ztl_tree_node_p node))
{
    if(node){
        ztl_tree_destory_it(tree, node->l, cb);
        ztl_tree_destory_it(tree, node->r, cb);
        if(cb) (*cb)(node);
        free(node);
    }
}

void ztl_tree_destory(ztl_tree_p tree)
{
    ztl_tree_destory_it(tree, tree->root, 0);
    free(tree);
}

/************  map ************/ 

typedef struct ztl_map_kv ztl_map_kv_t;
typedef ztl_map_kv_t* ztl_map_kv_p;
struct ztl_map_kv{
    char* key;
    size_t value;
};

typedef struct ztl_map ztl_map_t;
typedef ztl_map_t* ztl_map_p;
struct ztl_map{
    int size;
    ztl_tree_p tree;
};

ztl_map_p ztl_map_init();
void ztl_map_put(ztl_map_p map, char* key, size_t value);
size_t ztl_map_get(ztl_map_p map,char* key);
size_t ztl_map_remove(ztl_map_p map, char* key);
static void ztl_map_destory_cb(ztl_tree_node_p node);
void ztl_map_destory(ztl_map_p map);

uint64_t fnv1a(char* buf, size_t len);

ztl_map_p ztl_map_init()
{
    ztl_map_p map = calloc(1, sizeof(ztl_map_t));
    map->size = 0;
    map->tree = ztl_tree_init();
    return map;
}

void ztl_map_put(ztl_map_p map, char* key, size_t value)
{
    ztl_map_kv_p kv = calloc(1, sizeof(ztl_map_kv_t));
    kv->key = key;
    kv->value = value;
    ztl_tree_add(map->tree, fnv1a(key, strlen(key)), (size_t)kv);
    map->size = map->tree->size;
}

size_t ztl_map_get(ztl_map_p map,char* key)
{
    size_t v = ztl_tree_get(map->tree,  fnv1a(key, strlen(key)));
    if((int)v < 0) return -1;
    ztl_map_kv_p kv = (ztl_map_kv_p)v;
    return kv->value;
}

size_t ztl_map_remove(ztl_map_p map, char* key)
{
    size_t v = ztl_tree_remove(map->tree,  fnv1a(key, strlen(key)));
    if((int)v<0) return -1;
    ztl_map_kv_p kv = (ztl_map_kv_p)v;
    map->size = map->tree->size;
    size_t rv = kv->value;
    free(kv);
    return rv;
}

void ztl_map_destory_cb(ztl_tree_node_p node){
    if(node && node->v) free((ztl_map_kv_p)node->v);
}

void ztl_map_destory(ztl_map_p map)
{
    ztl_tree_destory_it(map->tree, map->tree->root, ztl_map_destory_cb);
    free(map->tree);
    free(map);
}

uint64_t fnv1a(char* buf, size_t len) 
{  
    uint64_t hv = 0xcbf29ce484222325ULL;
    char* bp = buf;  
    char* be = bp + len;  
    while (bp < be) {  
        hv ^= (uint64_t) *bp++;  
        hv += (hv << 1) + (hv << 4) + (hv << 5) +  
            (hv << 7) + (hv << 8) + (hv << 40);  
    }  
    return hv;  
}

/************ test ************/

void test_tree();
void test_map();

int main(int argc, char ** argv)
{
//     test_tree();
    test_map();
    return 0;
}

void test_tree()
{
    //    int a[] = {10, 40, 30, 60, 90, 70, 20, 50, 80, 110,
//        11, 41, 31, 61, 91, 71, 21, 51, 81, 111,
//        12, 42, 32, 62, 92, 72, 22, 52, 82, 112,
//        13, 43, 33, 63, 93, 73, 23, 53, 83, 113,
//        14, 44, 34, 64, 94, 74, 24, 54, 84, 114
//        15, 45, 35, 65, 95, 75, 25, 55, 85, 115,
//        16, 46, 36, 66, 96, 76, 26, 56, 86, 116,
//        17, 47, 37, 67, 97, 77, 27, 57, 87, 117,
//        18, 48, 38, 68, 98, 78, 28, 58, 88, 118,
//        19, 49, 39, 69, 99, 79, 29, 59, 89, 119
//        };
    
    ztl_tree_p tree = ztl_tree_init();
    for(int i=0; i<11077; i++){
        //printf("add to tree... %d\n", i);
//        ztl_tree_add(tree, a[i], i);
        ztl_tree_add(tree, i, i+1);
//        ztl_tree_add(tree, rand()%200, i);
    }
    //ztl_tree_add(tree, 17, 999);
    
    printf("tree Size: %d \n", tree->size);
//    ztl_tree_iterate(tree, tree->root);
    int dv = ztl_tree_remove(tree, 10031);
    printf("tree Size: %d, deleteVal: %d, rootVal:%d \n\n", tree->size, dv, (int)tree->root->v);
    
    int maxnum = 0;
    for(int i=9999; i<10050; i++){
        get_num = 0;
        int gv = ztl_tree_get(tree,  i);
        maxnum = get_num>maxnum?get_num:maxnum;
        printf("index: %d, value: %d \n", i, gv);
    }

    printf("\nmaxnum: %d\n\n", maxnum);
    
    ztl_tree_destory(tree);
}

void test_map()
{
    ztl_map_p map = ztl_map_init();
    ztl_map_put(map, "风轻云淡",  111111);
    ztl_map_put(map, "惠风和畅",  222222222);
    ztl_map_put(map, "天高仍鸟飞",  333333333);
    
    ztl_map_put(map, "风轻云淡", 7777777);

    ztl_map_put(map, "abc", 1234);
    ztl_map_put(map, "aac", 2345);
    ztl_map_put(map, "acc", 3456);
    ztl_map_put(map, "acca", 4567);
    
    for(int i=0; i<87; i++){
        char* str = calloc(10,sizeof(char));//动态内存生成字符串,否则所有的key都为最后一个
        sprintf( str, "mapkey%d", i);
        ztl_map_put(map, str, i+1);
    }
    
    printf("pl: %d, pr: %d, pb: %d\n\n",  
        (int)ztl_map_get(map, "风轻云淡"),  
        (int)ztl_map_get(map, "惠风和畅"), 
        (int)ztl_map_get(map, "天高仍鸟飞")
    );
    
    printf(" %d, %d, %d, %d\n\n",  
        (int)ztl_map_get(map, "abc"),  
        (int)ztl_map_get(map, "aac"), 
        (int)ztl_map_get(map, "acc"),
        (int)ztl_map_get(map, "acca")
    );
    
    printf(" %d, %d, %d, %d\n\n",  
        (int)ztl_map_get(map, "mapkey3"),  
        (int)ztl_map_get(map, "mapkey34"), 
        (int)ztl_map_get(map, "mapkey51"),
        (int)ztl_map_get(map, "mapkey67")
    );
    
    printf("map size: %d",map->size);
    
    ztl_map_destory(map);
}



[此贴子已经被作者于2021-8-30 17:35编辑过]

2021-08-28 21:53
xyzdwf
Rank: 2
等 级:论坛游民
威 望:1
帖 子:52
专家分:10
注 册:2017-1-9
收藏
得分:0 
发现一个可以优化的地方,少调整一次,插入速度快了那么一丁点
图片附件: 游客没有浏览图片的权限,请 登录注册
2021-08-29 12:01
username1111
Rank: 1
等 级:新手上路
帖 子:5
专家分:0
注 册:2021-8-20
收藏
得分:0 
回复 2楼 xyzdwf
2021-09-06 08:31
快速回复:二叉平衡树,大神帮忙找找虫子
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.061408 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved