| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7273 人关注过本帖, 5 人收藏
标题:三叉树演示
取消只看楼主 加入收藏
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
结帖率:100%
收藏(5)
 问题点数:0 回复次数:19 
三叉树演示
唉,yuma的百分贴是等不到了,估计他也没打算为这个东西出100分。

代码写好两天了。作为一个简单的算法示例,对我来说它没有保存价值。对于连指针都折腾不明白的新手而言,它又过于复杂,很难说能从中学到什么。

算了,既然都写好了,扔了有点浪费。发上来吧。有一个能看懂就算我没白发。

也不打算用分数来吸引人。希望参与这贴的朋友为的是学点知识,而不是蹭点分。

感谢随风的指正,目前已经修改两处错误。
程序代码:
#include<stdio.h>
#include<malloc.h>

typedef struct ternary_tree_node
{
    char key;
    int value;
    struct ternary_tree_node * left;
    struct ternary_tree_node * mid;
    struct ternary_tree_node * right;
}TERNARY_NODE, * TERNARY_TREE;

void ternary_tree_clear(TERNARY_TREE * tree);
void ternary_tree_insert(TERNARY_TREE * tree, char * string, int value);
void ternary_tree_delete(TERNARY_TREE * tree, char * string);
void ternary_tree_travel(TERNARY_TREE tree);
int ternary_tree_search(TERNARY_TREE tree, char * string);
int ternary_tree_node_count(TERNARY_TREE tree);


int main()
{
    TERNARY_TREE tt = NULL;
    ternary_tree_insert(&tt, "abc", 1);
    ternary_tree_insert(&tt, "abeh", 2);
    ternary_tree_insert(&tt, "abdi", 3);
    ternary_tree_insert(&tt, "abfj", 4);
    ternary_tree_travel(tt);
    printf("nodes count = %d\n\n", ternary_tree_node_count(tt));
    ternary_tree_delete(&tt, "abeh");
    ternary_tree_travel(tt);
    printf("nodes count = %d\n\n", ternary_tree_node_count(tt));
    ternary_tree_clear(&tt);
    return 0;
}


void ternary_tree_clear(TERNARY_TREE * tree)
{
    if(*tree == NULL) return;
    ternary_tree_clear(&((*tree)->left));
    ternary_tree_clear(&((*tree)->mid));
    ternary_tree_clear(&((*tree)->right));
    free(*tree);
    *tree = NULL;
}

void ternary_tree_insert(TERNARY_TREE * tree, char * string, int value)
{
    TERNARY_NODE * tmp;
   
    if(*tree == NULL)
    {
        tmp = (TERNARY_NODE *)malloc(sizeof(TERNARY_NODE));
        tmp->key = *string;
        tmp->value = 0;
        tmp->left = NULL;
        tmp->mid = NULL;
        tmp->right = NULL;
        *tree = tmp;
        if(string[1] == '\0')
        {
            tmp->value = value;
            return;
        }
        ternary_tree_insert(&(tmp->mid), string + 1, value);
    }
    else if((*tree)->key > *string)
    {
        ternary_tree_insert(&((*tree)->left), string, value);
    }
    else if((*tree)->key == *string)
    {
        if(string[1] == '\0')
        {
            (*tree)->value = value;
            return;
        }
        ternary_tree_insert(&((*tree)->mid), string + 1, value);
    }
    else
    {
        ternary_tree_insert(&((*tree)->right), string, value);
    }
}

void ternary_tree_delete(TERNARY_TREE * tree, char * string)
{
    TERNARY_NODE * pl, * pr, * pt;
   
    if(*tree == NULL) return;
    if(*string == '\0') return;
   
    if((*tree)->key > *string) ternary_tree_delete(&((*tree)->left), string);
    else if((*tree)->key < *string) ternary_tree_delete(&((*tree)->right), string);
    else if(string[1] == '\0') (*tree)->value = 0;
    else ternary_tree_delete(&((*tree)->mid), string + 1);
   
    if((*tree)->mid != NULL || (*tree)->value != 0) return;
   
    pl = (*tree)->left;
    pr = (*tree)->right;
    if(pl == NULL) pl = pr;
    else if(pr != NULL)
    {
        for(pt = pl; pt->right != NULL; pt = pt->right);
        pt ->right = pr;
    }
   
    free(*tree);
    *tree = pl;
}

