<数据结构 课程设计> 文件目录结构显示(Java 版)

  • 问题描述
    要求在给出Unix或windows下目录和文件信息的前提下,编程实现将其排列成一棵具有一定缩进的树。

  • 基本要求
    在给定的磁盘目录下,参照下表分层缩进输出文件目录结构

|_*/usr
      |_*mark
      |      |_hw.c
      |      |_*course
                    |_aa.txt
      |_*alex
             |_hw.c

本课程设计,我写了2个文件,一个是Main.java,一个是TreeNode.java。当然,用Java是因为File,等等类相当好用,方便快捷。输出子目录树,我用了孩子链式存储方式,先形成一棵树,然后再层次遍历它,看了一下其他大神写的多叉树的类,自己理解了一下相应的点,并且在适当的地方用到了。。
由于题目难度比较水,我又多增添了两个功能(水的点),下面贴出来,供大家参考。有不对的地方欢迎大家批评指正。
这不是重写方法后的代码,因为这是数据结构的课设,后面重写了栈和队列,,仅供参考。谢谢~
下面是Main.java

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;

/**
 * @author 计161 CJY in School of Computer and Control Engineering in YTU,
 *         数据结构课程设计 Made on 2017-12-15 14:45:38, 
 *         Project's name: Directory's Tree
 */
public class Main {
    static Scanner in = new Scanner(System.in);
    public static final int MAX_Node_Num = 0x3f3f3f;
    public static int filecount = 0;
    public static int directorycount = 0;
    public static int Cnt = 0;
    public static int depth = 0;
    public static int flag = 1;
    public static String ex = "|_";
    public static Stack<String> stack = new Stack<String>();
    public static Queue<String> queue = new LinkedList<String>();
    public static String x = "*";
    static TreeNode[] tn = new TreeNode[MAX_Node_Num];
    public static int TreeNodeNum_Start = 1;
    public static int tmp = 0;
    public static int cnt = 0; // 计数要输出缩进个数

    /**
     * @param x 文件夹前缀
     * @param Cnt 记录当前节点的子节点个数
     * @param Max_Node_Num 最大树节点个数
     * @param filecount 记录文件个数
     * @param directorycount 记录文件夹个数
     * @param depth 初始化深度
     * @param stack 用栈记录当前文件夹内的的文件等
     * @param ex 树形表示前缀
     * @param tmp 临时表示TreeNodeNum
     * @param currentDepth 表示当前文件树深度
     * @param TreeNodeNum_Start 表示起始Node节点
     * @param queue 用队列记录兄弟目录
     *
     */
    /**
     * 
     * 首先输入一个路径(看做一个节点),然后判断是否存在该路径,
     * 如果存在的话,选择要调用的方法,当选择4的时候,将flag置0,结束程序
     */
    public static void main(String[] args) throws java.lang.NullPointerException, IOException {
        // TODO Auto-generated method stub
        tn[0] = new TreeNode();
        System.out.println("please enter a Path Name:");
        String root = new String(in.nextLine());
        File path = new File(root);
        if (path.exists()) {
            while (true) {
                if (flag == 0)
                    break;
                goto_methods(choice(), path);
            }
        } else
            System.out.println("This path doesn't exist!");
        in.close();
        System.out.println("程序结束,欢迎使用");
    }

    /**
     * @param choice  为choice方法返回的整型值
     * @param path 输入的访问路径
     * @throws IOException
     * 
     * 通过调用choice方法返回选项值,确定调用的方法
     */
    public static void goto_methods(int choice, File path) throws IOException {
        // TODO Auto-generated method stub
        switch (choice) {
        case 1:
            print_subTree(path);
            break;
        case 2:
            print_parentTree(path);
            break;
        case 3:
            print_brotherTree(path);
            break;
        default:
            flag = 0;
            break;
        }
    }

    /**
     * @return  返回的整型值作为goto_methods方法的参数
     */
    private static int choice() {
        // TODO Auto-generated method stub
        String n ;
        int s ;
        while (true) {
            System.out.println("-----------------美丽的分割线------------------");
            System.out.println("|Make a Choice :                              |");
            System.out.println("|1.Print its directory's subtrees.            |");
            System.out.println("|2.Print its parent directory tree.           |");
            System.out.println("|3.Print its brother tree set.                |");  
            System.out.println("|4.Exit.                                      |");
            System.out.println("-----------------美丽的分割线------------------");

            n = in.next();
            s = n.charAt(0)-'0';
            if(s >= 1 && s <=4)
                break;
            else
                System.out.println("Your Choice is illegal, plz Enter again.");
        }
        return s;
    }

