简单的JAVA多叉树问题实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了简单的JAVA多叉树问题实现相关的知识,希望对你有一定的参考价值。

请编程实现:

一颗多叉树有M层,每个节点的子节点数不定,现要求打印该多叉树的第N层的全部节点。自定义数据结构。

不写代码说说思路也可以,谢谢!

TreeNode.java
/*
 * Copyright Walker Studio
 * All Rights Reserved.
 * 
 * 文件名称: TreeNode.java
 * 摘 要:
 * 作 者: Walker
 * 创建时间: 2013-03-19
 */
package com.walker.commons.data.model;

/**
 * 树节点
 * 
 * @author Walker
 * @version 1.0.0.0
 */
public class TreeNode 

/** 节点Id*/
private String nodeId;
/** 父节点Id*/
private String parentId;
/** 文本内容*/
private String text;

/**
 * 构造函数
 * 
 * @param nodeId 节点Id
 */
public TreeNode(String nodeId)

this.nodeId = nodeId;


/**
 * 构造函数
 * 
 * @param nodeId 节点Id
 * @param parentId 父节点Id
 */
public TreeNode(String nodeId, String parentId)

this.nodeId = nodeId;
this.parentId = parentId;


public String getNodeId() 
return nodeId;


public void setNodeId(String nodeId) 
this.nodeId = nodeId;


public String getParentId() 
return parentId;


public void setParentId(String parentId) 
this.parentId = parentId;


public String getText() 
return text;


public void setText(String text) 
this.text = text;





ManyTreeNode.java

/*
 * Copyright Walker Studio
 * All Rights Reserved.
 * 
 * 文件名称: ManyTreeNode.java
 * 摘 要:
 * 作 者: Walker
 * 创建时间: 2013-03-19
 */
package com.walker.commons.data.model;

import java.util.ArrayList;
import java.util.List;

/**
 * 多叉树节点
 *
 * @author Walker
 * @verion 1.0.0.0
 */
public class ManyTreeNode 

/** 树节点*/
private TreeNode data;
/** 子树集合*/
private List<ManyTreeNode> childList;

/**
 * 构造函数
 * 
 * @param data 树节点
 */
public ManyTreeNode(TreeNode data)

this.data = data;
this.childList = new ArrayList<ManyTreeNode>();


/**
 * 构造函数
 * 
 * @param data 树节点
 * @param childList 子树集合
 */
public ManyTreeNode(TreeNode data, List<ManyTreeNode> childList)

this.data = data;
this.childList = childList;


public TreeNode getData() 
return data;


public void setData(TreeNode data) 
this.data = data;


public List<ManyTreeNode> getChildList() 
return childList;


public void setChildList(List<ManyTreeNode> childList) 
this.childList = childList;





ManyNodeTree.java

/*
 * Copyright Walker Studio
 * All Rights Reserved.
 * 
 * 文件名称: ManyNodeTree.java
 * 摘 要:
 * 作 者: Walker
 * 创建时间: 2013-03-19
 */
package com.walker.commons.data.model;

import java.util.ArrayList;
import java.util.List;

/**
 * 多叉树生成、遍历工具
 * 
 * @author Walker
 * @version 1.0.0.0
 */
public class ManyNodeTree 

/** 树根*/
private ManyTreeNode root;

/**
 * 构造函数
 */
public ManyNodeTree()

root = new ManyTreeNode(new TreeNode("root"));


/**
 * 生成一颗多叉树,根节点为root
 * 
 * @param treeNodes 生成多叉树的节点集合
 * @return ManyNodeTree
 */
public ManyNodeTree createTree(List<TreeNode> treeNodes)

if(treeNodes == null || treeNodes.size() < 0)
return null;

ManyNodeTree manyNodeTree =  new ManyNodeTree();

//将所有节点添加到多叉树中
for(TreeNode treeNode : treeNodes)

if(treeNode.getParentId().equals("root"))

//向根添加一个节点
manyNodeTree.getRoot().getChildList().add(new ManyTreeNode(treeNode));

else

addChild(manyNodeTree.getRoot(), treeNode);



return manyNodeTree;


/**
 * 向指定多叉树节点添加子节点
 * 
 * @param manyTreeNode 多叉树节点
 * @param child 节点
 */
public void addChild(ManyTreeNode manyTreeNode, TreeNode child)

for(ManyTreeNode item : manyTreeNode.getChildList())

if(item.getData().getNodeId().equals(child.getParentId()))

//找到对应的父亲
item.getChildList().add(new ManyTreeNode(child));
break;

else

if(item.getChildList() != null && item.getChildList().size() > 0)

addChild(item, child);