void ternary_tree_travel_sub(TERNARY_TREE tree, char * string, int deep)
{
    if(tree == NULL) return;
    ternary_tree_travel_sub(tree->left, string, deep);
    string[deep] = tree->key;
    if(tree->value != 0)
    {
        string[deep + 1] = '\0';
        printf("%s <%d>\n", string, tree->value);
    }
    ternary_tree_travel_sub(tree->mid, string, deep + 1);
    ternary_tree_travel_sub(tree->right, string, deep);
}

void ternary_tree_travel(TERNARY_TREE tree)
{
    char tmp[1024];
    ternary_tree_travel_sub(tree, tmp, 0);
}

int ternary_tree_search(TERNARY_TREE tree, char * string)
{
    if(tree == NULL) return 0;
    if(*string == '\0') return 0;
    if(tree->key > *string) return ternary_tree_search(tree->left, string);
    if(tree->key < *string) return ternary_tree_search(tree->right, string);
    if(string[1] == '\0') return tree->value;
    return ternary_tree_search(tree->mid, string + 1);
}

int ternary_tree_node_count(TERNARY_TREE tree)
{
    int count;
    if(tree == NULL) return 0;
    count = ternary_tree_node_count(tree->left);
    count += ternary_tree_node_count(tree->mid);
    count += ternary_tree_node_count(tree->right);
    return count + 1;
}


[ 本帖最后由 beyondyf 于 2012-8-7 21:59 编辑 ]
搜索更多相关主题的帖子: color 价值 知识 
2012-08-04 08:25
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 4楼 silent_world
这位兄弟怎么称呼?我们在邮件里交流过几次。你好像是搞信号分析的是吧?

呵呵,问题挺多的,介意我点评你的代码吗?语言可能会有点直接。我们也可以私下交流。

刚发现一个问题,我的代码里少了一项操作功能。忘了写单个键的删除功能了。等我分析完silent_world的代码再补上。

当然,如果哪位朋友能帮我补上我将非常高兴!

重剑无锋,大巧不工
2012-08-04 17:37
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 9楼 随风飘荡
嗯,确实是打错了,应该是ternary_tree_insert(&((*tree)->mid), string + 1, value);我很诧异调试过程中这个问题居然没有在第二组测试数据插入时引发异常。感谢指正!

我对三叉树并没有过多的研究,对它也没什么好感。因为它的结点尺寸更大。虽然相同深度下的完全树的容积较二叉树更大些(这意味可以缩短检索时间),但树的平衡调整更复杂。二叉树完全可以实现三叉树的所有功能,而效率的差别(理论上)就是log2(n) 与log3(n)的差别。

呵呵,这里有点个人感情在内了。主要是因为我还没遇到三叉树能体现出明显优势的需求案例吧。

重剑无锋,大巧不工
2012-08-04 18:32
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 12楼 silent_world
呵呵,那就请多见谅了。

注释风格不统一,有点乱。

从你的代码行为看,你的三叉树是带头结点的。一般这个头结点是不动态申请的,因为没有这个必要,不管树是否为空,它总是存在的。而且动态申请会带来很多隐患,比如内存泄漏。在你的代码中,就忘了释放头结点的内存(事实上你忘了释放所有的内存)。

所以,trstrie_creat几乎没有必要。如果希望封装一下头结点的初始化过程,倒也可以留着,但只需要把mid域置NULL即可。


操作函数的头结点指针参数为什么定义为void * 型?故意躲开编译器对参数类型的检查么?在函数里又做了一次强制转换,这又何必呢?你的函数本就是个专用函数,只用来操作你定义的TERNARY_TRIE *类指针,通用指针在这里的使用只有害处没有益处。

tstrie_destroy函数的结构很怪异,感觉思路有些混乱,虽然运行上应该没什么问题,但有些判断是冗余的。