    /**
     * @param path  手动输入的路径
     * @throws IOException
     * 
     * 输出子目录树(Tree)
     * 
     * 该方法通过先判断是否存在以及是否是一个目录,随后调用build_Tree方法,建立一颗文件的多叉搜索树
     */
    public static void print_subTree(File path) throws IOException {
        // TODO Auto-generated method stub
        if (path.exists()) {
            if (path.isDirectory()) {
                build_Tree(path, depth);
            } else if (path.isFile()) {
                System.out.println(x + ex + path.getName());
                filecount++;
            } else
                System.out.println("Error!");
        } else
            System.out.println("This Path doesn't exist!");
        System.out.println(x + path.getName());
        for (int i = 0; i < filecount + directorycount; i++) {
            tn[i].traverse();
            if (depth < tn[i].getDepth())
                depth = tn[i].getDepth();
        }
        depth++;
        System.out.println("该目录下一共有:" + filecount + "个文件," + directorycount + "个目录, 目录深度为:" + depth);
    }

    /**
     * @param path 手动输入的路径
     * 
     * 输出当前路径的父路径(Stack & Tree)
     * 
     * 通过获取路径的父路径,将父路径存入栈中,再以此为路径,求得父路径 存入栈,直至其父路径为null,随后生成一颗树(也可以不这么做),
     * 出栈栈顶元素,作为树的根节点,然后继续出栈,将其后面的元素作为根节点的子节点。
     */
    private static void print_parentTree(File path) {
        // TODO Auto-generated method stub
        int cnt = 0;
        int tmp = 0;
        File prepath = path;
        tn[0] = new TreeNode();
        tn[0].setNodeName(path.getName());
        while (path.getParent() != null){
            stack.push(path.getParent());
            if(path.getParent() != null)
                path = new File(path.getParent());
        }
//      判断是否栈空,并将栈中元素纳入树,出栈
        while (!stack.isEmpty()) {
            tmp = cnt;
            tn[++cnt] = new TreeNode();
            tn[cnt].setNodeName(x + stack.peek());
            tn[cnt].setDepth(tmp);
            tn[tmp].addChildNode(tn[cnt]);
            stack.pop();
        }
//      层次遍历各个节点
        for (int i = 0; i < cnt; i++)
            tn[i].traverse();
        for(int i = 0 ; i < cnt ; i++)
            System.out.print("    ");
        if(prepath.isDirectory())
            System.out.println(ex + x +prepath.getPath());
        else
            System.out.println(ex + prepath.getPath());
        System.out.println("该目录的父目录共有:" + cnt +"个" );
    }

    /**
     * @param path 手动输入的路径
     * 
     * 输出该节点的兄弟节点(Queue)
     * 
     * 先获取当前路径的父节点,然后通过父节点获取其所有的子节点,并加入队列,获取完当前所有子节点之后,出队所有元素并输出结果。
     */
    private static void print_brotherTree(File path) {
        // TODO Auto-generated method stub
        if (path.getParent() != null) {
            File newpath = new File(path.getParent());
            String[] str = newpath.list();
            for (int i = 0; i < str.length; i++) {
                File thispath = new File(str[i]);
                if(thispath.getName().equals(path.getName()))
                    continue;
                if (thispath.isDirectory()) {
                    queue.offer(x + thispath.getName());
                } else {
                    queue.offer(thispath.getName());
                }
            }
            System.out.println("This Path's Brother Tree:");
//          当队不为空时,输出队首元素
            while (queue.peek() != null) {
                if (queue.peek() != path.getName()){
                    File tmpFile = new File(queue.peek());
                    if(tmpFile.isDirectory())
                        System.out.println(ex + x + queue.peek());
                    else
                        System.out.println(ex + queue.peek());
                }
                queue.poll();
            }
        } else
            System.out.println("This path doesn't have Brother Tree!");
    }

