题目原型:
有一张标准的树状结构表,里面有Structure_Id和 Parent_Id两个关键列,记录了结点的父子关系。现在要求添加一个字段为 Structure_Code ,标记为 三位一个节点关系,比如 第一级的为 001,002,第二级的为 001 001 , 001 002等,以此类推。
现在添加了这样一列:
想要的是这样的:
为什么要这样的东西呢?因为这列中可以描述:它的父亲是谁,爷爷是谁,太爷爷是谁,祖先是谁,当然也可以描述它的所有孩子有哪些,是居家必备,出门旅行的好东西啊!!!做树状设计时强烈推荐。
那么如何处理呢??这是个算法问题,请大家自行设计一下,我们对比一下执行效率。我的答案是5K条左右的数据,共需0.5秒。如果你的算法更优,请告诉我。
我的思路,不要先看啊,请自行设计一下。
解决思路: 1、定义一个NodeBean,包括Structure_ID,Parent_ID,Structure_Code,Child_Count四个属性 2、创建一个数据结构var dict=new Dictionary<String, NodeBean>(); 3、采用DataAdapter一次性将整表读入到内存,存放到dict中。 4、初始化根结点:查询所有根结点,然后按Stucture_ID做为Key,查询到dict中的此实例,然后把对应的NodeBean四个属性分别给定值,Parent_ID=11111-1111-1111-1111,Child_Count=0,Sturcture_Code分别为 001,002,003... 020等。 5、定义一个栈,FILO的东西,http://blog.csdn.net/aladdinty/article/details/3506285 Stack<string> stack = new Stack<string>(); 这个栈用来装需要马上找到父亲的节点。 6、遍历dict,找到第一条记录对应的Structure_Code,如果是空的,那么表示需要填充值,添加到上面定义好的栈里。 7、查找到对应的Parent_ID,然后拿此Parent_ID为KEY去dict中查找上一级节点对应的Structure_Code, 8、如果找到了,那么就可以更改父节点的,Child_Count++,表示又有一个孩子回家了。把父亲的Structure_Code放在前面,后面根据Child_Count记录001,002,003 9、如果还是没有找到,那么继续加入到定义好的栈里。 10、循环检查栈里面是不是有东西,有的话,遍历每一个,因为特殊的数据结构栈,所以是FILO的,就是先进后出,这样就把爷爷结点先和太爷爷结点建立起了关系,把它移除,然后处理父亲,最后处理孩子的。 OK,至此这个Dictionary整理完成,我们重新组装成SQL,一次性事务提交到数据库即可了。
附上代码实现:
using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Data.SQLite; using System.Diagnostics; using System.Windows.Forms; namespace WindowsFormsApplication2 { public class InsideBean { public String StructureId { get; set; } public String ParentId { get; set; } } public partial class Form1 : Form { public Form1() { InitializeComponent(); } //大字典 readonly Dictionary<String, NodeBean> _dict = new Dictionary<String, NodeBean>(); //定义一个堆 readonly Stack<String> _stack = new Stack<String>(); private String _sql = ""; private void button1_Click(object sender, EventArgs e) { // 开始计时 var watch = new Stopwatch(); watch.Start(); DbProviderFactory factory = SQLiteFactory.Instance; using (var conn = factory.CreateConnection()) { // 连接数据库 if (conn != null) { conn.ConnectionString = @"Data Source=c:\resource_db.db"; conn.Open(); //有哪些个学段科目 _sql = "select structure_id,parent_id,structure_node from t_resource_structure"; var adapter = new SQLiteDataAdapter(_sql, conn.ConnectionString); var dataSet = new DataSet(); adapter.Fill(dataSet, "myTable"); var dt = dataSet.Tables[0]; for (var i = 0; i < dt.Rows.Count; i++) { var mybean=new NodeBean { Child_Count = 0, Parent_ID = dt.Rows[i]["parent_id"].ToString(), StructureId = dt.Rows[i]["structure_id"].ToString(), Structure_Code = "" }; _dict.Add(dt.Rows[i]["structure_id"].ToString(),mybean); } //给所有根结点初值 _sql = "select structure_id from t_resource_structure where structure_id=xdkm_id"; adapter = new SQLiteDataAdapter(_sql, conn.ConnectionString); dataSet = new DataSet(); adapter.Fill(dataSet, "myTable"); dt = dataSet.Tables[0]; for (int i = 0; i < dt.Rows.Count; i++) { var code = 1000 + (i + 1); var resultCode = code.ToString().Substring(1, 3); _dict[dt.Rows[i][0].ToString()].Child_Count = 0; _dict[dt.Rows[i][0].ToString()].Structure_Code = resultCode; } foreach (KeyValuePair<string, NodeBean> a in _dict) { if (a.Value.Structure_Code == "") { //入栈,表示这个家伙需要进行本轮处理 _stack.Push(a.Value.StructureId); var currentBean = new InsideBean { ParentId = a.Value.Parent_ID, StructureId = a.Value.StructureId }; while (_stack.Count > 0) { if (_dict[currentBean.ParentId].Structure_Code == "") { _stack.Push(currentBean.ParentId); //结构ID currentBean.StructureId = currentBean.ParentId; //结构的父ID currentBean.ParentId = _dict[currentBean.ParentId].Parent_ID; } else { //找到了它父亲的东西 _dict[currentBean.ParentId].Child_Count++; int code = 1000 + (_dict[currentBean.ParentId].Child_Count); String resultCode = code.ToString().Substring(1, 3); _dict[currentBean.StructureId].Structure_Code = _dict[currentBean.ParentId].Structure_Code + resultCode; //把父亲出栈 _stack.Pop(); //把这个父亲的儿子 if (_stack.Count > 0) { //结构ID currentBean.StructureId = _stack.Peek();//取出顶层元素 //结构的父ID currentBean.ParentId = _dict[_stack.Peek()].Parent_ID; } } } } } //保存到数据库 _sql = "update t_resource_structure set structure_node=? where structure_id=?"; var cmd = conn.CreateCommand(); var trans = conn.BeginTransaction(); cmd.Connection = conn; cmd.CommandText = _sql; // 添加参数 cmd.Parameters.Add(cmd.CreateParameter()); cmd.Parameters.Add(cmd.CreateParameter()); try { foreach (var a in _dict) { cmd.Parameters[0].Value = a.Value.Structure_Code; cmd.Parameters[1].Value = a.Value.StructureId; cmd.ExecuteNonQuery(); } trans.Commit(); } catch (Exception err) { trans.Rollback(); throw; } } //更新一下资源与结构对应关系表 _sql = "update t_resource_location set structure_node=(select t_resource_structure.structure_node from t_resource_structure where t_resource_structure.structure_id=t_resource_location.node_id)"; using (var cmd2 = conn.CreateCommand()) { cmd2.Connection = conn; cmd2.CommandText = _sql; cmd2.ExecuteNonQuery(); } conn.Close(); // 停止计时 watch.Stop(); MessageBox.Show("完成:耗时" + watch.Elapsed); } } } }