POJ Problem 1002 Solved!

本文使用 Google Docs 编辑,以网页形式发布。最新版本请看以下链接:

http://docs.google.com/View?id=df4r7psc_973ccmbxncn

POJ Problem 1002 Solved! 

  这个题目的解题思路与上次写的英文单词自动补全、纠错很相似。先将电话号码用有根树的形式保存,每个节点表示一个号码,从根到叶节点就是一个完整的号码。记录每个叶子节点的出现在次数,若大于2,就表示有重复的号码了。

  POJ平台对输出的要求十分严格,一点差别都不能有。比如今天遇到的是多输出了一个 '\0',这是个不可见字符,测试根本看不出问题。

 

  因为有根树的代码大量借鉴了之前写的,所以这次基本上没有遇到什么大问题,只是有些细节上,出现了些低级错误(如 == 写成了 =,函数参数列表中 , 写成了 ;)。

 

  下面是代码:

  1 #include <string.h>
  2 #include <stdlib.h>
  3 #include <stdio.h>
  4 #include <ctype.h>
  5
  6 #define NUM_OF_CHILD 10
  7
  8 typedef  struct NumberNode
  9 {
 10      char number;
 11      struct NumberNode *child[NUM_OF_CHILD];   // 0 ~ 9
 12      struct NumberNode *parent;
 13
 14      long counter;   // number of occurence
 15 } NUMBER;
 16
 17 // function decleration ===================================
 18 NUMBER *build_tree ();
 19 // for build_tree() -------------------------------
 20 void parse_input ( char input[], char entry[]);
 21 NUMBER *init_root ();
 22 NUMBER *add_entry (NUMBER *root, char *entry);
 23 NUMBER *add_node (NUMBER *cur_node, char c);
 24 NUMBER *has_child (NUMBER *cur_node, char c);
 25
 26 void leaf_walk (NUMBER *root);
 27 // for leaf_walk()
 28 int has_no_child (NUMBER *cur_node);
 29 void print_entry (NUMBER *leaf);
 30
 31 // @func: build_tree
 32 // 从输入字符串建立有根树
 33 // @return 返回有根树的根节点
 34 NUMBER *build_tree ()
 35 {
 36      int num_of_input;
 37     scanf ("%d", &num_of_input);
 38
 39      char input[100];
 40      char entry[8];
 41     // TODO: build root
 42     NUMBER *root = init_root();
 43
 44      int i;
 45      for (i=0; i<num_of_input; ++i)
 46     {
 47         scanf ("%s", input);
 48         // procee *input* to number format
 49         parse_input (input, entry);
 50
 51         // TODO: add this entry to root
 52         add_entry (root, entry);
 53     }
 54
 55      return root;
 56 }
 57
 58 // @func init_root
 59 // 申请根节点内存,初始化根节点
 60 // @return 返回指向根节点的指针
 61 NUMBER *init_root ()
 62 {
 63     NUMBER *root = (NUMBER *) malloc ( sizeof (NUMBER));
 64     root->number = '\0';
 65      int i;
 66      for (i=0; i<NUM_OF_CHILD; ++i)
 67         root->child[i] = NULL;
 68     root->parent = NULL;
 69     root->counter = 0;
 70
 71      return root;
 72 }
 73
 74 // @func parse_input
 75 // parse string *input* to 7 digits and then store them in *entry*
 76 // @param input: unformat string
 77 // @param entry: storage for the 7 digits
 78 const  char A2iTable[26] =
 79     {'2','2','2', '3','3','3', '4','4','4', '5','5','5', '6','6','6',
 80     '7','7','7','7', '8','8','8', '9','9','9','9'};
 81 void parse_input ( char input[], char entry[])
 82 {
 83      size_t length = strlen (input);
 84      int i, j, index;
 85      for (i=0, j=0; i<length; ++i)
 86     {
 87          if (isdigit(input[i]))
 88         {
 89             entry[j++] = input[i];
 90         }
 91          else  if (input[i] == '-')
 92              continue;
 93          else  if (isupper(input[i]) && input[i]!='Q' && input[i]!='Z')
 94         {
 95             index = ( int)input[i] % ( int)('A');
 96             entry[j++] = A2iTable[index];
 97         }
 98     }
 99     entry[j] = '\0';
100
101     // debug: exam entry
102     // printf ("%s\n", entry);
103     
104 }
105
106
107 // @func add_entry
108 // 往 root 加电话号码条目 entry
109 // @para root 树的根节点
110 // @para entry 待加入单词
111 // @return 返回树的根节点
112 NUMBER *add_entry (NUMBER *root, char *entry)
113 {
114     NUMBER *cur_node = root;
115
116      int i;
117      for (i=0; i<strlen(entry); ++i)
118         cur_node = add_node (cur_node, *(entry+i));
119
120      return root;
121 }
122
123 // @func add_node
124 // 往当前节点 cur_node 添加 c 节点
125 // @para cur_node 当前节点
126 // @para c 要添加的节点字母
127 // @return 返回新节点
128 NUMBER *add_node (NUMBER *cur_node, char c)
129 {
130     NUMBER *child = has_child (cur_node, c);
131     // if *c* already exist
132      if (child)
133     {
134         ++ child->counter;
135          return child;
136     }
137     // otherwise, create a new node
138     child = (NUMBER *) malloc ( sizeof (NUMBER));
139     child->number = c;
140     child->counter = 1;
141     // maintain the tree
142     cur_node->child[c-'0'] = child;
143     child->parent = cur_node;
144      int i;
145      for (i=0; i<NUM_OF_CHILD; ++i)
146     {
147         child->child[i] = NULL;
148     }
149
150      return child;
151 }
152
153 // @func has_child
154 // 判断节点 cur_node 是否拥有一级子节点 c
155 // @para cur_node
156 // @para c 字节点字母
157 // @return 如果有则返回该子节点,无则返回 NULL
158 NUMBER *has_child (NUMBER *cur_node, char c)
159 {
160      if (!cur_node)
161          return NULL;
162      return cur_node->child[c-'0'];
163 }
164
165 int has_no_child (NUMBER *cur_node)
166 {
167      int i;
168      for (i=0; i<NUM_OF_CHILD; ++i)
169          if (cur_node->child[i])
170              return 0;
171      return 1;
172 }
173
174 int flag_no_duplicte = 1;
175 int hyphen_counter = 0;
176 void print_entry (NUMBER *leaf)
177 {
178      if (leaf->parent && leaf->parent->parent)  除去最顶节点 -邱国钦 10-5-8 下午2:41 
179     {
180         print_entry (leaf->parent);
181     }
182     printf ("%c", leaf->number);
183      if (2 == hyphen_counter++)
184         printf ("-");
185 }
186
187 void leaf_walk (NUMBER *root)
188 {
189      if (!root)
190          return;
191      if (has_no_child (root) && (root->counter > 1))
192     {
193         print_entry (root);
194         printf (" %ld\n", root->counter);
195         hyphen_counter = 0;
196         flag_no_duplicte = 0;
197          return;
198     }
199      int i;
200      for (i=0; i<NUM_OF_CHILD; ++i)
201         leaf_walk (root->child[i]);
202 }
203
204 int main ( int argc, char **argv)
205 {
206     NUMBER *root = build_tree ();
207
208     leaf_walk(root);
209      if (flag_no_duplicte)
210         printf ("No duplicates.\n");
211      return 0;
212 }

你可能感兴趣的:(职场,tree,休闲,rooted,POJ1002)