Tree结构菜单遍历及path生成方法

今天是17年的倒数第二天,明天就是跨年夜,17年末尾给小伙伴们分享一个小工具。
平时我们经常会遇到这样的需求,一个对象数组,对象中的每一项通过id和pid形成父子关系,我们需要取出某一个id节点下的所以子节点形成一个又父子关系层级的新对象;或者取出某一个id节点在整个节点树中的path路径,即父子层级上的关系,类似于面包屑导航。可能说的比较乱,还是用数据说话:

我们有这么一个data数组,可能是spa的路由管理;

var data = [
        {id:122,pid:12,name:"模块2/子模块2"},
        {id:11,pid:1,name:"模块1"},
        {id:12,pid:1,name:"模块2"},
        {id:13,pid:1,name:"模块3"},
        {id:1,pid:0,name:"根节点"},
        {id:111,pid:11,name:"模块1/子模块1"},
        {id:121,pid:12,name:"模块2/子模块1"}
    ]; 

这个时候需要得到每个页面的面包屑导航和该路由下的自路由信息

//属性菜单生成逻辑demo
    function Tree(arr){
        if(arr && arr instanceof Array){
            this._arr = arr;
            this._arrMap = {};
            //首先将节点信息遍历一遍,放到一个Map里,便于后续检索
            for(var i=0; i<arr.length; i++){
                var n = arr[i];
                if(n && n.id){
                    this._arrMap[n.id] = n;
                }
            }
            //建立父子关系
            for(var i=0; i<arr.length; i++){
                var n = arr[i];
                var p = this._arrMap[n.pid];
                if(p){
                    p.children = p.children || [];
                    p.children.push(n);
                }
            }

        }
    }

    Tree.prototype={
        constructor:Tree,
        //获得以某一个节点信息,其中已经包含了所有树状关系。本节点的子菜单在节点的children属性里
        getNode : function(rootid){
            return this._arrMap[rootid];
        },
        //获得某一个节点从根点到此节点的路径
        getPath : function(id){
            var _a = [];
            //当前节点
            var _currentNode = this._arrMap[id];
            while (_currentNode){
                _a.unshift(_currentNode);
                _currentNode = this._arrMap[_currentNode.pid];
            }
            return _a;
        }

    }

    //测试

    var data = [
        {id:122,pid:12,name:"模块2/子模块2"},
        {id:11,pid:1,name:"模块1"},
        {id:12,pid:1,name:"模块2"},
        {id:13,pid:1,name:"模块3"},
        {id:1,pid:0,name:"根节点"},
        {id:111,pid:11,name:"模块1/子模块1"},
        {id:121,pid:12,name:"模块2/子模块1"}
    ];

    var tree = new Tree(data);

    console.info(tree);

    //获得节点信息
    console.info(tree.getNode(1));
    console.info(tree.getNode(12));
    console.info(tree.getNode(14));

    //获得节点路径
    console.info(tree.getPath(1));
    console.info(tree.getPath(121));
    console.info(tree.getPath(1211));

到这里,相信小伙伴们也已经从我拙劣的文字里明白该怎么用了吧,希望能帮到大家。

created by 子非鱼

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉树可以用链式存储结构或者数组存储结构来实现。下面是链式存储结构的实现: ```c typedef struct Node { int data; struct Node *leftChild; struct Node *rightChild; } Node; // 前序遍 void preOrder(Node *root) { if (root != NULL) { printf("%d ", root->data); preOrder(root->leftChild); preOrder(root->rightChild); } } // 中序遍 void inOrder(Node *root) { if (root != NULL) { inOrder(root->leftChild); printf("%d ", root->data); inOrder(root->rightChild); } } // 后序遍 void postOrder(Node *root) { if (root != NULL) { postOrder(root->leftChild); postOrder(root->rightChild); printf("%d ", root->data); } } ``` 其中,前序遍先访问根节点,再访问左子树,最后访问右子树;中序遍先访问左子树,再访问根节点,最后访问右子树;后序遍先访问左子树,再访问右子树,最后访问根节点。 如果使用数组存储结构,可以按照如下方式实现: ```c #define MAX_SIZE 100 int tree[MAX_SIZE]; // 前序遍 void preOrder(int root, int size) { if (root < size) { printf("%d ", tree[root]); preOrder(root * 2 + 1, size); preOrder(root * 2 + 2, size); } } // 中序遍 void inOrder(int root, int size) { if (root < size) { inOrder(root * 2 + 1, size); printf("%d ", tree[root]); inOrder(root * 2 + 2, size); } } // 后序遍 void postOrder(int root, int size) { if (root < size) { postOrder(root * 2 + 1, size); postOrder(root * 2 + 2, size); printf("%d ", tree[root]); } } ``` 数组实现中,左子节点的下标为 root * 2 + 1,右子节点的下标为 root * 2 + 2。下标从 0 开始,因此如果树的节点数为 n,数组的大小应该为 2^n - 1。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值