标题:三叉树演示
只看楼主
beyondyf
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:103
帖 子:3282
专家分:12654
注 册:2008-1-21
结帖率:100%
 问题点数:0 回复次数:55 
三叉树演示
唉,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
姻脂梦
Rank: 6Rank: 6
等 级:侠之大者
帖 子:264
专家分:424
注 册:2012-7-3
得分:0 
保存了细细学习,谢了
2012-08-04 09:50
demonleer
Rank: 9Rank: 9Rank: 9
等 级:贵宾
威 望:10
帖 子:483
专家分:1225
注 册:2012-6-4
得分:0 
无条件顶之
2012-08-04 10:00
silent_world
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:1
帖 子:258
专家分:1138
注 册:2011-9-24
得分:0 
呵呵,偶也来凑凑热闹,只是时间仓促,若有错误,望不吝指出。

/*********************************************************************
Copyright (c) 2012 by silent_world.
All rights reserved. You are not allowed to
copy or distribute the code without permission.
*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


////////////////////////////////////////////////////
//config
#define TSTRIE_NULL (0)
#define TSTRIE_SUCCESS (0)
#define TSTRIE_FAIL (-1)
#define TSTRIE_DELNODE(curNode) do{\
                                       if(curNode->cur_property) \
                                            free(curNode->cur_property); \
                                       free(curNode); \
                                  }while(0)

/////////////////////////////////////////////////////
//struct define

enum{
     TERNARY_LEFT = 0,
     TERNARY_MIDDLE,
     TERNARY_RIGHT
};

typedef struct _TERNARY_TRIE_
{
     char cur_data;           //呵呵,浪费几个字节,惭愧啊

     char *cur_property;
/*
     采用数组存放三叉指针:
     0---左子树
     1---中间子树
     2---右子树
*/
     struct _TERNARY_TRIE_ *child_trie[3];
     struct _TERNARY_TRIE_ *parent;    //父结点
}TERNARY_TRIE;


/*构建树根指针,赋值-1
万物起始为-1,此节点仅仅是形式,完全不需要存值。
*/
void *tstrie_create()
{
     TERNARY_TRIE *me = TSTRIE_NULL;

     if(TSTRIE_NULL == (me = (TERNARY_TRIE *)malloc(sizeof(TERNARY_TRIE))))
          return me;
     memset(me, 0, sizeof(TERNARY_TRIE));

     me->cur_data = -1;

     return me;
}


void tstrie_destroy(void *root)
{
     TERNARY_TRIE *me = (TERNARY_TRIE *)root;
     TERNARY_TRIE *preNode = 0, *curNode = 0;

     preNode = curNode = me->child_trie[TERNARY_MIDDLE];

     while(curNode)
     {
          while(curNode->child_trie[TERNARY_LEFT])curNode = curNode->child_trie[TERNARY_LEFT];
     
          if(curNode->child_trie[TERNARY_MIDDLE])
               curNode = curNode->child_trie[TERNARY_MIDDLE];
          else if(curNode->child_trie[TERNARY_RIGHT])
               curNode = curNode->child_trie[TERNARY_RIGHT];
          else
          {
               preNode = curNode->parent;
               if(preNode->child_trie[TERNARY_LEFT] == curNode)
                    preNode->child_trie[TERNARY_LEFT] = 0;
               else if(preNode->child_trie[TERNARY_MIDDLE] == curNode)
                    preNode->child_trie[TERNARY_MIDDLE] = 0;
               else if(preNode->child_trie[TERNARY_RIGHT] == curNode)
                    preNode->child_trie[TERNARY_RIGHT] = 0;

               TSTRIE_DELNODE(curNode);

               curNode = preNode;
          }
     }
}


int tstrie_addData(void *root, char *cur_data, char *prop)
{
     TERNARY_TRIE *tmpNode = 0, *curNode = 0, *preNode = 0, *strNode = 0;
     TERNARY_TRIE *me = 0;
     unsigned char *cur_p = cur_data, *cur_prop = 0;
     int ret = -1;

     me = (TERNARY_TRIE *)root;
     if(TSTRIE_NULL == me)
          return -1;

     preNode = curNode = me->child_trie[TERNARY_MIDDLE];

     while(curNode)
     {
          if(*cur_p == 0) return TSTRIE_SUCCESS;

          preNode = curNode;

          ret = (*cur_p - curNode->cur_data);
          if(0 != ret)
               ret = (ret > 0)?1:-1;
          else
               cur_p++;


          curNode = curNode->child_trie[ret + 1];
     }
     curNode = preNode;

     preNode = TSTRIE_NULL;
     strNode = TSTRIE_NULL;
     while(*cur_p)
     {
          tmpNode = (TERNARY_TRIE *)malloc(sizeof(TERNARY_TRIE));
          if(0 == tmpNode)
               break;
          memset(tmpNode, 0, sizeof(TERNARY_TRIE));

          tmpNode->cur_data = *cur_p;

          if(0 != preNode)
          {
               tmpNode->parent = preNode;
               preNode->child_trie[TERNARY_MIDDLE] = tmpNode;
          }
          preNode = tmpNode;

          if(0 == strNode)
               strNode = tmpNode;

          cur_p++;
     }

     if(preNode)
     {
          if((prop) && (strlen(prop)))
          {
               cur_prop = (char *)malloc((strlen(prop) + 4) >> 2 << 2);
               if(cur_prop)
               {
                    memset(cur_prop, 0, (strlen(prop) + 4) >> 2 << 2);
                    strcpy(cur_prop, prop);

                    preNode->cur_property = cur_prop;
               }
          }
     }


     if(TSTRIE_NULL == curNode)
     {
          curNode = me;
          curNode->child_trie[TERNARY_MIDDLE] = strNode;
     }
     else
          curNode->child_trie[ret + 1] = strNode;

     if(0 != strNode)
          strNode->parent = curNode;

     return TSTRIE_SUCCESS;
}


