【Java作业】树形结构(组合)

简介: 【Java作业】树形结构(组合)

一、实验内容

1.问题

菜单是一对多的树型结构。如下图是早期TurboC2.0的菜单结构:


根据给定的菜单数据文件:


File
Load F3
Pick Alt-F3
New
Save F2
Write to
Diretory
Change Dir
Os Shell
Quit Alx-X Edit Run
Program reset Ctrl-F2
Go To cursor F4
Trace into F7
Step over F8
User Screen Alt-F5 Compile
Compile to OBJ
Make EXE file
Link EXE file
Build all
Primary C file
Get info Project
Project name
Break make on
Auto dependencies
Clear project
Remove messages Break/Watch
Add watch Ctrl-F7
Delete watch
Edit watch
Remove all watches
Toggle breakpoint Ctrl-F8
Clear all breakpoints
View next breakpoint Debug
Evalute Ctrl-F4
Call stack Ctrl-F3
Find function
Refresh display
Display swapping
Source debugging Options
Compiler
Model
Defines
Code generation
Optimization
Source
Errors
Names
Linker
Map file
Initialize segments
Default library
Warn duplicate symbols
Stack warning
Case-sensitive link
Environment
Message Tracking
Keep messages
Config auto save
Edit auto save
Backup files
Tab Size
Zoomed windows
Screen size
Directories
Include directories
Library directories
Output directories
Turbo C directory
Pick file name
Current pick file
Arguments
Save options
Retrieve options


3.要求

①读菜单数据文件,建立如上图的树的实例;

②用宽度遍历,输出菜单标题验证。

③请看菜单项目.ppt后完成。

注:该资料只有一个页面是跟Java有关,部分是按C写的材料,请结合Java语言来完成。


二、程序设计

1.UML图


w2.png

2.设计思路

①存储结构MenuItem、MenuAnalyseStru

MenuIterm类用来存储菜单选项,其内有私有属性menuTitle(存储菜单选项内容)和私有属性menu(存储子节点的list),对外提供相应的get,set方法,同时提供print方法,用来递归打印自身以及子节点


w1.png

MenuAnalyseStru类用来存储每层的菜单信息,其内用属性preBlankCount(存储前导空格数)和list(存储改成的菜单选项),对外提供相应的get,set方法,同时提供add方法,用来添加该层的菜单选项


q5.png

②文件读取工具类MyFileReader

为了符合设计模式中的单一职责原则,将文件读取、计算前置空格和处理存储等操作进行抽象成单独的类,降低程序的复杂度。

利用加载器中的方法获取该程序的运行路径,在利用该路径得到相应的文件输入流,逐行读入返回String列表。


q4.png

③正则表达式封装类RegexUtil

此类为工具类,主要根据传入的正则表达式字符串返回匹配到的第一个字符串(即前置空格)

主要是封装了相应操作(利用jdk中的Pattern和Matcher类读取我们所需要的字符串)


q3.png

④处理类Handler

此类主要功能是对从文件读取到的字符串list进行处理,将其存储在我们设定好的存储结构MenuItem、MenuAnalyseStru中。

具体思路如下:


q2.png

⑤测试类

之前将各个操作抽象成单独类,所以测试类只需按次序调用相应的类中的方法即可


q1.png

三、代码详情

1.菜单项MenuItem类

package com.dreamchaser.work4;
import java.util.ArrayList;
import java.util.List;
/**
 * 存储每项信息
 */
class MenuItem{
    /**
     * 菜单内容
     */
    private String menuTitle;
    /**
     * 子菜单
     */
    private List<MenuItem> menu=new ArrayList<>(3);
    public MenuItem(String menuTitle) {
        this.menuTitle = menuTitle;
    }
    /**
     * 打印自身及以下结点
     */
    public void print(){
        System.out.println(menuTitle);
        /**
         * 递归打印子节点
         */
        for (MenuItem menuItem:menu){
            menuItem.print();
        }
    }
    public String getMenuTitle() {
        return menuTitle;
    }
    public void setMenuTitle(String menuTitle) {
        menuTitle = menuTitle;
    }
    public List<MenuItem> getMenu() {
        return menu;
    }
    public void setMenu(List<MenuItem> menu) {
        this.menu = menu;
    }
}


