trie树的一个简单例子源码

一下源码是google code jam 上一个简单的题目

题目:

http://code.google.com/codejam/contest/2924486/dashboard#s=p4

 

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXNAMELENGTH 110
#define MAXCHILD 110

typedef struct node{
 char name[MAXNAMELENGTH];
 struct node * child[MAXCHILD];
 int size;
}p_node;

typedef struct {
 p_node * root;
 int is_empty;
}tree;

void init();

void insert(tree *t, char *);

char * get_next_name(int *begin, char *path, char delimiter);

int get_matched_child(char *name, p_node * parent);

int traverse(tree *t, char *path);

p_node * get_empty_node();


/*
* allocate memery for a new empty node, and initialize the memery block for the node.
*
*/
p_node * get_empty_node()
{
 p_node * p = (node *)malloc(sizeof(node));
 memset(p->name, 0, MAXNAMELENGTH);
 int i;
 for(i=0; i<MAXCHILD; ++i)
 {
  p->child[i] = NULL;
 }
 p->size = 0;
 return p;
}

/*
* Extract a name from the string path, names are delimited by the given delimiter in the path.
* begin:  we extract from the given beginning posision, and the begin is an address,
*    it need hold the next beginning position after we extract one name.
* path:   names are in it.
* delimiter: used to delimit
*/
char * get_next_name(int *begin, char *path, char delimiter)
{
 char *result = NULL;

 char * t_str = NULL;

 if(path == NULL)
 {
  //printf("get_next_name error: path is empty!\n");
  exit(1);
 }
 if(*begin >= strlen(path)+1)
 {
  //printf("get_next_name : to the end!\n");
  return result;
 } 
 result = (char *)malloc(sizeof(char)*MAXNAMELENGTH);
 t_str = (char *)malloc(sizeof(char)*MAXNAMELENGTH);
 strcpy(t_str, path + (*begin));
 int length = strchr(t_str, (unsigned int)delimiter) - t_str;
 if(length < 0)
 {
  length = strlen(t_str);
  length = length - 1;  //去掉最后的回车换行和结束字符,结束字符会在后面补齐 
  *begin = *begin + length + 2;
 }
 else
 {
  *begin = *begin + length + 1;
 }
 strncpy(result, t_str, length);
 *(result+length) = '\0';  //construct a C string
 return result;
}

/*
* if return i > parent->size represent that we cannot find a matched child. And the new name should store at the position of i;
*/
int get_matched_child(char * name, p_node * parent)
{
 if(parent == NULL)
 {
  //printf("get_matched_child: all children are NULL\n");
  return 0;
 }
 int i=0;
 for(; i<parent->size; ++i)
 {
  if(parent->child[i] == NULL)
  {
   return i;
  }
  if(strcmp(name, parent->child[i]->name) == 0)
  {
   return i;
  }
 }
 return i;
}

/*
* divide the path into names, construct a node for each name, and insert the node into the tree t.
* Note: the same name reuser the same node in the tree.
*/
void insert(tree *t, char *path)
{
 if(t == NULL)
 {
  //printf("insert error: tree is empty!\n");
 }
 if(NULL == path || strlen(path) > MAXNAMELENGTH)
 {
  //printf("insert error: path error!\n");
 }
 p_node * t_parent;
 p_node * a_n;
 t_parent = t->root;
 int begin=1;
 char *name = NULL;
 int child_index = -1; 
 while((name = get_next_name(&begin, path, '/')) != NULL)
 {
  if((child_index = get_matched_child(name, t_parent)) < t_parent->size )
  {
   t_parent = t_parent->child[child_index];
  }
  else
  {
   a_n = get_empty_node();  
   strcpy(a_n->name, name);
   t_parent->child[child_index] = a_n;
   ++t_parent->size;
   t_parent = a_n;
  }
 }
 t->is_empty = 1;
}

int traverse(tree *t, char *path)
{
 
 if(t == NULL)
    {   
  //printf("insert error: tree is empty!\n");
 }
 if(NULL == path || strlen(path) > MAXNAMELENGTH)
 {    
  //printf("insert error: path error!\n");
 }

 int result = 0;
 char *name;
 int begin = 1;
 int child_index = -1;
 p_node * a_n = NULL;
 p_node * t_parent = NULL;
 t_parent = t->root;
 while((name = get_next_name(&begin, path, '/')) != NULL)
 {
  if((child_index = get_matched_child(name, t_parent)) < t_parent->size )
  {
   t_parent = t_parent->child[child_index];
  }
  else
  {
   a_n = get_empty_node(); 
   strcpy(a_n->name, name);
   t_parent->child[child_index] = a_n;
   
   ++(t_parent->size);
   t_parent = a_n;
   
   ++result;
  }
 }

 return result;

}

void init(tree *t)
{
 if(t == NULL)
 {
  t = (tree *)malloc(sizeof(tree));
 }
 t->root = get_empty_node();
 t->is_empty = 0;   //0 reprent empty; 1 reprent non-empty
}
/*
int main()
{

 FILE *in;
 FILE *out;
 in = fopen("A-large-tries-practice.in", "rb");
 out = fopen("tries_result", "w+");

 tree t;
 


 int i, j;
 int result = 0;
 int cases = 0;
 int n, m;
 char str[10], str1[10], path[110];

 fscanf(in, " %s ", &str);
 cases = atoi(str);
 for(i=0; i<cases; ++i)
 {
  result = 0;
  init(&t);
  fscanf(in, " %s %s ", &str, &str1);
  n = atoi(str);
  m = atoi(str1);
  for(j=0; j<n; ++j)
  {
   fgets(path, MAXNAMELENGTH, in);
   insert(&t, path);
  }
  for(j=0; j<m; ++j)
  {
   fgets(path, MAXNAMELENGTH, in);
   result = result + traverse(&t, path);
  }
  printf("%d\n", i);
  fprintf(out, "Case #%d: %d\n", i+1, result);
 }

 return 1;
}
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值