int tstrie_delData(void *root, unsigned char *cur_data)
{
     TERNARY_TRIE *curNode = 0, *preNode = 0;
     TERNARY_TRIE *me = (TERNARY_TRIE *)root;
     int ret = -1;
     unsigned char *cur_p = cur_data;

     if(TSTRIE_NULL == me)
          return -1;
     curNode = me->child_trie[TERNARY_MIDDLE];

     while((curNode) && (*cur_p))
     {
          ret = (*cur_p - curNode->cur_data);
          if(0 != ret)
               ret = (ret > 0)?1:-1;
          else
               cur_p++;

          preNode = curNode;

          curNode = curNode->child_trie[ret + 1];
     }
     curNode = preNode;

     if(*cur_p)
          return TSTRIE_FAIL;
     else
     {
          preNode = preNode->parent;
          if(curNode->cur_property)
          {
               free(curNode->cur_property);
               curNode->cur_property = 0;
          }

          while((0 == curNode->child_trie[TERNARY_LEFT])
               && (0 == curNode->child_trie[TERNARY_MIDDLE])
               && (0 == curNode->child_trie[TERNARY_RIGHT])
               && (0 == curNode->cur_property))
          {
               if(me == preNode)
               {
                    TSTRIE_DELNODE(curNode);
                    me->child_trie[TERNARY_MIDDLE] = 0;
                    break;
               }
               else
               {
                    TSTRIE_DELNODE(curNode);

                    if(preNode->child_trie[TERNARY_MIDDLE] == curNode)
                    {
                         preNode->child_trie[TERNARY_MIDDLE] = 0;

                         curNode = preNode;
                         preNode = preNode->parent;
                    }
                    else
                    {
                         if(preNode->child_trie[TERNARY_LEFT] == curNode)
                              preNode->child_trie[TERNARY_LEFT] = 0;
                         else if(preNode->child_trie[TERNARY_RIGHT] == curNode)
                              preNode->child_trie[TERNARY_RIGHT] = 0;

                         break;
                    }
               }
          }

          return TSTRIE_SUCCESS;
     }

}


char *tstrie_searchData(void *root, unsigned char *cur_data)
{
     TERNARY_TRIE *curNode = 0, *preNode = 0;
     TERNARY_TRIE *me = (TERNARY_TRIE *)root;
     int ret = -1;
     unsigned char *cur_p = cur_data;
     
     if(TSTRIE_NULL == me)
          return TSTRIE_NULL;
     curNode = me->child_trie[TERNARY_MIDDLE];

     while(curNode)
     {
          preNode = curNode;
         
          ret = (*cur_p - curNode->cur_data);
          if(0 != ret)
               ret = (ret > 0)?1:-1;
          else
               cur_p++;
         
         
          curNode = curNode->child_trie[ret + 1];
     }

     curNode = preNode;

     if(0 == *cur_p)
     {
          return curNode->cur_property;
     }

     return TSTRIE_NULL;
}


char *testStr[7] = {
     "zhong",
     "hua",
     "ren",
     "min",
     "gong",
     "he",
     "guo"
};


int main()
{
     TERNARY_TRIE *cur_root = 0;
     char *prop_p = 0;
     int i = 0;

     cur_root = tstrie_create();
     if(0 == cur_root)
          return -1;

     for(i = 0; i < 7; i++)
     {
          tstrie_addData(cur_root, testStr[i], testStr[i]);
     }

     for(i = 0; i < 7; i++)
     {
          prop_p = tstrie_searchData(cur_root, testStr[i]);
          if(TSTRIE_NULL == prop_p)
               printf("Search fail...\n");
          else
               printf("The word %s property is:\n %s\n", testStr[i], prop_p);
     }

     tstrie_delData(cur_root, testStr[3]);

     for(i = 0; i < 7; i++)
     {
          prop_p = tstrie_searchData(cur_root, testStr[i]);
          if(TSTRIE_NULL == prop_p)
               printf("Search fail...\n");
          else
               printf("The word %s property is:\n %s\n", testStr[i], prop_p);
     }

     return 0;
}





[ 本帖最后由 silent_world 于 2012-8-4 10:22 编辑 ]
2012-08-04 10:14
信箱有效
Rank: 13Rank: 13Rank: 13Rank: 13
等 级:蒙面侠
威 望:9
帖 子:1102
专家分:4268
注 册:2012-6-19
得分:0 
先学点知识,顺便蹭点分
2012-08-04 12:13
随风飘荡
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:3
帖 子:208
专家分:598
注 册:2011-9-9
得分:0 
我只看到了各种递归……种递归……递归……归……
2012-08-04 13:54
jokerskill
Rank: 7Rank: 7Rank: 7
等 级:黑侠
帖 子:392
专家分:554
注 册:2012-3-4
得分:0 
三叉树???
2012-08-04 17:33
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
随风飘荡
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:3
帖 子:208
专家分:598
注 册:2011-9-9
得分:0 
杨大哥,insert函数里面的中子节点那个为什么递归到tmp了,打错了吧,还是我理解错了

被二叉树搞头都晕现在还有三叉树我得好好看看...

对了,三叉树的优点是什么(相对于二叉树)




[ 本帖最后由 随风飘荡 于 2012-8-4 18:18 编辑 ]
收到的鲜花
  • beyondyf2012-08-04 18:35 送鲜花  50朵   附言:如此认真读我的代码,是我的荣幸!
  • beyondyf2012-08-04 18:36 送鲜花  50朵   附言:感谢指正!
2012-08-04 18:01
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



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-374683-1-1.html




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

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