我正在改你的addData函数(存在严重的逻辑错误),可现在只改了一半就发现已经完全看不出你原来代码的样子了。呵呵,再改那就成我的代码了。我想还是你自己改一下吧。第一个循环就有问题。如果树中已有了“ABC”,再插入“AB”这个串时你的程序事实上是直接退出,并没有完成“AB”串指针加载到cur_property域的动作。

下面的函数还没看,但恐怕类似的问题还有。

这是我对你tstrie_destroy函数的修改,呵呵还能看出是你的代码么?

程序代码:
void tstrie_destroy(TERNARY_TRIE * root)
{
    TERNARY_TRIE * curNode, * delNode;
    curNode = root->child_trie[TERNARY_MIDDLE];
    root->child_trie[TERNARY_MIDDLE] = TSTRIE_NULL;
    if(curNode == TSTRIE_NULL) return;
    while(curNode != root)
    {
        if(curNode->child_trie[TERNARY_LEFT] != TSTRIE_NULL)
        {
            curNode = curNode->child_trie[TERNARY_LEFT];
            curNode->parent->child_trie[TERNARY_LEFT] = TSTRIE_NULL;
        }
        else if(curNode->child_trie[TERNARY_MIDDLE] != TSTRIE_NULL)
        {
            curNode = curNode->child_trie[TERNARY_MIDDLE];
            curNode->parent->child_trie[TERNARY_MIDDLE] = TSTRIE_NULL;
        }
        else if(curNode->child_trie[TERNARY_RIGHT] != TSTRIE_NULL)
        {
            curNode = curNode->child_trie[TERNARY_MIDDLE];
            curNode->parent->child_trie[TERNARY_MIDDLE] = TSTRIE_NULL;
        }
        else
        {
            delNode = curNode;
            curNode = curNode->parent;
            TSTRIE_DELNODE(delNode);
        }
    }
}

重剑无锋,大巧不工
2012-08-05 09:58
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 14楼 embed_xuel
嗯,这点你们做嵌入式开发的感触恐怕更深。内存少运行时间长呵呵。

重剑无锋,大巧不工
2012-08-05 11:26
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 18楼 随风飘荡
还真没明白你说的意思

把你改过的代码部分发上来看看

重剑无锋,大巧不工
2012-08-05 16:25
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
我还以为是你做了什么改动呢。原来又是我的一处bug,感谢指正。一会儿奖励你

我遍历的本意是按字典序输出信息字符串。bug是遍历顺序上的失误,调整成如下就好了。一会儿我会修改第一页中的代码。
由此也能看出软件维护的意义和成本有多大了。

程序代码:
void ternary_tree_travel_sub(TERNARY_TREE tree, char * string, int deep)
{
    if(tree == NULL) return;
    ternary_tree_travel_sub(tree->left, string, deep);
    string[deep] = tree->key;
    if(tree->value != 0)
    {
        string[deep + 1] = '\0';
        printf("%s <%d>\n", string, tree->value);
    }
    ternary_tree_travel_sub(tree->mid, string, deep + 1);
    ternary_tree_travel_sub(tree->right, string, deep);
}



重剑无锋,大巧不工
2012-08-05 17:05
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
你能发现这个错误,现在你已经有这种水平了吧。

肿么了?肿么了?

[ 本帖最后由 beyondyf 于 2012-8-5 17:13 编辑 ]

重剑无锋,大巧不工
2012-08-05 17:12
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 25楼 embed_xuel
呵呵,收徒还真不敢当。不过这里能认真看代码,并能发现其中的问题,并有自己的修改意见的朋友,确实不多。

我很愿意与这样有灵性的朋友交流。以前老杨(laoyang103)也是一点就透,可惜最近不见他了。不知道我这兄弟现在咋样了。

重剑无锋,大巧不工
2012-08-05 17:51
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
随风有没有兴趣帮我实现信息串的删除功能?也真诚邀请其他有兴趣的朋友参与。

先定一下函数原型 void ternary_tree_delete(TERNARY_TREE * tree, char * string);

要求,当string存在于tree时删除之(多余的结点及映射值),如果不存在直接退出,不引发别的操作。

重剑无锋,大巧不工
2012-08-05 21:22
快速回复:三叉树演示
数据加载中...
 
   



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

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