2.菜单层MenuAnalyseStru类

package com.dreamchaser.work4;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
/**
 * 存储每层信息
 */
public class MenuAnalyseStru {
    /**
     * 前导空格数
     */
    private Integer preBlankCount=0;
    /**
     * 同层的菜单项
     */
    private LinkedList<MenuItem> list=new LinkedList<>();
    public MenuAnalyseStru(Integer preBlankCount) {
        this.preBlankCount = preBlankCount;
    }
    /**
     * 添加一个菜单项
     * @param menuItem
     */
    public void add(MenuItem menuItem){
        list.add(menuItem);
    }
    public Integer getPreBlankCount() {
        return preBlankCount;
    }
    public LinkedList<MenuItem> getList() {
        return list;
    }
}


3.文件读取工具类MyFileReader

package com.dreamchaser.work4;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
 * 文件读取类
 */
public class MyFileReader {
    /**
     * 读取项目文件,以行字符串list返回
     * @param name
     * @return
     */
    public static List<String> readFile(String name){
        List<String> list=new ArrayList<>(20);
        //获取文件加载时的绝对路径
        String filePath=MyFileReader.class.getClassLoader().getResource(name).getFile();
        File file=new File(filePath);
        if (file.exists()&&file.isFile()){
            BufferedReader reader=null;
            try {
                reader=new BufferedReader(new FileReader(file));
                String line=null;
//                //前置空格
                while ((line=reader.readLine())!=null){
                    list.add(line);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    //最后将输入流关闭
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return list;
    }
}

4.正则表达式封装类RegexUtil

package com.dreamchaser.work4;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexUtil {
    /**
     * 返回单个字符串,若匹配到多个的话就返回第一个,方法与getSubUtil一样
     * @param soap
     * @param rgex
     * @return
     */
    public static String getSubUtilSimple(String soap,String rgex){
        Pattern pattern = Pattern.compile(rgex);// 匹配的模式
        Matcher m = pattern.matcher(soap);
        int i=0;
        while(m.find()){
            return m.group(0);
        }
        return "";
    }
}

5.处理类Handler

package com.dreamchaser.work4;
import java.util.ArrayList;
import java.util.List;
/**
 * 用于处理读取文件后的list,将其处理成根目录返回
 */
public class Handler {
    public static List<MenuAnalyseStru> handle(List<String> strings){
        List<MenuAnalyseStru> menuAnalyseStrus=new ArrayList<>(5);
        /**
         * 表示层数
         */
        Integer layer=0;
        /**
         * 前置空格数
         */
        Integer pre=0;
        for (String s:strings){
            //通过正则表达式匹配相应的前置空格,然后统计长度赋值给pre
            pre=RegexUtil.getSubUtilSimple(s,"^ +").length();
            //创建相应的菜单选项
            MenuItem menuItem=new MenuItem(s);
            if (menuAnalyseStrus.size()==pre/4){
                //当前层如果没有创建对象则先创建对象
                MenuAnalyseStru menuAnalyseStru=new MenuAnalyseStru(pre);
                menuAnalyseStru.add(menuItem);
                menuAnalyseStrus.add(menuAnalyseStru);
            }else {
                menuAnalyseStrus.get(pre/4).add(menuItem);
            }
            //如果不是第一层的话,则要把子节点加入父节点中
            if (pre!=0){
                //获取上一层的最后一个,即父节点
                MenuItem father=menuAnalyseStrus.get(pre/4-1).getList().getLast();
                //再将其加入父节点的子节点中
                father.getMenu().add(menuItem);
            }
        }
        return menuAnalyseStrus;
    }
}

6.测试类Test

package com.dreamchaser.work4;
import java.util.List;
/**
 * 测试类
 */
public class Test {
    public static void main(String[] args) {
        //读取文件
        List<String> list=MyFileReader.readFile("TurboC.txt");
        //处理数据
        List<MenuAnalyseStru> strus=Handler.handle(list);
        //打印输出,只需获取顶层的菜单选项遍历即可
        for (MenuItem m:strus.get(0).getList()){
            m.print();
        }
    }
}

四、运行结果(测试结果)



q2.png

q1.png

五、收获心得

主要花时间的地方在于handler将数组读取进我们设计好的数据结构中,那部分逻辑有点绕,一开始想复杂了,后来发现其实可以挺简单的。

还有就是如何读取前置空格,那时候我只知道可以用正则表达式去做,至于怎么做还是有点模糊的(之前没怎么遇到就没什么印象了),后来去翻了别人的博客才渐渐掌握。

除此之外,文件路径的读取也是一个难点,这个路径一般只能用绝对路径(在maven项目中,把资源文件放在resouces目录下),用相对路径会报文件未找到的异常,所以如何根据程序运行环境去读取文件的绝对路径也是一个难点。


相关文章
|
4月前
|
Java
【java作业3——类的定义】复数,连续子数组,最大素数
🍒 1 定义复数类 作业内容: 定义一个复数类Complex(数据成员:a,b表示复数a+bi).并配以合适的方法完成复数对象的生成、复数的运算(加、减、乘除),然后做一个主类测试它。
43 0
|
4月前
|
Java 网络架构
Java面向对象开发作业
Java面向对象开发作业
68 0
|
10月前
|
存储 Java 关系型数据库
0018Java程序设计-springboot智慧环卫养管作业平台1
0018Java程序设计-springboot智慧环卫养管作业平台
69 0
|
5天前
|
Java 数据处理
技术分享:高效与灵活并存——Java版通用树形结构转换工具的实现与应用
在软件开发中,树形结构的数据表现形式无处不在,从文件系统的目录树到组织架构的部门树,再到各类产品的分类结构。处理这些具有层级关系的数据时,将其转换为树形结构以便展示和操作显得尤为重要。Java作为一门成熟的编程语言,虽然提供了强大的集合框架,但并未直接提供树形结构转换的内置工具。因此,开发一个高效且灵活的通用树形结构转换工具成为许多项目中的必备需求。
14 2
|
15天前
|
Java
用JAVA架建List集合为树形结构的代码方法
这段代码定义了一个表示树形结构的 `Node` 类和一个用于构建树形结构的 `TreeController`。`Node` 类包含基本属性如 `id`、`pid`、`name` 和 `type`,以及子节点列表 `children`。`TreeController` 包含初始化节点列表并将其转换为树形结构的方法。通过过滤和分组操作实现树形结构的构建。详情可见:[代码示例链接1](http://www.zidongmutanji.com/zsjx/43551.html),[代码效果参考链接2](https://www.257342.com/sitemap/post.html)。
25 5
|
10月前
|
SQL Java 定位技术
0018Java程序设计-springboot智慧环卫养管作业平台2
0018Java程序设计-springboot智慧环卫养管作业平台
41 0
|
3月前
|
算法 前端开发 Java
探讨Java中递归构建树形结构的算法
探讨Java中递归构建树形结构的算法
33 1
|
3月前
|
小程序 Java 数据库
基于Java作业管理系统设计和实现(源码+LW+调试文档+讲解等)
基于Java作业管理系统设计和实现(源码+LW+调试文档+讲解等)
|
3月前
|
Java
JAVA构建List集合为树形结构的方法和代码
JAVA构建List集合为树形结构的方法和代码
19 0
|
4月前
|
JavaScript Java 测试技术
基于Java的作业管理系统的设计与实现(源码+lw+部署文档+讲解等)
基于Java的作业管理系统的设计与实现(源码+lw+部署文档+讲解等)