题目来自一个搜索公司的笔试题:
http://www.lietu.com/joinus/
http://www.lietu.com/joinus/ClassTree.htm
http://www.lietu.com/joinus/ClassTree.htm
一、层次树(ClassTree.txt):
分类号 | 分类名 | 父分类 | 是否是末级 |
001 | 图书 | 0 | 1 |
001001 | 计算机 | 001 | 1 |
001001001 | 硬件 | 001001 | 0 |
001001002 | 计算机理论 | 001001 | 0 |
001001003 | 网络 | 001001 | 0 |
001001004 | 语言与编程 | 001001 | 1 |
001001004001 | C/C++/VC/C# | 001001004 | 0 |
001001004003 | Basic/VB/VB Script | 001001004 | 0 |
001001004004 | Pascal/Delphi/Fortran | 001001004 | 0 |
001001004005 | Java/Java Script/JSP/EJB | 001001004 | 0 |
001001004008 | Power Builder | 001001004 | 0 |
001001004009 | HTML/XML/ASP/PHP/Perl | 001001004 | 0 |
001001004011 | Director | 001001004 | 0 |
001001004012 | 汇编语言 | 001001004 | 0 |
001001004014 | Foxpro | 001001004 | 0 |
001001004015 | .Net技术 | 001001004 | 0 |
001001004016 | 其他 | 001001004 | 0 |
001001004017 | WAP | 001001004 | 0 |
001001005 | 操作系统 | 001001 | 0 |
001001006 | 数据库 | 001001 | 1 |
001001006001 | Oracle | 001001006 | 0 |
001001006002 | Informix | 001001006 | 0 |
001001006003 | DB2 | 001001006 | 0 |
001001006004 | Sybase | 001001006 | 0 |
001001006005 | SQL Server | 001001006 | 0 |
001001006006 | Foxpro | 001001006 | 0 |
001001006007 | Access | 001001006 | 0 |
001001006008 | 数据仓库 | 001001006 | 0 |
001001006009 | 数据库原理 | 001001006 | 0 |
001001006010 | PowerBuilder | 001001006 | 0 |
001001007 | 认证、等级考试 | 001001 | 0 |
001001008 | 图形图像/网页制作 | 001001 | 1 |
001001008001 | 3DStudio/Max | 001001008 | 0 |
001001008002 | MAYA | 001001008 | 0 |
……
二、参考答案(C#版本,一共两个文件,CategoryNode.cs和Program.cs):
1 //CategoryNode.cs
2
3 using System.Collections.Generic;
4
5 namespace Tree
6 {
7 class CategoryNode
8 {
9 private String no;// 分类号
10
11 private String name;// 分类名
12
13 private bool isLeaf;// 是否为末级
14
15 List<CategoryNode> children =null;
16 //记录此类别的所有子类
17
18 public CategoryNode(String no, String name, bool isLeaf)
19 {
20 this.no = no;
21 this.name = name;
22 this.isLeaf = isLeaf;
23 if (!isLeaf)
24 {
25 children = new List<CategoryNode>(5);
26 }
27 }
28
29 public void addChildren(CategoryNode node)//给此条目增加一个子条目
30 {
31 if (isLeaf)
32 {
33 throw new Exception("add child error to leaf node:" + no );
34 }
35 children.Add(node);
36 }
37
38 public bool leaf()
39 {
40 return isLeaf;
41 }
42
43 public String getName()
44 {
45 return name;
46 }
47
48 public String getNo()
49 {
50 return no;
51 }
52
53 public override String ToString()
54 {
55 String temp = "";
56 foreach (CategoryNode child in children)
57 {
58 temp += child.name+"\n";
59 }
60 temp += "\n";
61 return temp;
62 }
63 }
64 }
1 //Program.cs
2 using System;
3 using System.IO;
4 using System.Collections.Generic;
5
6 namespace Tree
7 {
8 class TreeFind
9 {
10 [STAThread]
11 static void Main(string[] args)
12 {
13 Dictionary<String, CategoryNode> ht = new Dictionary<String, CategoryNode>();
14 StreamReader sr;
15 string line;
16 string temp;
17 try
18 {
19 sr = new StreamReader(@"D:\lg\work\d1\ClassTree.txt", System.Text.Encoding.Default);
20 //ommit head line
21 sr.ReadLine();
22 CategoryNode node = new CategoryNode("0", "ROOT", false);
23 ht.Add("0", node);
24 while ((line = sr.ReadLine()) != null)
25 {
26 line = line.Replace(" ", "");
27 string[] strarray = line.Split(new char[] { '\t' });
28 bool isLeaf = ("0".Equals(strarray[3]));
29
30 node = new CategoryNode(strarray[0], strarray[1], isLeaf);
31 ht.Add(strarray[0], node);
32
33 //if (!"0".Equals(strarray[2]))
34 {
35 ht[strarray[2]].addChildren(node);
36 }
37 }
38 }
39 catch (Exception e)
40 {
41 Console.WriteLine(e.Message);
42 }
43 Console.WriteLine("Please Enter a father node:");
44 temp = Console.ReadLine();
45 while (temp != "exit")
46 {
47 if (ht.ContainsKey(temp))
48 {
49 if (ht[temp].leaf())
50 {
51 Console.WriteLine("The father node haven't any childs!");
52 }
53 else
54 {
55 Console.Write(ht[temp]);
56 }
57 }
58 else
59 {
60 Console.WriteLine("The father node dosn't exists!");
61 }
62 Console.WriteLine("Please Enter a father node:");
63 temp = Console.ReadLine();
64 }
65 }
66 }
67 }
三、自己的理解和体会
因为前段时间一直在学习二叉树和判定树,所以对这个有点敏感。有了二叉树的基础,这个看了一下明白了。就是定义了一个Node类,然后很技巧的定义了一个Hashtable,通过这个Hashtable就可以每次读入一行数据,根据data[3](父类的no)设置该父类的孩子结点了。
这个Hashtable运用得太有技巧了,赞!自己也长见识了!
要是自己去实现这个程序,肯定想不出办法来。只能用很笨的方法实现,也就是定义Node类时定义四个字段,(因为一行中有四个字段)其中包括一个father结点,然后搜索时全部遍历一篇匹配这个father的no,然后再取出该结点。但是这样效率肯定大大降低了,因为要全文遍历。
呵呵,今天又长见识了,对hashtable的作用有了更深的了解。以前只是因为正好符合一对一的key-value关系,所以用到它了;今天总算看到它的最根本的用处了,建立索引!
ok!
jiang,加油哦!