朋友今天问我一个面试题,我看了看,给大家分享一下
2012-10-11 03:59
751 查看
本人才疏学浅,望大家多给意见,有更好的做法大加分享分享
下面是题目:
已知表table_department中有两个字段,分别为d_id,d_name。d_id记录的是部门编码, d_name记录的是部门名称,各部门的组织方式如下:
A为顶级部门,A部门的下级部门使用AA、BA、CA……表示
AA的下级部门使用AAA、BAA、CAA……表示
BA的夏季部门使用ABA、BBA、CBA……表示
以此类推。
新建一个应用程序,写一个页面或窗体,讲table_department表中的数据,按树状排列显示,如下所示:
A总经办
-AA生产部
--AAA保修部
--BAA非保部
-BA物流部
--ABA物流一部
--BBA物流二部
--CBA物流三部
-CA市场部
--ACA市场拓展
--BCA营销部
---ABCA电器营销部
---BBCA电子营销部
…………
…………
加分项:
表table_department用XML实现
===================================================
这个问题我觉得会有比较多的解法,我这里暂且考虑面试的问题,所以给出的解法不会考虑太多严谨的东西
首先建库建表添加数据
SQL脚本为
=================================================
========================================
第一种解法
也是最简单傻瓜式的解法,使用ADO.Net读取数据. 并将读到的数据,根据d_id字段的数据创建TreeView节点,并加载数据
观察树节点的规律,每个节点只有d_id的现实,只有最后一个节点现实完整的d_id和d_name,并且每个d_id的字符表示一个层次结构
因此可以写一个方法,根据包含d_id和d_name的字符串创建节点和添加数据
简单步骤:
1、 首先该方法要往TreeView添加数据,因此该方法一定要有一个TreeNode参数(鉴于根节点只有一个,可以将A添加为根节点,或直接就将"公司"作为根节点)
2、 观察d_id的字符串,根节点在最右边,子节点在左边(估计是为了故意设计的面试题,这样不好排序)
实际这个很简单,将d_id字符串转换成字符数组,从后往左遍历,并在TreeNode中创建节点,如果节点存在就不用创建
3、 因此方法原型可以定义为:
4、 接下来看方法如何实现
由于TreeNode是有层次显示的,所以这里使用递归最为容易(循环感觉也可以实现)
4.1 首先将d_id编程字符数组,并得到最后一个字符,这个顶级节点
4.2 在TreeNode中检索是否存在这个节点. 检索存在就是看TreeNode的子节点中是否有Tag与nodeStr匹配的(这里可使用Linq,不过既然简单用最原始的)
写一个方法,由于部门的名字是不会重复的,所以这么写
该方法只要找到TreeNode直接子节点中存在与给定字符串相同的节点就返回true,否则返回false
4.3 判断是否存在节点,如果不存在就创建,如果存在就得到这个节点
这里需要注意的是,所有节点的逻辑结构均有Tag属性来确认,而Text属性最终使用d_id与d_name替换,因此这里是一个临时的值
4.4 考虑如果存在就得到该节点,但是不要写循环一次了,太麻烦,因此修改IsExist方法
因此4.3步的代码可以改为
这个方法的思路来自int.TryParse方法,如果找到了,那么返回true,那么tnObj中就有了该节点
如果没有找到那么创建一个,反正tnObj中就有当前子节点
4.5 这里应该判断是不是最后一个节点,如果是最后一个节点那么就应该将id和d_name加到Text属性上
由于使用递归完成,因此再次调用这个方法的时候,会将存储d_id的char数组最后一个字符去掉
因此使用chs.Length == 1即可判断是否为最后一个节点
5、 整合一下方法
6、 添加窗体的Load事件,并添加代码
7、 最后要用XML存储,递归遍历节点,创建XML数据,就像遍历文件夹一样
7.1 添加递归方法
7.2 添加按钮事件
========================================
第二种方法
第一种方法比较简单,关键在于如何处理d_id结构而已,而且顺序读取和创建
实际上TreeNode与XML结构一致,是可以同样处理的,也就是说先从数据库中取出数据,生成XML数据,在递归遍历XML数据创建TreeNode
1、 从数据库中读取数据,并创建XML文件
树形结构有一个特点,就是每一个节点只允许有一个父节点和一个子节点,所以可以从数据库中取出所有数据,得到所有数据的节点片段数据
在根据一定算法将节点连起来
1.1 添加一个方法,该方法完成从数据库中读取数据,并得到XML集合(数组也行,个人比较喜欢集合)
1.2 读取数据库,创建XML集合
2、 处理XML片段集合的结构,这个结构没有构成树状结构,因此写一个方法将这个XML片段集合变成一个XML树片段
这里算法有很多,也可以使用Linq查询,但是我不打算详细描述算法,因为有些比较抽象
这里用一个不一定最快,但是很直观的算法
2.1 添加一个方法
2.2 了解到XML每一个节点至多只有一个父节点和子节点,因此只要将处理好节点的去掉即可
同时每一个节点都是通过d_id分层次,而这个层次很有规律,父节点刚好比子节点多一个字符,也就是说
父节点的d_id与子节点的d_id.Substring(1)相同
所以就可以从最长的节点开始找,依次为每一个节点找父节点即可
3、 XML结构有了,那么就可以保存该数据了
另外遍历XML结构,加载到TreeView控件中
4、 添加Load方法
5、 添加保存XML的代码(添加XElement字段)
第三种方法
写了第二种方法就不太想写第三种方法了,介绍一下基本思想吧
为数据表创建一个对象模型,但是多出一个字段,就是记录反序的d_id
那么就可以利用排序等手段创建对象集合
同时解析每一个字符创建TreeView节点了
=================================================
好了,就给出成型的两个算法吧!如果有时间在慢慢看. 本人见识有限,还请大家多提意见,如果有更好的思路,借鉴一下啊!!!
2012年10月10日晚
下面是题目:
已知表table_department中有两个字段,分别为d_id,d_name。d_id记录的是部门编码, d_name记录的是部门名称,各部门的组织方式如下:
A为顶级部门,A部门的下级部门使用AA、BA、CA……表示
AA的下级部门使用AAA、BAA、CAA……表示
BA的夏季部门使用ABA、BBA、CBA……表示
以此类推。
新建一个应用程序,写一个页面或窗体,讲table_department表中的数据,按树状排列显示,如下所示:
A总经办
-AA生产部
--AAA保修部
--BAA非保部
-BA物流部
--ABA物流一部
--BBA物流二部
--CBA物流三部
-CA市场部
--ACA市场拓展
--BCA营销部
---ABCA电器营销部
---BBCA电子营销部
…………
…………
加分项:
表table_department用XML实现
===================================================
这个问题我觉得会有比较多的解法,我这里暂且考虑面试的问题,所以给出的解法不会考虑太多严谨的东西
首先建库建表添加数据
SQL脚本为
=================================================
-- 创建数据库 if db_id('testdb') is not null drop database testdb; go create database testdb; -- 使用数据库 use testdb; --创建数据表 if object_id('table_department', 'U') is null create table table_department ( d_id varchar(10), d_name nvarchar(50) ); go -- 添加数据 insert into table_department(d_id, d_name) values('A', '总经办'); insert into table_department(d_id, d_name) values('AA', '生产部'); insert into table_department(d_id, d_name) values('BA', '物流部'); insert into table_department(d_id, d_name) values('CA', '市场部'); insert into table_department(d_id, d_name) values('AAA', '保修部'); insert into table_department(d_id, d_name) values('BAA', '非保部'); insert into table_department(d_id, d_name) values('ABA', '物流一部'); insert into table_department(d_id, d_name) values('BBA', '物流二部'); insert into table_department(d_id, d_name) values('CBA', '物流三部'); insert into table_department(d_id, d_name) values('ACA', '市场拓展'); insert into table_department(d_id, d_name) values('BCA', '经营部'); insert into table_department(d_id, d_name) values('ABCA', '电器经营部'); insert into table_department(d_id, d_name) values('BBCA', '电子经营部');
========================================
第一种解法
也是最简单傻瓜式的解法,使用ADO.Net读取数据. 并将读到的数据,根据d_id字段的数据创建TreeView节点,并加载数据
观察树节点的规律,每个节点只有d_id的现实,只有最后一个节点现实完整的d_id和d_name,并且每个d_id的字符表示一个层次结构
因此可以写一个方法,根据包含d_id和d_name的字符串创建节点和添加数据
简单步骤:
1、 首先该方法要往TreeView添加数据,因此该方法一定要有一个TreeNode参数(鉴于根节点只有一个,可以将A添加为根节点,或直接就将"公司"作为根节点)
2、 观察d_id的字符串,根节点在最右边,子节点在左边(估计是为了故意设计的面试题,这样不好排序)
实际这个很简单,将d_id字符串转换成字符数组,从后往左遍历,并在TreeNode中创建节点,如果节点存在就不用创建
3、 因此方法原型可以定义为:
private void ShowFromString(string d_id, string id, string d_name, TreeNode tn) { // 实现代码 // d_id创建结构使用 // id记录部门id号 // d_name记录部门名称 // tn表示当前节点 }
4、 接下来看方法如何实现
由于TreeNode是有层次显示的,所以这里使用递归最为容易(循环感觉也可以实现)
4.1 首先将d_id编程字符数组,并得到最后一个字符,这个顶级节点
char[] chs = d_id.ToCharArray(); string nodeStr = chs[chs.Length - 1].ToString();
4.2 在TreeNode中检索是否存在这个节点. 检索存在就是看TreeNode的子节点中是否有Tag与nodeStr匹配的(这里可使用Linq,不过既然简单用最原始的)
写一个方法,由于部门的名字是不会重复的,所以这么写
private bool IsExist(string nodeText, TreeNode tn) { bool isTrue = false; for(int i = 0; i < tn.Nodes.Count; i++) { if(tn.Nodes[i].Tag as string == nodeText) { isTrue = true; break; } } return isTrue; }
该方法只要找到TreeNode直接子节点中存在与给定字符串相同的节点就返回true,否则返回false
4.3 判断是否存在节点,如果不存在就创建,如果存在就得到这个节点
这里需要注意的是,所有节点的逻辑结构均有Tag属性来确认,而Text属性最终使用d_id与d_name替换,因此这里是一个临时的值
TreeNode tnObj = null; if(!IsExist(nodeStr, tn)) { tnObj = tn.Nodes.Add(nodeStr); tnObj.Tag = nodeStr; } else { // 得到这个节点 }
4.4 考虑如果存在就得到该节点,但是不要写循环一次了,太麻烦,因此修改IsExist方法
private bool IsExist(string nodeText, TreeNode tn, out TreeNode tnObj) { tnObj = null; bool isTrue = false; for(int i = 0; i < tn.Nodes.Count; i++) { if(tn.Nodes[i].Tag as string == nodeText) { isTrue = true; tnObj = tn.Nodes[i]; // 将找到的节点直接返回 break; } } return isTrue; }
因此4.3步的代码可以改为
if(!IsExist(nodeStr, tn, out tnObj)) { tnObj = tn.Nodes.Add(nodeStr); tnObj.Tag = nodeStr; }
这个方法的思路来自int.TryParse方法,如果找到了,那么返回true,那么tnObj中就有了该节点
如果没有找到那么创建一个,反正tnObj中就有当前子节点
4.5 这里应该判断是不是最后一个节点,如果是最后一个节点那么就应该将id和d_name加到Text属性上
由于使用递归完成,因此再次调用这个方法的时候,会将存储d_id的char数组最后一个字符去掉
因此使用chs.Length == 1即可判断是否为最后一个节点
if(chs.Length == 1) { // 将当前节点即为结束节点 tnObj.Text = string.Format("{0} {1}", id, d_name); } else { // 如果不是最终节点,则递归 ShowFromString(new string(chs, 0, chs.Length - 1), id, d_name, tnObj); }
5、 整合一下方法
private void ShowFromString(string d_id, string id, string d_name, TreeNode tn) { char[] chs = d_id.ToCharArray(); string nodeStr = chs[chs.Length - 1].ToString(); TreeNode tnObj = null; if(!IsExist(nodeStr, tn, out tnObj)) { tnObj = tn.Nodes.Add(nodeStr); tnObj.Tag = nodeStr; } if(chs.Length == 1) { tnObj.Text = string.Format("{0} {1}", id, d_name); } else { ShowFromString(new string(chs, 0, chs.Length - 1), id, d_name, tnObj); } } private bool IsExist(string nodeText, TreeNode tn, out TreeNode tnObj) { tnObj = null; bool isTrue = false; for(int i = 0; i < tn.Nodes.Count; i++) { if(tn.Nodes[i].Tag as string == nodeText) { isTrue = true; tnObj = tn.Nodes[i]; // 将找到的节点直接返回 break; } } return isTrue; }
6、 添加窗体的Load事件,并添加代码
private void Form1_Load(object sender, EventAges e) { // 添加根节点公司, 就是在公司下面添加节点 TreeNode tn = tvCompany.Nodes.Add("公司"); // 处理数据库,读数据 using(SqlConnection conn = new SqlConnection(@"server=.\sqlexpress;database=testdb;integrated security=true")) { using(SqlCommand cmd = new SqlCommand("select d_id, d_name from table_department", conn)) { conn.Open(); using(SqlDataReader reader = cmd.ExecuteReader()) { if(reader.HasRow) { while(reader.Read()) { string d_id = reader.GetString(0); string d_name = reader.GetString(1); ShowFromString(d_id, d_id, d_name, tn); } } } } } }
7、 最后要用XML存储,递归遍历节点,创建XML数据,就像遍历文件夹一样
7.1 添加递归方法
private void GetXML(TreeNode tn, XElement ele) { // 得到tn下的数据,并加到ele中 for (int i = 0; i < tn.Nodes.Count; i++) { // 创建对应节点 XElement ele1 = new XElement(tn.Nodes[i].Text.Replace(" ", "_")); // 由于XML中节点名中不允许有空格,所以去掉 ele.Add(ele1); // 递归 GetXML(tn.Nodes[i], ele1); } }
7.2 添加按钮事件
private void createXML_Click(object sender, EventArgs e) { XDocument xDoc = new XDocument(); xDoc.Add(new XElement("Company")); GetXML(tvCompany.Nodes[0], xDoc.Root); xDoc.Save("company.xml"); }
========================================
第二种方法
第一种方法比较简单,关键在于如何处理d_id结构而已,而且顺序读取和创建
实际上TreeNode与XML结构一致,是可以同样处理的,也就是说先从数据库中取出数据,生成XML数据,在递归遍历XML数据创建TreeNode
1、 从数据库中读取数据,并创建XML文件
树形结构有一个特点,就是每一个节点只允许有一个父节点和一个子节点,所以可以从数据库中取出所有数据,得到所有数据的节点片段数据
在根据一定算法将节点连起来
1.1 添加一个方法,该方法完成从数据库中读取数据,并得到XML集合(数组也行,个人比较喜欢集合)
private List<XElement> GetElementByDatabase() { // 代码 }
1.2 读取数据库,创建XML集合
private List<XElement> GetElementByDatabase() { List<XElement> list = new List<XElement>(); using (SqlConnection conn = new SqlConnection(@"server=.\sqlexpress;database=testdb;integrated security=true")) { using (SqlCommand cmd = new SqlCommand("select d_id, d_name from table_department", conn)) { conn.Open(); using (SqlDataReader reader = cmd.ExecuteReader()) { if (reader.HasRows) { while (reader.Read()) { string d_id = reader[0].ToString(); string d_name = reader[1].ToString(); // 开始生成XML数据 list.Add(new XElement("department", new XAttribute("d_id", d_id), new XAttribute("d_name", d_name) )); } } } } } return list; }
2、 处理XML片段集合的结构,这个结构没有构成树状结构,因此写一个方法将这个XML片段集合变成一个XML树片段
这里算法有很多,也可以使用Linq查询,但是我不打算详细描述算法,因为有些比较抽象
这里用一个不一定最快,但是很直观的算法
2.1 添加一个方法
public XElement GetXMLTree(List<XElement> listXML) { // 代码 }
2.2 了解到XML每一个节点至多只有一个父节点和子节点,因此只要将处理好节点的去掉即可
同时每一个节点都是通过d_id分层次,而这个层次很有规律,父节点刚好比子节点多一个字符,也就是说
父节点的d_id与子节点的d_id.Substring(1)相同
所以就可以从最长的节点开始找,依次为每一个节点找父节点即可
public XElement GetXMLTree(List<XElement> listXML) { // 先为listXML降序排序,因为d_id越长,节点越深 listXML.Sort((XElement x1, XElement x2) => { return x2.Attribute("d_id").Value.Length - x1.Attribute("d_id").Value.Length; }); // 从左开始为每一个节点找父节点,很显然,最长的节点最深 // 一旦找到父节点,添加进去,就可以将该节点从集合中移除 for (int i = 0; i < listXML.Count; i++) { XElement curr = listXML[i]; for (int j = i + 1; j < listXML.Count; j++) { // 判断是否为父子关系 if (curr.Attribute("d_id").Value.Substring(1) == listXML[j].Attribute("d_id").Value) { listXML[j].Add(curr); } } } return listXML[listXML.Count - 1]; }
3、 XML结构有了,那么就可以保存该数据了
另外遍历XML结构,加载到TreeView控件中
private void ShowTreeNode(TreeNode tn, XElement ele) { foreach (XElement item in ele.Elements()) { TreeNode tn1 = tn.Nodes.Add(string.Format("{0} {1}", item.Attribute("d_id").Value, item.Attribute("d_name").Value)); if (item.HasElements) { ShowTreeNode(tn1, item); } } }
4、 添加Load方法
XElement element = null; // 记录要保存的XML数据 private void Form1_Load(object sender, EventArgs e) { List<XElement> xelements = GetElementByDatabase(); element = GetXMLTree(xelements); ShowTreeNode(tvCompany.Nodes.Add("公司"), element); }
5、 添加保存XML的代码(添加XElement字段)
private void btnSave_Click(object sender, EventArgs e) { XDocument xDoc = new XDocument(element); xDoc.Save("xml.xml"); MessageBox.Show("OK"); }
第三种方法
写了第二种方法就不太想写第三种方法了,介绍一下基本思想吧
为数据表创建一个对象模型,但是多出一个字段,就是记录反序的d_id
那么就可以利用排序等手段创建对象集合
同时解析每一个字符创建TreeView节点了
=================================================
好了,就给出成型的两个算法吧!如果有时间在慢慢看. 本人见识有限,还请大家多提意见,如果有更好的思路,借鉴一下啊!!!
2012年10月10日晚
相关文章推荐
- 朋友今天问我一个面试题,我看了看,给大家分享一下
- 朋友今天问我一个面试题,我看了看,给大家分享一下
- 一个小公司老板的日常管理[朋友发来的,给大家分享一下]
- 一个小公司老板的日常管理[朋友发来的,给大家分享一下]
- 一个小公司老板的日常管理[朋友发来的,给大家分享一下]
- 太感动了,转载他人让大家也分享 一个妓女死了,学校为她降半旗!(无比崇敬)---希望朋友能转载一下!
- 好久没更新博客了,今天给大家分享一下Android中的资源与国际化的问题,通常我们新建一个Android工程,目录结构如下图所示: 我们主要看一下layout与values目录,layou
- 今天写了一个webservice的loadrunner脚步和大家分享一下
- 今天堂哥给我介绍了一个很好的博客,给大家分享一下
- 今天看了一个利用MYeclipse进行Struts讲解的视频和大家分享一下
- 今天又在网上看到一个爱情小故事.读完后挺那样的...给大家分享一下...
- 一个不错的Silverlight展示网站反编译后的源码和大家分享一下(http://www.microsoft.com/taiwan/student/Good.htm),很简单的
- 给大家分享一下我经历的Unix C面试题【转】
- struts2错误信息的几种显示 今天总结一下 分享给大家
- 前两天写的一个菜单和大家分享一下
- 遇到的一个问题和大家分享一下
- 如何备考CCIE/HCIE,一个源自于美帝学员的问题,我会在下午的直播分享会上为大家分享一下经验
- 今天的面试题分享给大家
- 今天学到一个新东西与大家分享: 花是什么?
- 今天给大家做一个猜数字游戏的东西,,不仅能帮助大家更加了解angluar还能小小娱乐一下