如何将平面数据结构显示为层次数据结构(Java)?
我最近在一次求职考试中遇到了这个问题 假设您有一个平面数据结构,如下所示:如何将平面数据结构显示为层次数据结构(Java)?,java,data-structures,Java,Data Structures,我最近在一次求职考试中遇到了这个问题 假设您有一个平面数据结构,如下所示: **Category** **Name** **Parent** 1 electronics 0 2 Television 1 3 21inch 2 4 23inch
**Category** **Name** **Parent**
1 electronics 0
2 Television 1
3 21inch 2
4 23inch 2
5 LCD display 2
6 player 1
7 mp3player 6
8 vcd player 6
9 dvd player 6
10 hd quality 8
现在,从上面的平面数据结构中,我们想展示类似于下面的层次树结构的内容
-Electronics
| -Television
| | -21 inch
| | -23 inch
| | -lcd display
| -Player
| | -mp3player
| | -vcdplayer
| | | -HD display
| | -DVD player
然后,如果我向数组中添加另一个条目,如:
11 Test 3
然后它应该在21英寸下方显示Test
条目
所以对于这类事情,我目前使用的是ArrayList
,能够遍历到第二级,但无法遍历到第三级。那么,做这件事的最佳方式是什么呢
谢谢
编辑:
我被要求只使用基于DOS的Java应用程序来构建这个概念 你可以从Swing中得到灵感
EDIT当我这么说的时候,我的意思是你可以使用一个类来实现一个类似的接口;请注意,您甚至可以直接使用这个接口,因为Swing是标准JRE的一部分,并且在任何标准Java可用的地方都可以使用
此外,因为它是一个接口(而不是类),所以它只是一种构造调用的方法。因此,您可以轻松地在基于控制台的应用程序中使用它。使用ArrayList作为输入,需要使用递归方法以分层/树表示形式打印所有节点
如果您没有使用递归,那么这可能是您无法达到高于您提到的第二个级别的原因
有关递归的一些链接:
以下是一些示例代码,使用递归将它们按层次结构列出。Item类有一个子类列表。诀窍是向正确的父级添加任何新的子级。以下是我为此创建的方法:
public Item getItemWithParent(int parentID){
Item result = null;
if(this.categoryID == parentID){
result = this;
} else {
for(Item nextChild : children){
result = nextChild.getItemWithParent(parentID);
if(result != null){
break;
}
}
}
return result;
}
也许有一种更有效的方法,但这是可行的
然后,如果要向层次结构添加新项目,请执行以下操作:
public void addItem(int categoryID, String name, int parentID) {
Item parentItem = findParent(parentID);
parentItem.addChild(new Item(categoryID, name, parentID));
}
private Item findParent(int parentID) {
return rootNode.getItemWithParent(parentID);
}
public String toStringHierarchy(int tabLevel){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < tabLevel; i++){
builder.append("\t");
}
builder.append("-" + name);
builder.append("\n");
for(Item nextChild : children){
builder.append(nextChild.toStringHierarchy(tabLevel + 1));
}
return builder.toString();
}
public class Node
{
// My name
public String name;
// My first child. Null if no children.
public Node child;
// The next child after me under the same parent.
public Node sibling;
// The top node in the tree.
public static Node adam;
// Add first node to tree
public Node(String name)
{
this.name=name;
this.child=null;
this.sibling=null;
adam=this;
}
// Add a non-Adam node to the tree.
public Node(String name, Node parent)
{
// Copy my name. Easy part.
this.name=name;
// Make me the first child of my parent. The previous first child becomes
// my sibling. If the previous first child was null, fine, now my sibling is null.
// Note this means that children always add to the front. If this is undesirable,
// we could make this section a little more complicated to impose the desired
// order.
this.sibling=parent.child;
parent.child=this;
// As a new node, I have no children.
this.child=null;
}
// Print the current node and all nodes below it.
void printFamily(int level)
{
// You might want a fancier print function than this, like indenting or
// whatever, but I'm just trying to illustrate the principle.
System.out.println(level+" "+name);
// First process children, then process siblings.
if (child!=null)
child.printFamiliy(level+1);
if (sibling!=null)
sibling.printFamily(level);
}
// Print all nodes starting with adam
static void printFamily()
{
adam.printFamily(1);
}
// Find a node with a given name. Must traverse the tree.
public static Node findByName(String name)
{
return adam.findByName(name);
}
private Node findByNameFromHere(String name)
{
if (this.name.equals(name))
return this;
if (child!=null)
{
Node found=child.findByNameFromHere(name);
if (found!=null)
return found;
}
if (sibling!=null)
{
Node found=sibling.findByNameFromHere(name);
if (found!=null)
return found;
}
return null;
}
// Now we can add by name
public Node(String name, String parentName)
{
super(name, findByName(parentName));
}
}
对于实际显示,我只需传入一个“tab level”,它表示要在多大程度上进行tab,然后为每个子级递增它,如下所示:
public void addItem(int categoryID, String name, int parentID) {
Item parentItem = findParent(parentID);
parentItem.addChild(new Item(categoryID, name, parentID));
}
private Item findParent(int parentID) {
return rootNode.getItemWithParent(parentID);
}
public String toStringHierarchy(int tabLevel){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < tabLevel; i++){
builder.append("\t");
}
builder.append("-" + name);
builder.append("\n");
for(Item nextChild : children){
builder.append(nextChild.toStringHierarchy(tabLevel + 1));
}
return builder.toString();
}
public class Node
{
// My name
public String name;
// My first child. Null if no children.
public Node child;
// The next child after me under the same parent.
public Node sibling;
// The top node in the tree.
public static Node adam;
// Add first node to tree
public Node(String name)
{
this.name=name;
this.child=null;
this.sibling=null;
adam=this;
}
// Add a non-Adam node to the tree.
public Node(String name, Node parent)
{
// Copy my name. Easy part.
this.name=name;
// Make me the first child of my parent. The previous first child becomes
// my sibling. If the previous first child was null, fine, now my sibling is null.
// Note this means that children always add to the front. If this is undesirable,
// we could make this section a little more complicated to impose the desired
// order.
this.sibling=parent.child;
parent.child=this;
// As a new node, I have no children.
this.child=null;
}
// Print the current node and all nodes below it.
void printFamily(int level)
{
// You might want a fancier print function than this, like indenting or
// whatever, but I'm just trying to illustrate the principle.
System.out.println(level+" "+name);
// First process children, then process siblings.
if (child!=null)
child.printFamiliy(level+1);
if (sibling!=null)
sibling.printFamily(level);
}
// Print all nodes starting with adam
static void printFamily()
{
adam.printFamily(1);
}
// Find a node with a given name. Must traverse the tree.
public static Node findByName(String name)
{
return adam.findByName(name);
}
private Node findByNameFromHere(String name)
{
if (this.name.equals(name))
return this;
if (child!=null)
{
Node found=child.findByNameFromHere(name);
if (found!=null)
return found;
}
if (sibling!=null)
{
Node found=sibling.findByNameFromHere(name);
if (found!=null)
return found;
}
return null;
}
// Now we can add by name
public Node(String name, String parentName)
{
super(name, findByName(parentName));
}
}
为了提高效率,我会创建如下内容:
public void addItem(int categoryID, String name, int parentID) {
Item parentItem = findParent(parentID);
parentItem.addChild(new Item(categoryID, name, parentID));
}
private Item findParent(int parentID) {
return rootNode.getItemWithParent(parentID);
}
public String toStringHierarchy(int tabLevel){
StringBuilder builder = new StringBuilder();
for(int i = 0; i < tabLevel; i++){
builder.append("\t");
}
builder.append("-" + name);
builder.append("\n");
for(Item nextChild : children){
builder.append(nextChild.toStringHierarchy(tabLevel + 1));
}
return builder.toString();
}
public class Node
{
// My name
public String name;
// My first child. Null if no children.
public Node child;
// The next child after me under the same parent.
public Node sibling;
// The top node in the tree.
public static Node adam;
// Add first node to tree
public Node(String name)
{
this.name=name;
this.child=null;
this.sibling=null;
adam=this;
}
// Add a non-Adam node to the tree.
public Node(String name, Node parent)
{
// Copy my name. Easy part.
this.name=name;
// Make me the first child of my parent. The previous first child becomes
// my sibling. If the previous first child was null, fine, now my sibling is null.
// Note this means that children always add to the front. If this is undesirable,
// we could make this section a little more complicated to impose the desired
// order.
this.sibling=parent.child;
parent.child=this;
// As a new node, I have no children.
this.child=null;
}
// Print the current node and all nodes below it.
void printFamily(int level)
{
// You might want a fancier print function than this, like indenting or
// whatever, but I'm just trying to illustrate the principle.
System.out.println(level+" "+name);
// First process children, then process siblings.
if (child!=null)
child.printFamiliy(level+1);
if (sibling!=null)
sibling.printFamily(level);
}
// Print all nodes starting with adam
static void printFamily()
{
adam.printFamily(1);
}
// Find a node with a given name. Must traverse the tree.
public static Node findByName(String name)
{
return adam.findByName(name);
}
private Node findByNameFromHere(String name)
{
if (this.name.equals(name))
return this;
if (child!=null)
{
Node found=child.findByNameFromHere(name);
if (found!=null)
return found;
}
if (sibling!=null)
{
Node found=sibling.findByNameFromHere(name);
if (found!=null)
return found;
}
return null;
}
// Now we can add by name
public Node(String name, String parentName)
{
super(name, findByName(parentName));
}
}
通常的免责声明:这段代码是从我的头上掉下来的,完全没有经过测试
如果我是为一个真正的应用程序这样做的,我会包括错误检查和毫无疑问的各种外围设备。公共类文件阅读器{
public class FileReader {
Map<Integer, Employee> employees;
Employee topEmployee;
class Employee {
int id;
int mgrId;
String empName;
List<Employee> subordinates;
public Employee(String id, String mgrid, String empName) {
try {
int empId = Integer.parseInt(id);
int mgrId = 0;
if (!"Null".equals(mgrid)) {
mgrId = Integer.parseInt(mgrid);
}
this.id = empId;
this.mgrId = mgrId;
this.empName = empName;
} catch (Exception e) {
System.out.println("Unable to create Employee as the data is " + id + " " + mgrid + " " + empName);
}
}
List<Employee> getSubordinates() {
return subordinates;
}
void setSubordinates(List<Employee> subordinates) {
this.subordinates = subordinates;
}
int getId() {
return id;
}
void setId(int id) {
this.id = id;
}
int getMgrId() {
return mgrId;
}
}
public static void main(String[] args) throws IOException {
FileReader thisClass = new FileReader();
thisClass.process();
}
private void process() throws IOException {
employees = new HashMap<Integer, Employee>();
readDataAndCreateEmployees();
buildHierarchy(topEmployee);
printSubOrdinates(topEmployee, tabLevel);
}
private void readDataAndCreateEmployees() throws IOException {
BufferedReader reader = new BufferedReader(new java.io.FileReader("src/main/java/com/springapp/mvc/input.txt"));
String line = reader.readLine();
while (line != null) {
Employee employee = createEmployee(line);
employees.put(employee.getId(), employee);
if (employee.getMgrId() == 0) {
topEmployee = employee;
}
line = reader.readLine();
}
}
int tabLevel = 0;
private void printSubOrdinates(Employee topEmployee, int tabLevel) {
for (int i = 0; i < tabLevel; i++) {
System.out.print("\t");
}
System.out.println("-" + topEmployee.empName);
List<Employee> subordinates = topEmployee.getSubordinates();
System.out.print(" ");
for (Employee e : subordinates) {
printSubOrdinates(e, tabLevel+1);
}
}
public List<Employee> findAllEmployeesByMgrId(int mgrid) {
List<Employee> sameMgrEmployees = new ArrayList<Employee>();
for (Employee e : employees.values()) {
if (e.getMgrId() == mgrid) {
sameMgrEmployees.add(e);
}
}
return sameMgrEmployees;
}
private void buildHierarchy(Employee topEmployee) {
Employee employee = topEmployee;
List<Employee> employees1 = findAllEmployeesByMgrId(employee.getId());
employee.setSubordinates(employees1);
if (employees1.size() == 0) {
return;
}
for (Employee e : employees1) {
buildHierarchy(e);
}
}
private Employee createEmployee(String line) {
String[] values = line.split(" ");
Employee employee = null;
try {
if (values.length > 1) {
employee = new Employee(values[0], values[2], values[1]);
}
} catch (Exception e) {
System.out.println("Unable to create Employee as the data is " + values);
}
return employee;
}
}
地图员工;
员工至上员工;
班级员工{
int-id;
总经理;
字符串名称;
列出下属;
公共雇员(字符串id、字符串mgrid、字符串empName){
试一试{
int empId=Integer.parseInt(id);
int-mgrId=0;
如果(!“Null”。等于(mgrid)){
mgrId=Integer.parseInt(mgrId);
}
this.id=empId;
this.mgrId=mgrId;
this.empName=empName;
}捕获(例外e){
System.out.println(“无法创建员工,因为数据为”+id+“”+mgrid+“”+empName);
}
}
列出下属(){
回报下属;
}
作废集合坐标(列出下级){
这个。下属=下属;
}
int getId(){
返回id;
}
void setId(int id){
this.id=id;
}
int getMgrId(){
返回mgrId;
}
}
公共静态void main(字符串[]args)引发IOException{
FileReader thisClass=新建FileReader();
thisClass.process();
}
私有void进程()引发IOException{
employees=newhashmap();
readDataAndCreateEmployees();
构建层次结构(topEmployee);
打印下属(topEmployee,tabLevel);
}
私有void readDataAndCreateEmployees()引发IOException{
BufferedReader=new BufferedReader(new java.io.FileReader(“src/main/java/com/springapp/mvc/input.txt”);
字符串行=reader.readLine();
while(行!=null){
Employee=createEmployee(行);
employee.put(employee.getId(),employee);
if(employee.getMgrId()==0){
topEmployee=员工;
}
line=reader.readLine();
}
}
int tabLevel=0;
私人下属(员工topEmployee,int tabLevel){
for(int i=0;i1){
员工=新员工(值[0]、值[2]、值[1]);
}
}捕获(例外e){
System.out.println(“无法创建员工,因为数据为”+值);
}
返回员工;
}
}
如果你能放一些代码片段,我就能理解你的代码,那就太好了