    /**
     * @param path  手动输入的路径
     * @param depth 构建树的深度(层数)
     * @throws IOException
     * 
     * 构建一颗多叉树(Tree)
     * 
     * 首先将输入的path路径作为树的根节点,获取path路径下的所有文件列表,将其路径下的文件和文件夹作为该根节点的子节点,
     * 记录该节点的节点下标,该节点的父节点下标,以及该节点的深度(层数),
     * 如果子节点为目录,则将该节点作为临时的根节点,同时从该节点进行遍历,获取该节点下的文件列表,将其作为目录的子节点,
     * 同时,记录作为目录的子节点的个数。
     * 直到所有的节点遍历完毕,当前建立好了一颗多叉搜索树。
     * 遍历时,通过遍历每个节点,看是否有子节点列表,有的话则将其输出,并继续查找是否有子节点
     * 遍历时,通过访问度不为0的节点来遍历文件目录,不遍历叶子结点。
     */
    public static void build_Tree(File path, int depth) throws IOException {
        // TODO Auto-generated method stub
        String[] arr = path.list();
        int currentDepth = depth + 1;
        if (depth == 0) {
            tn[0].setNodeName(x + path.getName());
            tn[0].setDepth(tmp);
        } else {
            tn[TreeNodeNum_Start] = new TreeNode();
            tn[TreeNodeNum_Start].setNodeName(x + path.getName());
            tn[TreeNodeNum_Start].setDepth(depth);
            tn[TreeNodeNum_Start].setSelfId(TreeNodeNum_Start);
            tn[TreeNodeNum_Start].setParentId(tmp);
            tn[tmp].addChildNode(tn[TreeNodeNum_Start]);
            tn[tmp].setCnt(Cnt++);
            tmp = TreeNodeNum_Start;
            Cnt = 0;
            TreeNodeNum_Start++;
        }
        for (int i = 0; i < arr.length; i++) {
            String str = arr[i];
            File file = new File(path.getPath(), str);
            if (file.isDirectory()) {
                directorycount++;
                build_Tree(file.getCanonicalFile(), currentDepth);// 递归调用
            } else {
                tn[TreeNodeNum_Start] = new TreeNode();
                tn[TreeNodeNum_Start].setNodeName(file.getName());
                tn[TreeNodeNum_Start].setDepth(currentDepth);
                tn[TreeNodeNum_Start].setSelfId(TreeNodeNum_Start);
                tn[TreeNodeNum_Start].setParentId(tmp);
                tn[tmp].addChildNode(tn[TreeNodeNum_Start]);
                tn[tmp].setCnt(Cnt++);
                TreeNodeNum_Start++;
                filecount++;
            }
        }
    }
}

下面是TreeNode.Java
这个类是构建多叉树的,看了一下这个博客。然后加了点功能,保留了他的功能,感谢这位大佬,这是他的博文地址http://ylq365.iteye.com/blog/980627

import java.util.List;  
import java.util.ArrayList;  
import java.io.Serializable;  

/**
 * @author 计161 CJY in School of Computer and Control Engineering in YTU,
 *         数据结构课程设计 Made on 2017-12-15 14:50:21, 
 *         Project's name: Directory's Tree
 *
 */
public class TreeNode implements Serializable {  
    private int parentId;  
    private int selfId;
    private int depth = 0;
    private String space = "    ";
    private String ex = "_";
    private String ex1 = "|";
    private int cnt = 0;
    protected String nodeName;   
    protected TreeNode parentNode;  
    protected List<TreeNode> childList;
    public TreeNode() {  
        initChildList();  
    }  

    public TreeNode(TreeNode parentNode) {  
        this.getParentNode();  
        initChildList();  
    }  

    public boolean isLeaf() {  
        if (childList == null) {  
            return true;  
        } else {  
            if (childList.isEmpty()) {  
                return true;  
            } else {  
                return false;  
            }  
        }  
    }  

    /* 插入一个child节点到当前节点中 */  
    public void addChildNode(TreeNode treeNode) {  
        initChildList();  
        childList.add(treeNode);  
    }  

    public void initChildList() {  
        if (childList == null)  
            childList = new ArrayList<TreeNode>();  
    }  

    /* 返回当前节点的父辈节点集合 */  
    public List<TreeNode> getElders() {  
        List<TreeNode> elderList = new ArrayList<TreeNode>();  
        TreeNode parentNode = this.getParentNode();  
        if (parentNode == null) {  
            return elderList;  
        } else {  
            elderList.add(parentNode);  
            elderList.addAll(parentNode.getElders());  
            return elderList;  
        }  
    }  

