POJ2003 多叉树模拟

题意

首先输入是一个头结点;

之后存在三个操作:

  • [existing member] hires [new member]
  • fire [existing member]
  • print

分别表示插入、删除、打印。

删除一个节点会让他的第一个子节点往上移顶替他位置,并对这个子节点也进行重复的删除操作(最左边的一系列节点依次上移)。

每个节点前需要打印N个+表示N层,最后以------------------------------------------------------------结束

思路

没啥思路可言,就是模拟而已,但是对Java来说是一种挑战。特别注意删除操作,每次删除一个节点要同时考虑他的父、子节点,而当改变一个节点位置要把他周围受影响的节点信息也要变,仔细就好。

注意

开始用标准输入输出报超时,后来去搜了Java快速输入输出得到一个输入:StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

但是并不如hasNext()好用,只有先存储输入,依旧爆运行时错误。

后来输入继续用Scanner,输出换成了PrintWriter成功AC,虽然时间还是很多但好在AC了,以后就都用PrintWriter吧。

最后说两点:

  • 定义ArrayList等容器,new xxx<>()时,<>中要填写参数,不然会爆编译错误。
  • PrintWriter的println是把输出放入缓冲区,最后要flush()才能取出。

代码

/*
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

*/

import java.io.*;
import java.util.*;

/**
 * @Author Yuri
 * @Date 2020/11/24 15:49
 * @Version 1.0
 * @Description:
 */

class Tree {
    String name;
    Integer dad;
    ArrayList<Integer> children;

    public Tree(String name, Integer dad) {
        this.name = name;
        this.dad = dad;
        children = new ArrayList<Integer>();
    }

    @Override
    public String toString() {
        return "Tree{" +
                "name='" + name + '\'' +
                ", dad=" + dad +
                '}';
    }
}

public class Main {
    //    static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
    static Scanner in = new Scanner(System.in);
    static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
    static String a, b, temp;
    static ArrayList<Tree> treeArrayList = new ArrayList<Tree>();
    static Integer index = 0;
    static Map<String, Integer> map = new HashMap<String, Integer>();
    static Tree headNode = null;
    static Integer pos = 0;
    static ArrayList<String> putIn = new ArrayList<String>();


    public static void hires() throws IOException {
//        in.nextToken();
        temp = putIn.get(pos++);
//        in.nextToken();
        b = putIn.get(pos++);
        treeArrayList.add(new Tree(b, map.get(a))); //增加节点
        treeArrayList.get(map.get(a)).children.add(index); //添加到父节点的孩子数组
        map.put(b, index++); //添加映射
    }

    public static void fire() throws IOException {
//        in.nextToken();
        b = putIn.get(pos++);
        Integer selfIndex = map.get(b);
        Integer dadIndex = treeArrayList.get(selfIndex).dad;

        if (!treeArrayList.get(selfIndex).children.isEmpty()) { //判断孩子是否为空
            int childIndex = treeArrayList.get(selfIndex).children.get(0);
            update(childIndex); //要递归到叶子节点,才能开始改变自己的孩子节点为父节点的孩子节点
            treeArrayList.get(childIndex).dad = dadIndex; //将子节点的父节点改为自己的父节点--->孙子指向爷爷,因为爸爸没了
            if (dadIndex != -1) {  //如果自己存在父节点,就要把父节点中的孩子数组中的自己的改为子节点
                int ix = treeArrayList.get(dadIndex).children.indexOf(selfIndex);
                treeArrayList.get(dadIndex).children.set(ix, childIndex);
            } else { //不存在那么子节点就变为头结点了
                headNode = treeArrayList.get(childIndex);
            }
        } else if (dadIndex != -1) { //如果自己不存在子节点但存在父节点 则直接在父节点中移除
            int ix = treeArrayList.get(dadIndex).children.indexOf(selfIndex);
            treeArrayList.get(dadIndex).children.remove(ix);
        } else { //子,父节点都不存在就表示没节点了
            headNode = null;
        }
    }

    public static void update(Integer selfIndex) {
        Integer dadIndex = treeArrayList.get(selfIndex).dad;
        ArrayList<Integer> children = treeArrayList.get(dadIndex).children;
        if (!treeArrayList.get(selfIndex).children.isEmpty()) {
            int childIndex = treeArrayList.get(selfIndex).children.get(0);
            update(childIndex);
            children.set(0, childIndex); //把父节点数组中第一个值(本身是自己)换为自己的孩子
        } else {
            children.remove(selfIndex); //没有孩子就直接移除自己
        }
        treeArrayList.get(selfIndex).children = children;
        for (int i = 0; i < children.size(); i++) {
            treeArrayList.get(children.get(i)).dad = selfIndex; //自己变成了曾经兄弟姐妹的父节点
        }
    }

    public static void print(Tree node, int floor) {
        for (int i = 0; i < node.children.size(); i++) {
            Tree tree = treeArrayList.get(node.children.get(i));
            for (int j = 0; j < floor; j++) {
                out.printf("+");
            }
            out.println(tree.name);
            print(tree, floor + 1); //每次递归进一层
        }
    }

    public static String op[] = new String[]{"hires", "fire", "print"};

    public static void main(String[] args) throws IOException {
        //本来是为了StreamTokenizer类准备的
        while (in.hasNext()) {
            putIn.add(in.next());
        }
        temp = putIn.get(pos++);
        headNode = new Tree(temp, -1); //头结点
        treeArrayList.add(headNode);
        map.put(temp, index++); //记录String和Index的映射
        while (pos < putIn.size()) {
            temp = putIn.get(pos++);
            if (temp.equals("fire")) {
                fire();
            } else if (temp.equals("print")) {
                if (headNode != null) { //要考虑节点被删完的情况
                    out.println(headNode.name);
                    print(headNode, 1);
                }
                out.println("------------------------------------------------------------");
            } else {
                a = temp;
                hires();
            }
        }
        out.flush();//输出
    }
}
posted @ 2020-11-26 10:18  AkimotoAkira  阅读(85)  评论(0编辑  收藏  举报