/**
 * 遍历多叉树 
 * 
 * @param manyTreeNode 多叉树节点
 * @return 
 */
public String iteratorTree(ManyTreeNode manyTreeNode)

StringBuilder buffer = new StringBuilder();
buffer.append("\\n");

if(manyTreeNode != null) 

for (ManyTreeNode index : manyTreeNode.getChildList()) 

buffer.append(index.getData().getNodeId()+ ",");

if (index.getChildList() != null && index.getChildList().size() > 0 ) 

buffer.append(iteratorTree(index));




buffer.append("\\n");

return buffer.toString();


public ManyTreeNode getRoot() 
return root;


public void setRoot(ManyTreeNode root) 
this.root = root;


public static void main(String[] args)

List<TreeNode> treeNodes = new ArrayList<TreeNode>();
treeNodes.add(new TreeNode("系统权限管理", "root"));
treeNodes.add(new TreeNode("用户管理", "系统权限管理"));
treeNodes.add(new TreeNode("角色管理", "系统权限管理"));
treeNodes.add(new TreeNode("组管理", "系统权限管理"));
treeNodes.add(new TreeNode("用户菜单管理", "系统权限管理"));
treeNodes.add(new TreeNode("角色菜单管理", "系统权限管理"));
treeNodes.add(new TreeNode("用户权限管理", "系统权限管理"));
treeNodes.add(new TreeNode("站内信", "root"));
treeNodes.add(new TreeNode("写信", "站内信"));
treeNodes.add(new TreeNode("收信", "站内信"));
treeNodes.add(new TreeNode("草稿", "站内信"));

ManyNodeTree tree = new ManyNodeTree();

System.out.println(tree.iteratorTree(tree.createTree(treeNodes).getRoot()));


参考技术A XX?XX?XX?XX?XX?XX?
hui追问

好玩啊?傻X

javascript多叉树的实现

1、创造一个节点

数据是以节点的形式存储的:

1
2
3
4
5
6
7
class Node {
  constructor(data) {
    this.data = data;
    this.parent = null;
    this.children = [];
  }
}
2、创造树

树用来连接节点,就像真实世界树的主干一样,延伸着很多分支

1
2
3
4
5
class MultiwayTree {
  constructor() {
    this._root = null;
  }
}
3、添加一个节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function add(data, toData, traversal) {
  let node = new Node(data)
  // 第一次添加到根节点
  // 返回值为this,便于链式添加节点
  if (this._root === null) {
    this._root = node;
    return this;
  }
  let parent = null,
    callback = function(node) {
      if (node.data === toData) {
        parent = node;
        return true;
      }
    };
  // 根据遍历方法查找父节点(遍历方法后面会讲到),然后把节点添加到父节点
  // 的children数组里
  // 查找方法contains后面会讲到
  this.contains(callback, traversal);
  if (parent) {
    parent.children.push(node);
    node.parent = parent;
    return this;
  } else {
    throw new Error(‘Cannot add node to a non-existent parent.‘);
  }
}
4、深度优先遍历

深度优先会尽量先从子节点查找,子节点查找完再从兄弟节点查找,适合数据深度比较大的情况,如文件目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function traverseDF(callback) {
  let stack = [], found = false;
  stack.unshift(this._root);
  let currentNode = stack.shift();
  while(!found && currentNode) {
    // 根据回调函数返回值决定是否在找到第一个后继续查找
    found = callback(currentNode) === true ? true : false;
    if (!found) {
      // 每次把子节点置于堆栈最前头,下次查找就会先查找子节点
      stack.unshift(...currentNode.children);
      currentNode = stack.shift();
    }
  }
}
5、广度优先遍历

广度优先遍历会优先查找兄弟节点,一层层往下找,适合子项较多情况,如公司岗位级别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function traverseBF(callback) {
  let queue = [], found = false;
  queue.push(this._root);
  let currentNode = queue.shift();
  while(!found && currentNode) {
    // 根据回调函数返回值决定是否在找到第一个后继续查找
    found = callback(currentNode) === true ? true : false;
    if (!found) {
      // 每次把子节点置于队列最后,下次查找就会先查找兄弟节点
      queue.push(...currentNode.children)
      currentNode = queue.shift();
    }
  }
}
6、包含节点

1
2
3
function contains(callback, traversal) {
  traversal.call(this, callback);
}
回调函数算法可自己根据情况实现,灵活度较高

7、移除节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 返回被移除的节点
function remove(data, fromData, traversal) {
  let parent = null,
    childToRemove = null,
    callback = function(node) {
      if (node.data === fromData) {
        parent = node;
        return true;
      }
    };
  this.contains(callback, traversal);
  if (parent) {
    let index = this._findIndex(parent.children, data);
    if (index < 0) {
      throw new Error(‘Node to remove does not exist.‘);
    } else {
      childToRemove = parent.children.splice(index, 1);
    }
  } else {
    throw new Error(‘Parent does not exist.‘);
  }
  return childToRemove;
}
_findIndex实现:

