| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 7273 人关注过本帖, 5 人收藏
标题:三叉树演示
取消只看楼主 加入收藏
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
非诚勿扰广告时间

挺喜欢随风的,多大了?

我的代码是放弃版权的,谁都可以随便复制、分发、修改。唯一的要求是不要在不做任何修改的情况声称这段代码属于你。

但请注意silent_world的代码可有版权声明,不要随便复制哦。

有容没有兴趣参与么?

重剑无锋,大巧不工
2012-08-05 21:55
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
后生可畏。多交流代码,有助于你对理论的理解和应用能力的提高。

重剑无锋,大巧不工
2012-08-05 22:59
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 37楼 随风飘荡
不对

说来话长,现在我得去上班,中午回来慢慢解释给你,删除操作远比添加操作复杂。你也可以自己再好好想想。

不要着急,我们可以慢慢讨论这个问题,晚上还是尽量按时睡觉的好。

重剑无锋,大巧不工
2012-08-06 08:07
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 39楼 silent_world
平时探讨的问题多在基础算法的编码技巧点这像的微观层面,很高兴能在工程项目这样的宏观角度和你交流。

我不是职业搞软件的,做过的项目排除IDE自动生成的部分一般也就几千行代码的规模。不过我对软件工程的兴趣并不亚于对算法的兴趣。

而且我做OO开发的时间远多于做PO的时间,所以对于代码架构也有一点个人的见解。

关于头指针。可能是我们的理解不同,因为我的代码用的也是头指针。对树的操作也是通过头指针完成的。

咱俩算法的一个重要的不同在于我的树不带头结点,而你的树是带头结点的。

这里需要强调的一点,头结点并不是树根,而是一个指向树根的引导结点。头结点的作用本就是替代头指针。

树带不带头结点的操作方式是不同的,很难说哪种好哪种坏,需要具体问题具体分析。

因为我的树是不带头结点的,我的头指针直接指向树根结点,操作中需要用二级指针来处理头指针的指向问题。

而你的树是有头结点的,至于这个结点该置于栈内还是置于堆内,我想我们的出发点不同。我想,你考虑的是树的生命周期独立于其创建线程(函数)的生命周期的情况。
只是其作用在你的代码里没有体现出来,却引发了麻烦。

再谈谈代码封装和复用的问题。我也很注重代码的内聚性和耦合性以及通用性。

如果你TERNARY_TRIE结构的cur_property域设计成void *型指针我会很赞同。这可以扩大你的三叉树的使用范围。这是一种复用设计。

但是你的destroy、add、del等函数,它们不是通用函数,是专用函数。你的这些函数只能操作TERNARY_TRIE树对不对?

如果误传入其它类型的指针将导致不可预知的问题。所以这里用void * 指针毫无意义,反而埋下了祸根。这不是可以复用的部分。

三叉搜索树的作用等同于字典键值对,可以实现对键的压缩存储(键头的相同部分可以共用)。值是可以复用的部分,可以是文件地址,可以是IP值等等各种特征值。而树的结构和操作不是可以复用的部分。


很遗憾你现在工作忙。等闲下来有时间了再完成你的代码吧。到时候我们可以更进一步地讨论一些更细节的问题。

重剑无锋,大巧不工
2012-08-06 13:55
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 41楼 zanzan1986
首先没有“任意多叉树”这个名词,普通树就是“任意多叉”的。

子节点指针可以用一个链表来实现。但这种应用不多。

更普遍的应用是将普通树转化成二叉树。比如用二叉树的左子树表示普通树的子结点,用右子树表示普通树的兄弟结点。

事实上任何树都可以转化成相应的二叉树形式来表示,知道为什么数据结构里对二叉树这么重事了吧。

重剑无锋,大巧不工
2012-08-06 14:04
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
回复 45楼 zanzan1986
不要捣乱,现在在说三叉树的事。

重剑无锋,大巧不工
2012-08-06 16:12
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
呵呵,我很享受这样的讨论。但总感觉我们俩说的是两件事,silent_world强调的是void *在公用模块中的作用,而我所说的是void *在目前讨论的三叉搜索树模型中的隐患。

对于void *指针的一个典型范例就是stdlib.h中的qsort函数。通过使用void *参数可以使qsort函数对任意类型的数组进行排序。

但是对于tstrie_destroy(void *root)函数,root必须是一个TERNARY_TRIE型指针,君的函数也只能处理TERNARY_TRIE树(在函数里也做了显示转换),所以这个void *的好处在这里并没有得到体现。相反由于它掩盖了传入指针的原有类型,函数内部并不能知道它原来是指向什么的指针,一概当作TERNARY_TRIE处理。当由于某种原因传入一个别的类型指针,编译器不会发出警告,这时会引发不可预知的问题。这是我反对在这里使用void * 的重要原因。

君提出的另一个概念倒是很有意思,工厂模式在C语言里的应用。
我的C语言学习和使用的阶段主要是在初中和高中。上大学后学了两年C++,之后.net异军突起就改学C#了,包括现在主要使用的语言是C#,C只在玩ACM和论坛交流时才用。
我对语言的使一直以来用分的很开,面向对象就要用面向对象的思想,面向过程就用面向过程的角度。
不过,现在,有时间我一定看看设计模式在C语言下的应用方法和案例。

最后,指出一点,君的tstrie_delData函数逻辑不对。

呵呵,我说话过于直,这是个缺陷,silent_world请见谅,希望这不要影响你交流的心情

重剑无锋,大巧不工
2012-08-06 20:24
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
随风写的怎么样了? silent_world的代码也还没修改?

重剑无锋,大巧不工
2012-08-07 13:31
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
提供一组测试数据吧。最好写一个能返回树中结点个数的函数,以验证操作的正确性。

顺序插入如下串
abc
abeh
abdi
abfj
此时树中应该有9个结点
删除abeh
此时树中应该有7个结点

重剑无锋,大巧不工
2012-08-07 18:08
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
收藏
得分:0 
明天要出差,提前先把我写的删除函数放上来吧。同步更新第一页完整代码。各位晚安。
程序代码:
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;
}

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



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

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