精华帖 (4) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (5)
|
|
---|---|
作者 | 正文 |
发表时间:2012-04-15
最后修改:2012-04-17
(原创)新概念智能树形菜单--利用加权多叉树结合JavaScript树形控件实现
大家都知道树形菜单,不管在基于什么样的技术开发的系统上,树形菜单都是用户界面中非常常用的一种菜单形式,在目前市场上常见的JavaScript框架及组件库中均包含自己的树形控件,例如JQuery、Dojo、Yahoo UI、Ext JS等,还有一些独立的树形控件,例如dhtmlxtree等,这些树形控件完美的解决了层次数据的展示问题。那么树形菜单发展到现在就算完美了吗?还有没有进一步的发展空间呢?还有没有进一步的完善空间呢?答案是肯定的。在这篇文章里,我提出一种新的想法对树形菜单进行扩展,也许会给您的项目带来一些新的用户体验,我管这种扩展型的树形菜单叫做“智能树形菜单”。那么智能树形菜单和普通的树形菜单到底有什么区别呢,它到底智能在哪呢,让我们先来看一组用例场景:
网民高小宝是一名网上银行的忠实用户,他经常利用网银办理各种银行业务,假设高小宝在
他想给自己的朋友李小磊转一笔钱,于是他在界面左上角的“输入交易功能关键字”输入框中输入“转账”二字,点击“搜索”按钮,查询出了如下的结果,如图:
他看到左侧的树形菜单区域中搜索出了三个交易功能,分别是行内转账、跨行转账和跨行快速转账,于是他点击跨行转账后,主界面进入跨行转账信息录入界面,高小宝很快完成了转账操作,如下图:
高小宝一看,这个银行的网上银行系统操作这么方便,于是他又陆续使用了以下几个功能,分别是“投资理财->定活互转”、“投资理财->理财产品->产品购买”、“我的贷款->贷款信息查询”、“客户服务->昵称设置”,本次登录他一共使用了五个功能点,其中“转账汇款->跨行转账”功能使用了两次,一次是给朋友李小磊转钱,另一次是给朋友王小然转钱,其他四个功能各使用了一次。
他看到昨天使用的五个功能点菜单全部自动展开了,而且菜单顺序也发生了变化:原来排在最后的一级菜单“客户服务”居然移到了“我的贷款”下面,而原来排在第一位的“账户管理”却移到了“客户服务”下面,由于部分菜单自动展开,所以菜单栏右侧出现了滚动条。
A、用户首次登录系统时,功能菜单树全部闭合,并且按照菜单编号排序,且每一层菜单节点都按照这个规则排序,保持整棵功能树兄弟节点横向有序(关于“兄弟节点横向有序”的概念请查看附录:我的上一篇文章《多叉树结合JavaScript树形控件实现无限级树形菜单(一种构建多级有序树形结构JSON(或XML)数据源的方法)》); B、系统会自动记录每一个功能路径(功能路径指的是由一级菜单节点到功能叶子节点的一条完整路径,例如“投资理财->理财产品->产品购买”就是一条功能路径)的使用率; C、系统提供菜单节点搜索功能,用户可以输入菜单节点关键字,系统会搜索出包含关键字的所有功能路径,并展示出搜索结果; D、用户再次登录系统时,功能菜单重新排序,并且部分展开,其规则如下: (1)整棵功能菜单树按照使用率加节点编号的方式排序,先按使用率排序,使用率相同的情况下按照节点编号排序,保持兄弟节点横向有序; (2)热点功能自动展开(热点功能指的是功能使用率大于所有功能平均使用率的功能叶子节点,例如在上面的用例场景中,高小宝第一次使用网银时,“跨行转账”被使用了两次,“定活互转”、“产品购买”、“贷款信息查询”、“昵称设置”都被使用了一次,其他功能被使用了零次,假设一共有30个功能,那么功能平均使用率是(2+1+1+1+1)/ 30 = 0.2, 这五个功能的使用率均大于0.2,所以都属于热点功能) E、系统主界面默认进入焦点功能(焦点功能指的是热点功能中使用率最高的功能)的操作界面;
好了,智能树形菜单的概念就介绍完了,下面讲述详细实现方案。
二、 详细实现方案
下面这张图就是扩展之后的多叉树,并且根据这张图定义了一系列名词概念,如图所示:
我们先根据这张图定义一组名词概念:
2、节点权值
3、功能叶子节点
4、功能路径
5、功能路径权值
6、 优先功能路径
7、功能叶子列表
8、功能叶子权值
9、热点功能叶子
10、焦点功能叶子
11、功能路径可见
12、菜单节点搜索
13、功能路径筛选
14、增加功能路径权值
我们可以把这棵加了节点权值的多叉树叫做加权多叉树,英文名称叫weighted multiple tree,简称W-M-Tree。
其中黄色圆圈代表功能叶子节点。
构造出这棵树之后,向客户端的JavaScript树形控件返回树形结构的JSON字符串,返回如下内容: { id: '0', text: '根', children: [ { id: '1', text: '1', children: [ { id: '11', text: '11', leaf: true }, { id: '12', text: '12', children: [ { id: '121', text: '121', leaf: true }, { id: '122', text: '122', leaf: true }, { id: '123', text: '123', leaf: true } ] } ] }, { id: '2', text: '2', children: [ { id: '21', text: '21', leaf: true }, { id: '22', text: '22', leaf: true } ] }, { id: '3', text: '3', children: [ { id: '31', text: '31', leaf: true }, { id: '32', text: '32', children: [ { id: '321', text: '321', leaf: true }, { id: '322', text: '322', leaf: true }, { id: '323', text: '323', leaf: true } ] } ] }, { id: '4', text: '4', children: [ { id: '41', text: '41', leaf: true }, { id: '42', text: '42', leaf: true }, { id: '43', text: '43', leaf: true } ] } ] }
进行功能路径筛选后,向客户端返回如下JSON字符串: { id: '0', text: '根', children: [ { id: '1', text: '1', children: [ { id: '12', text: '12', children: [ { id: '121', text: '121', leaf: true }, { id: '122', text: '122', leaf: true }, { id: '123', text: '123', leaf: true } ] } ] } ] }
图三,用户再使用关键字“321”在功能叶子列表中进行搜索,搜索结果如图所示:
进行功能路径筛选后,向客户端返回如下JSON字符串: { id: '0', text: '根', children: [ { id: '3', text: '3', children: [ { id: '32', text: '32', children: [ { id: '321', text: '321', leaf: true } ] } ] } ] }
到这里,您一定会问:菜单节点搜索必须要在服务器端进行吗,这样响应速度岂不是很慢?是的,这的确是个问题,那么,该功能能否放在客户端来实现呢?通过改造现有的树形控件或者重新开发新的树形控件,利用JavaScript在客户端来实现菜单节点的搜索功能,而无需与服务器进行交互。比如,能否利用JavaScript在客户端构造一棵多叉树,然后采用类似的方法来实现菜单节点的搜索呢?具体实现方法不是本文讨论的重点,本文只是提供一个思路,具体实现还要看您了,呵呵。
图五,当用户退出,再次登录系统后,在服务器端再次构造出加权多叉树和功能叶子列表,此时数据结构变成如下样子:
树中红色线条部分为优先功能路径,功能叶子列表中红色圆圈为焦点功能叶子。
图七,当用户退出,再次登录系统后,在服务器端再次构造出加权多叉树和功能叶子列表,此时数据结构变成如下样子:
树中红色线条部分根据路径权值和节点编号重新进行了兄弟节点横向排序;
现在服务器向客户端返回的JSON字符串变成了如下: { id: '0', text: '根', children: [ { id: '1', text: '1', children: [ { id: '12', text: '12', children: [ { id: '122', text: '122', leaf: true }, { id: '121', text: '121', leaf: true }, { id: '123', text: '123', leaf: true } ] }, { id: '11', text: '11', leaf: true } ] }, { id: '3', text: '3', children: [ { id: '32', text: '32', children: [ { id: '323', text: '323', leaf: true }, { id: '321', text: '321', leaf: true }, { id: '322', text: '322', leaf: true } ] }, { id: '31', text: '31', leaf: true } ] }, { id: '2', text: '2', children: [ { id: '21', text: '21', leaf: true }, { id: '22', text: '22', leaf: true } ] }, { id: '4', text: '4', children: [ { id: '41', text: '43211', leaf: true }, { id: '42', text: '42', leaf: true }, { id: '43', text: '43', leaf: true } ] } ] }
对于热点功能叶子自动展开,和系统默认进入焦点功能界面这两个功能,只需要客户端通过AJAX的方式从服务器端的功能叶子列表中取出热点功能叶子和焦点功能叶子的节点编号后,在客户端通过编程处理,取热点功能叶子的方法很简单,只需要取出叶子权值大于叶子平均权值的节点即可,然后再找到一个权值最大的叶子就是焦点功能叶子;至于如何展开树形控件的叶子节点本文不做叙述,那是树形控件要实现的功能。
三、 源代码实现(服务器端JAVA代码演示) 以下代码拷贝出来后可以直接运行测试(注:关于菜单节点搜索功能,这里用java来演示,在服务器端进行,系统响应速度很慢,应该放在客户端实现):
package test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Collections; /** * 功能菜单树类 */ public class FunctionTree { public static void main(String[] args) { // 读取层次数据结果集列表 List dataList = VirtualDataGenerator.getVirtualResult(); // 构造加权多叉树 Node root = buildWeightedMultiTree(dataList); // 构造功能叶子列表 List functionLeafList = buildFunctionLeafList(root); // 对多叉树重新进行横向排序 root.sortChildren(); // 输出首次登录后的树形菜单 System.out.println("首次登录时的树形菜单:\n" + root.toString()); // 进行菜单节点搜索(即功能路径筛选) searchTreeNode(root, "321"); // 输出搜索结果 System.out.println("搜索后的树形菜单:\n" + root.toString()); // 增加功能路径权值 increaseRouteWeight(root, functionLeafList, "122"); increaseRouteWeight(root, functionLeafList, "323"); // 对多叉树重新进行横向排序 root.sortChildren(); // 输出权值变化后的树形菜单 System.out.println("路径权值变化后再次登录时的树形菜单:\n" + root.toString()); // 获取热点功能叶子 List hotFunctionLeaf = getHotFunctionLeaf(functionLeafList); // 输出热点功能叶子 printHotFunctionLeaf(hotFunctionLeaf); // 程序输出结果如下: // 首次登录时的树形菜单: // {id : '0', text : '根', children : [{id : '1', text : '1', children : [{id : '11', text : '11', leaf : true},{id : '12', text : '12', children : [{id : '121', text : '121', leaf : true},{id : '122', text : '122', leaf : true},{id : '123', text : '123', leaf : true}]}]},{id : '2', text : '2', children : [{id : '21', text : '21', leaf : true},{id : '22', text : '22', leaf : true}]},{id : '3', text : '3', children : [{id : '31', text : '31', leaf : true},{id : '32', text : '32', children : [{id : '321', text : '321', leaf : true},{id : '322', text : '322', leaf : true},{id : '323', text : '323', leaf : true}]}]},{id : '4', text : '4', children : [{id : '41', text : '41', leaf : true},{id : '42', text : '42', leaf : true},{id : '43', text : '43', leaf : true}]}]} // 搜索后的树形菜单: // {id : '0', text : '根', children : [{id : '3', text : '3', children : [{id : '32', text : '32', children : [{id : '321', text : '321', leaf : true}]}]}]} // 路径权值变化后再次登录时的树形菜单: // {id : '0', text : '根', children : [{id : '1', text : '1', children : [{id : '12', text : '12', children : [{id : '122', text : '122', leaf : true},{id : '121', text : '121', leaf : true},{id : '123', text : '123', leaf : true}]},{id : '11', text : '11', leaf : true}]},{id : '3', text : '3', children : [{id : '32', text : '32', children : [{id : '323', text : '323', leaf : true},{id : '321', text : '321', leaf : true},{id : '322', text : '322', leaf : true}]},{id : '31', text : '31', leaf : true}]},{id : '2', text : '2', children : [{id : '21', text : '21', leaf : true},{id : '22', text : '22', leaf : true}]},{id : '4', text : '4', children : [{id : '41', text : '41', leaf : true},{id : '42', text : '42', leaf : true},{id : '43', text : '43', leaf : true}]}]} // 热点功能叶子: // [{id : '323', text : '323', leaf : true}, {id : '122', text : '122', leaf : true}] } /** * 构造加权多叉树 * @return */ public static Node buildWeightedMultiTree(List dataList) { // 节点列表(散列表,用于临时存储节点对象) HashMap nodeList = new HashMap(); // 根节点 Node root = null; // 根据结果集构造节点列表(存入散列表) for (Iterator it = dataList.iterator(); it.hasNext();) { Map dataRecord = (Map) it.next(); Node node = new Node(); node.id = (String) dataRecord.get("id"); node.text = (String) dataRecord.get("text"); node.parentId = (String) dataRecord.get("parentId"); node.weight = Integer.parseInt((String) dataRecord.get("weight")); nodeList.put(node.id, node); } // 构造无序的多叉树 Set entrySet = nodeList.entrySet(); for (Iterator it = entrySet.iterator(); it.hasNext();) { Node node = (Node) ((Map.Entry) it.next()).getValue(); if (node.parentId == null || node.parentId.equals("")) { root = node; } else { ((Node) nodeList.get(node.parentId)).addChild(node); // 在节点中增加一个父节点的引用 node.parentNode = (Node) nodeList.get(node.parentId); } } return root; } /** * 构造功能叶子列表 * @param root * @return */ public static List buildFunctionLeafList(Node root) { List functionLeafList = new ArrayList(); root.initializeLeafList(functionLeafList); return functionLeafList; } /** * 进行菜单节点搜索(即功能路径筛选) * @param root * @param keyWord */ public static void searchTreeNode(Node root, String keyWord) { // 首先设置整棵树的功能路径为不可见 root.setTreeNotVisible(); // 在整棵功能树中搜索包含关键字的节点,并进行路径筛选 root.searchTreeNode(keyWord); } /** * 增加功能路径权值 * @param root */ public static void increaseRouteWeight(Node root, List functionLeafList, String nodeId) { // 首先设置整棵树的功能路径为可见 root.setTreeVisible(); // 对包含功能叶子节点的路径权值加1 for (Iterator it = functionLeafList.iterator(); it.hasNext();) { Node leafNode = (Node) it.next(); if (leafNode.id.equals(nodeId)) { leafNode.increaseRouteWeight(); } } } /** * 获取热点功能叶子 * @param functionLeafList * @return */ public static List getHotFunctionLeaf(List functionLeafList) { int count = 0; int totalWeight = 0; BigDecimal avgWeight; for (Iterator it = functionLeafList.iterator(); it.hasNext();) { Node node = (Node) it.next(); totalWeight += node.weight; count++; } avgWeight = (new BigDecimal(totalWeight)).divide(new BigDecimal(count), 2, BigDecimal.ROUND_HALF_UP); List retList = new ArrayList(); for (Iterator it = functionLeafList.iterator(); it.hasNext();) { Node node = (Node) it.next(); if (node.weight > avgWeight.doubleValue()) { retList.add(node); } } return retList; } /** * 输出热点功能叶子 * @param hotFunctionLeaf */ public static void printHotFunctionLeaf(List hotFunctionLeaf) { System.out.println("热点功能叶子:\n" + hotFunctionLeaf); } } /** * 节点类 */ class Node { /** * 节点编号 */ public String id; /** * 节点内容 */ public String text; /** * 父节点编号 */ public String parentId; /** * 节点权值 */ public int weight; /** * 是否可见,默认为true */ public boolean visible = true; /** * 父节点引用 */ public Node parentNode; /** * 孩子节点列表 */ private Children children = new Children(); // 添加孩子节点 public void addChild(Node node) { this.children.addChild(node); } // 先序遍历,拼接JSON字符串 public String toString() { if (visible) { String result = "{" + "id : '" + id + "'" + ", text : '" + text + "'"; if (children != null && children.getSize() != 0) { result += ", children : " + children.toString(); } else { result += ", leaf : true"; } return result + "}"; } else { return ""; } } // 兄弟节点横向排序 public void sortChildren() { if (children != null && children.getSize() != 0) { children.sortChildren(); } } // 先序遍历,构造功能叶子列表 public void initializeLeafList(List leafList) { if (children == null || children.getSize() == 0) { leafList.add(this); } else { children.initializeLeafList(leafList); } } // 先序遍历,设置该节点下的所有功能路径为不可见 public void setTreeNotVisible() { visible = false; if (children != null && children.getSize() != 0) { children.setTreeNotVisible(); } } // 先序遍历,设置该节点下的所有功能路径为可见 public void setTreeVisible() { visible = true; if (children != null && children.getSize() != 0) { children.setTreeVisible(); } } // 设置包含该叶子节点的功能路径可见 public void setRouteVisible() { visible = true; for (Node parentNode = this.parentNode; parentNode != null; parentNode = parentNode.parentNode) { parentNode.visible = true; } } // 对包含该叶子节点的功能路径权值加1 public void increaseRouteWeight() { weight++; updateNodeWeightToDB(this); for (Node parentNode = this.parentNode; parentNode != null; parentNode = parentNode.parentNode) { parentNode.weight++; updateNodeWeightToDB(parentNode); } } // 更新节点权值到数据库 public void updateNodeWeightToDB(Node node) { // 暂时不实现,实际应用中需要实现该方法 // 或者用户退出系统时,遍历整棵树,统一更新所有节点的权值到数据库中,应该这样做比较好,一次性统一处理 } // 先序遍历,搜索菜单节点,同时进行功能路径过滤 public void searchTreeNode(String keyWord) { if (this.text.indexOf(keyWord) > -1) { this.setTreeVisible(); this.setRouteVisible(); } else { if (children != null && children.getSize() != 0) { children.searchTreeNode(keyWord); } } } } /** * 孩子列表类 */ class Children { private List list = new ArrayList(); public int getSize() { return list.size(); } public void addChild(Node node) { list.add(node); } // 拼接孩子节点的JSON字符串 public String toString() { String result = "["; for (Iterator it = list.iterator(); it.hasNext();) { Node node = (Node) it.next(); if (node.visible) { result += node.toString(); result += ","; } } result = result.substring(0, result.length() - 1); result += "]"; return result; } // 在孩子节点中寻找功能叶子节点 public void initializeLeafList(List leafList) { for (Iterator it = list.iterator(); it.hasNext();) { ((Node) it.next()).initializeLeafList(leafList); } } // 孩子节点排序 public void sortChildren() { // 对本层节点进行排序 // 可根据不同的排序属性,传入不同的比较器,这里传入优先级比较器 Collections.sort(list, new NodePriorityComparator()); // 对每个节点的下一层节点进行排序 for (Iterator it = list.iterator(); it.hasNext();) { ((Node) it.next()).sortChildren(); } } // 设置孩子节点为不可见 public void setTreeNotVisible() { for (Iterator it = list.iterator(); it.hasNext();) { ((Node) it.next()).setTreeNotVisible(); } } // 设置孩子节点为可见 public void setTreeVisible() { for (Iterator it = list.iterator(); it.hasNext();) { ((Node) it.next()).setTreeVisible(); } } // 搜索菜单节点,同时进行功能路径过滤 public void searchTreeNode(String keyWord) { for (Iterator it = list.iterator(); it.hasNext();) { ((Node) it.next()).searchTreeNode(keyWord); } } } /** * 节点比较器 */ class NodePriorityComparator implements Comparator { // 按照 (节点权值+节点编号) 比较 public int compare(Object o1, Object o2) { // 按权值由大到小排序 int w1 = ((Node)o1).weight; int w2 = ((Node)o2).weight; if (w1 < w2) { return 1; } else if (w1 > w2) { return -1; } else { // 权值相等时,按照节点编号由小到大排序 int i1 = Integer.parseInt(((Node)o1).id); int i2 = Integer.parseInt(((Node)o2).id); return i1 < i2 ? -1 : (i1 == i2 ? 0 : 1); } } } /** * 构造虚拟的层次数据 */ class VirtualDataGenerator { // 构造无序的结果集列表,实际应用中,该数据应该从数据库中查询获得; public static List getVirtualResult() { List dataList = new ArrayList(); HashMap dataRecord1 = new HashMap(); dataRecord1.put("id", "0"); dataRecord1.put("text", "根"); dataRecord1.put("parentId", ""); dataRecord1.put("weight", "1"); HashMap dataRecord2 = new HashMap(); dataRecord2.put("id", "1"); dataRecord2.put("text", "1"); dataRecord2.put("parentId", "0"); dataRecord2.put("weight", "1"); HashMap dataRecord3 = new HashMap(); dataRecord3.put("id", "2"); dataRecord3.put("text", "2"); dataRecord3.put("parentId", "0"); dataRecord3.put("weight", "1"); HashMap dataRecord4 = new HashMap(); dataRecord4.put("id", "3"); dataRecord4.put("text", "3"); dataRecord4.put("parentId", "0"); dataRecord4.put("weight", "1"); HashMap dataRecord5 = new HashMap(); dataRecord5.put("id", "4"); dataRecord5.put("text", "4"); dataRecord5.put("parentId", "0"); dataRecord5.put("weight", "1"); HashMap dataRecord6 = new HashMap(); dataRecord6.put("id", "11"); dataRecord6.put("text", "11"); dataRecord6.put("parentId", "1"); dataRecord6.put("weight", "1"); HashMap dataRecord7 = new HashMap(); dataRecord7.put("id", "12"); dataRecord7.put("text", "12"); dataRecord7.put("parentId", "1"); dataRecord7.put("weight", "1"); HashMap dataRecord8 = new HashMap(); dataRecord8.put("id", "21"); dataRecord8.put("text", "21"); dataRecord8.put("parentId", "2"); dataRecord8.put("weight", "1"); HashMap dataRecord9 = new HashMap(); dataRecord9.put("id", "22"); dataRecord9.put("text", "22"); dataRecord9.put("parentId", "2"); dataRecord9.put("weight", "1"); HashMap dataRecord10 = new HashMap(); dataRecord10.put("id", "31"); dataRecord10.put("text", "31"); dataRecord10.put("parentId", "3"); dataRecord10.put("weight", "1"); HashMap dataRecord11 = new HashMap(); dataRecord11.put("id", "32"); dataRecord11.put("text", "32"); dataRecord11.put("parentId", "3"); dataRecord11.put("weight", "1"); HashMap dataRecord12 = new HashMap(); dataRecord12.put("id", "41"); dataRecord12.put("text", "41"); dataRecord12.put("parentId", "4"); dataRecord12.put("weight", "1"); HashMap dataRecord13 = new HashMap(); dataRecord13.put("id", "42"); dataRecord13.put("text", "42"); dataRecord13.put("parentId", "4"); dataRecord13.put("weight", "1"); HashMap dataRecord14 = new HashMap(); dataRecord14.put("id", "43"); dataRecord14.put("text", "43"); dataRecord14.put("parentId", "4"); dataRecord14.put("weight", "1"); HashMap dataRecord15 = new HashMap(); dataRecord15.put("id", "121"); dataRecord15.put("text", "121"); dataRecord15.put("parentId", "12"); dataRecord15.put("weight", "1"); HashMap dataRecord16 = new HashMap(); dataRecord16.put("id", "122"); dataRecord16.put("text", "122"); dataRecord16.put("parentId", "12"); dataRecord16.put("weight", "1"); HashMap dataRecord17 = new HashMap(); dataRecord17.put("id", "123"); dataRecord17.put("text", "123"); dataRecord17.put("parentId", "12"); dataRecord17.put("weight", "1"); HashMap dataRecord18 = new HashMap(); dataRecord18.put("id", "321"); dataRecord18.put("text", "321"); dataRecord18.put("parentId", "32"); dataRecord18.put("weight", "1"); HashMap dataRecord19 = new HashMap(); dataRecord19.put("id", "322"); dataRecord19.put("text", "322"); dataRecord19.put("parentId", "32"); dataRecord19.put("weight", "1"); HashMap dataRecord20 = new HashMap(); dataRecord20.put("id", "323"); dataRecord20.put("text", "323"); dataRecord20.put("parentId", "32"); dataRecord20.put("weight", "1"); dataList.add(dataRecord1); dataList.add(dataRecord2); dataList.add(dataRecord3); dataList.add(dataRecord4); dataList.add(dataRecord5); dataList.add(dataRecord6); dataList.add(dataRecord7); dataList.add(dataRecord8); dataList.add(dataRecord9); dataList.add(dataRecord10); dataList.add(dataRecord11); dataList.add(dataRecord12); dataList.add(dataRecord13); dataList.add(dataRecord14); dataList.add(dataRecord15); dataList.add(dataRecord16); dataList.add(dataRecord17); dataList.add(dataRecord18); dataList.add(dataRecord19); dataList.add(dataRecord20); return dataList; } }
四、 联系方式
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2012-04-16
LZ用了这么大篇幅,这么多概念 定义了这么点事。。。而且感觉这个所谓的智能和人家那些extjstree,jquery tree神马的一点关系都木有,真是躺着也中枪啊。。不过还是赞扬LZ这么认真的写作精神
|
|
返回顶楼 | |
发表时间:2012-04-16
楼主的代码贴得太多了,修饰下就是论文了,投稿去吧。
|
|
返回顶楼 | |
发表时间:2012-04-16
就是个前缀搜索吧..其他没什么.因为太长了看不太懂哦.
|
|
返回顶楼 | |
发表时间:2012-04-16
第一次发表时间:2012-01-01,原文连接:http://www.iteye.com/topic/1119490
第二次发表时间:2012-01-24 ,原文连接:http://www.iteye.com/topic/1119961
第三次发表时间:2012-02-01 ,原文连接:http://www.iteye.com/topic/1120062
不解释,大家都懂的。
敢问,javaeye管理员,发生这种情况,就不采取点措施吗?? 长此以往,javaeye会是什么样子??让人心寒啊!!!! 和一开始的iteye的理念渐行渐远了!哎!!! |
|
返回顶楼 | |
发表时间:2012-04-16
朋友,先申请个专利再来介绍,引起银行注意,然后等着收钱
|
|
返回顶楼 | |
发表时间:2012-04-16
lib 写道
第一次发表时间:2012-01-01,原文连接:http://www.iteye.com/topic/1119490
第二次发表时间:2012-01-24 ,原文连接:http://www.iteye.com/topic/1119961
第三次发表时间:2012-02-01 ,原文连接:http://www.iteye.com/topic/1120062
不解释,大家都懂的。
敢问,javaeye管理员,发生这种情况,就不采取点措施吗?? 长此以往,javaeye会是什么样子??让人心寒啊!!!! 和一开始的iteye的理念渐行渐远了!哎!!!
|
|
返回顶楼 | |
发表时间:2012-04-16
最后修改:2012-04-16
lib 写道 第一次发表时间:2012-01-01,原文连接:http://www.iteye.com/topic/1119490 第二次发表时间:2012-01-24 ,原文连接:http://www.iteye.com/topic/1119961 第三次发表时间:2012-02-01 ,原文连接:http://www.iteye.com/topic/1120062 第四次发表时间:2012-02-08 ,原文连接:http://www.iteye.com/topic/1120263 不解释,大家都懂的。 敢问,javaeye管理员,发生这种情况,就不采取点措施吗?? 长此以往,javaeye会是什么样子??让人心寒啊!!!! 和一开始的iteye的理念渐行渐远了!哎!!! 我就说这货看着怎么这么眼熟 |
|
返回顶楼 | |
发表时间:2012-04-17
最后修改:2012-07-08
各位,先别急着骂,我想说几句: ####################################################################################### 这篇文章是我睡觉做梦的时候梦到的,醒来之后赶紧写成文章发到iteye上,
我觉得这篇文章最有价值的地方是 “菜单节点搜索” 功能,现有的树形控件应该加入这个功能就完美了。
树形菜单的节点数量一般是几十个节点,如果层次比较深的话,要找到某一个节点,找起来很麻烦,应该加入一个搜索功能,您说呢?
另:我做梦的时候一共梦到三篇文章,您别不信,这是真的,分别是: 《多叉树结合JavaScript树形控件实现无限级树形菜单(一种构建多级有序树形结构JSON(或XML)数据源的方法)》 《(原创)新概念智能树形菜单--利用加权多叉树结合JavaScript树形控件实现》 《(原创)统计分析系统中的树形结构统计报表--利用加权多叉树实现》
其实这篇文章是个过渡,文中提到的“加权多叉树”的概念是在为第三篇文章做铺垫!我觉得第三篇文章也很有价值,欢迎阅读,谢谢。 另:我这三篇文章是经过十几次修改才逐渐完善的,请尊重我的劳动成果,多谢了。
这三篇文章都会陆续发到iteye上,有意见可以提,别骂人!
文章中提到的新概念“加权多叉树”,到底能够在哪些地方有应用,到底有多大价值,我也不知道,我只是觉得很有价值,所以发表在网上,供大家参考,我不想让肉烂在锅里。 各位,对我这篇文章发表回复请到【java综合】板块,那里有一篇帖子,叫《【分享原创文章,推动技术创新】“多叉树”和“加权多叉树”在软件开发中的应用(讨论帖,欢迎各位高手踊跃发表评论)》,专门集中讨论这个话题的,多谢了,链接是:http://www.iteye.com/topic/1124411
#######################################################################################
|
|
返回顶楼 | |
发表时间:2012-04-17
不想说什么,不过这个搜索功能确实还行哈。
|
|
返回顶楼 | |