    /* 返回当前节点的晚辈集合 */  
    public List<TreeNode> getJuniors() {  
        List<TreeNode> juniorList = new ArrayList<TreeNode>();  
        List<TreeNode> childList = this.getChildList();  
        if (childList == null) {  
            return juniorList;  
        } else {  
            int childNumber = childList.size();  
            for (int i = 0; i < childNumber; i++) {  
                TreeNode junior = childList.get(i);  
                juniorList.add(junior);  
                juniorList.addAll(junior.getJuniors());  
            }  
            return juniorList;  
        }  
    }  

    /* 返回当前节点的孩子集合 */  
    public List<TreeNode> getChildList() {  
        return childList;  
    }  

    /* 删除节点和它下面的晚辈 */  
    public void deleteNode() {  
        TreeNode parentNode = this.getParentNode();  
        int id = this.getSelfId();    
        if (parentNode != null) {  
            parentNode.deleteChildNode(id);  
        }  
    }  

    /* 删除当前节点的某个子节点 */      
    public void deleteChildNode(int childId) {  
        List<TreeNode> childList = this.getChildList();  
        int childNumber = childList.size();  
        for (int i = 0; i < childNumber; i++) {  
            TreeNode child = childList.get(i);  
            if (child.getSelfId() == childId) {  
                childList.remove(i);  
                return;  
            }  
        }  
    }  

    /* 动态的插入一个新的节点到当前树中 */  
    public boolean insertJuniorNode(TreeNode treeNode) {  
        int juniorParentId = treeNode.getParentId();  
        if (this.parentId == juniorParentId) {  
            addChildNode(treeNode);  
            return true;  
        } else {  
            List<TreeNode> childList = this.getChildList();  
            int childNumber = childList.size();  
            boolean insertFlag;  
            for (int i = 0; i < childNumber; i++) {  
                TreeNode childNode = childList.get(i);  
                insertFlag = childNode.insertJuniorNode(treeNode);  
                if (insertFlag == true)  
                    return true;  
            }  
            return false;  
        }  
    }  

    /* 找到一颗树中某个节点 */  
    public TreeNode findTreeNodeById(int id) {  
        if (this.selfId == id)  
            return this;  
        if (childList.isEmpty() || childList == null) {  
            return null;  
        } else {  
            int childNumber = childList.size();  
            for (int i = 0; i < childNumber; i++) {  
                TreeNode child = childList.get(i);  
                TreeNode resultNode = child.findTreeNodeById(id);  
                if (resultNode != null) {  
                    return resultNode;  
                }  
            }  
            return null;  
        }  
    }  

    /* 遍历一棵树,层次遍历,以及输出节点数*/  
    public void traverse() {
        if (selfId < 0)  
            return;  
        if (childList == null || childList.isEmpty())  
            return;  
        int childNumber = childList.size();  
        for (int i = 0; i < childNumber; i++) {  
            TreeNode child = childList.get(i);
            for(int j = 0 ;j < child.depth; j++)
                System.out.print(space+ex1);
            System.out.println(ex+child.getNodeName());
        }  
    } 

    public int getParentId() {  
        return parentId;  
    }  
    public void setDepth(int depth){
        this.depth = depth;
    }
    public int getDepth(){
        return depth;
    }
    public void setParentId(int parentId) {  
        this.parentId = parentId;  
    }  

    public int getSelfId() {  
        return selfId;  
    }  

    public void setSelfId(int selfId) {  
        this.selfId = selfId;  
    }  

    public TreeNode getParentNode() {  
        return parentNode;  
    }  

    public void setParentNode(TreeNode parentNode) {  
        this.parentNode = parentNode;  
    }  

    public String getNodeName() {  
        return nodeName;  
    }  
    public void setNodeName(String nodeName) {  
        this.nodeName = nodeName;  
    }  

    public void setCnt(int cnt){
        this.cnt = cnt;
    }
    public int getCnt(){
        return cnt;
    }
}

好了就是这些,具体的步骤我写在注释里了,欢迎提意见~我也是菜鸡一枚。
最后再次感谢大佬的博文,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值