1
2
3
4
5
6
7
8
9
10
function _findIndex(arr, data) {
  let index = -1;
  for (let i = 0, len = arr.length; i < len; i++) {
    if (arr[i].data === data) {
      index = i;
      break;
    }
  }
  return index;
}
完整算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
class Node {
  constructor(data) {
    this.data = data;
    this.parent = null;
    this.children = [];
  }
}
class MultiwayTree {
  constructor() {
    this._root = null;
  }
  //深度优先遍历
  traverseDF(callback) {
    let stack = [], found = false;
    stack.unshift(this._root);
    let currentNode = stack.shift();
    while(!found && currentNode) {
      found = callback(currentNode) === true ? true : false;
      if (!found) {
        stack.unshift(...currentNode.children);
        currentNode = stack.shift();
      }
    }
  }
  //广度优先遍历
  traverseBF(callback) {
    let queue = [], found = false;
    queue.push(this._root);
    let currentNode = queue.shift();
    while(!found && currentNode) {
      found = callback(currentNode) === true ? true : false;
      if (!found) {
        queue.push(...currentNode.children)
        currentNode = queue.shift();
      }
    }
  }
  contains(callback, traversal) {
    traversal.call(this, callback);
  }
  add(data, toData, traversal) {
    let node = new Node(data)
    if (this._root === null) {
      this._root = node;
      return this;
    }
    let parent = null,
      callback = function(node) {
        if (node.data === toData) {
          parent = node;
          return true;
        }
      };
    this.contains(callback, traversal);
    if (parent) {
      parent.children.push(node);
      node.parent = parent;
      return this;
    } else {
      throw new Error(‘Cannot add node to a non-existent parent.‘);
    }
  }
  remove(data, fromData, traversal) {
    let parent = null,
      childToRemove = null,
      callback = function(node) {
        if (node.data === fromData) {
          parent = node;
          return true;
        }
      };
    this.contains(callback, traversal);
    if (parent) {
      let index = this._findIndex(parent.children, data);
      if (index < 0) {
        throw new Error(‘Node to remove does not exist.‘);
      } else {
        childToRemove = parent.children.splice(index, 1);
      }
    } else {
      throw new Error(‘Parent does not exist.‘);
    }
    return childToRemove;
  }
  _findIndex(arr, data) {
    let index = -1;
    for (let i = 0, len = arr.length; i < len; i++) {
      if (arr[i].data === data) {
        index = i;
        break;
      }
    }
    return index;
  }
}
控制台测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
var tree = new MultiwayTree();
tree.add(‘a‘)
  .add(‘b‘, ‘a‘, tree.traverseBF)
  .add(‘c‘, ‘a‘, tree.traverseBF)
  .add(‘d‘, ‘a‘, tree.traverseBF)
  .add(‘e‘, ‘b‘, tree.traverseBF)
  .add(‘f‘, ‘b‘, tree.traverseBF)
  .add(‘g‘, ‘c‘, tree.traverseBF)
  .add(‘h‘, ‘c‘, tree.traverseBF)
  .add(‘i‘, ‘d‘, tree.traverseBF);
console.group(‘traverseDF‘);
tree.traverseDF(function(node) {
  console.log(node.data);
});
console.groupEnd(‘traverseDF‘);
console.group(‘traverseBF‘);
tree.traverseBF(function(node) {
  console.log(node.data);
});
console.groupEnd(‘traverseBF‘);
// 深度优先查找
console.group(‘contains1‘);
tree.contains(function(node) {
  console.log(node.data);
  if (node.data === ‘f‘) {
    return true;
  }
}, tree.traverseDF);
console.groupEnd(‘contains1‘)
// 广度优先查找
console.group(‘contains2‘);
tree.contains(function(node) {
  console.log(node.data);
  if (node.data === ‘f‘) {
    return true;
  }
}, tree.traverseBF);
console.groupEnd(‘contains2‘);
tree.remove(‘g‘, ‘c‘, tree.traverseBF);

 

以上是关于简单的JAVA多叉树问题实现的主要内容,如果未能解决你的问题,请参考以下文章

[DataStructure]非线性数据结构之哈希表二叉树及多叉树 Java 代码实现

数组实现多叉树

一种多叉树的实现,提供树形结构打印,树转表输出等功能

python实现 多叉树 寻找最短路径

javascript多叉树的实现

javascript多叉树的实现