欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-05-10 11:28:05
一、实验内容1.问题菜单是一对多的树型结构。如下图是早期TurboC2.0的菜单结构:根据给定的菜单数据文件 ①读菜单数据文件,建立如上图的树的实例;②用宽度遍历,输出菜单标题验证。③请看菜单项目.ppt后完成。...

一、实验内容

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图

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

2.设计思路

①存储结构MenuItem、MenuAnalyseStru

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

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

②文件读取工具类MyFileReader

为了符合设计模式中的单一职责原则,将文件读取、计算前置空格和处理存储等操作进行抽象成单独的类,降低程序的复杂度。
利用加载器中的方法获取该程序的运行路径,在利用该路径得到相应的文件输入流,逐行读入返回String列表。
【Java作业】树形结构(组合)

③正则表达式封装类RegexUtil

此类为工具类,主要根据传入的正则表达式字符串返回匹配到的第一个字符串(即前置空格)
主要是封装了相应操作(利用jdk中的Pattern和Matcher类读取我们所需要的字符串)
【Java作业】树形结构(组合)

④处理类Handler

此类主要功能是对从文件读取到的字符串list进行处理,将其存储在我们设定好的存储结构MenuItem、MenuAnalyseStru中。
具体思路如下:
【Java作业】树形结构(组合)

⑤测试类

之前将各个操作抽象成单独类,所以测试类只需按次序调用相应的类中的方法即可
【Java作业】树形结构(组合)

三、代码详情

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();
        }
    }
}

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

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

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

五、收获心得

主要花时间的地方在于handler将数组读取进我们设计好的数据结构中,那部分逻辑有点绕,一开始想复杂了,后来发现其实可以挺简单的。
还有就是如何读取前置空格,那时候我只知道可以用正则表达式去做,至于怎么做还是有点模糊的(之前没怎么遇到就没什么印象了),后来去翻了别人的博客才渐渐掌握。
除此之外,文件路径的读取也是一个难点,这个路径一般只能用绝对路径(在maven项目中,把资源文件放在resouces目录下),用相对路径会报文件未找到的异常,所以如何根据程序运行环境去读取文件的绝对路径也是一个难点。

本文地址:https://blog.csdn.net/qq_46101869/article/details/109647885