Java 数据结构基础 简单树的实现与实例##
树与二叉树的实现差不多,二叉树类变量里面有两个子节点,树的类里面有一个树类的链表,下面看具体的实现
public class MuxTree {
private MyString data;
public MuxTree parent;
public List<MuxTree> children;
//...
}
//这里的MyString是我自己定义的类,用于解决后面的问题,也可以用模板类代替
//该类有父节点,和子节点的集合。
构造函数:
public MuxTree(){
this.data = new MyString("");
this.parent = null;
this.children = new LinkedList<>();
}
//该构造函数生成一个无子树的节点,因为涉及到后面题目的解决所以父节点的内容为空
public MuxTree(String data, MuxTree parent){
this.data = new MyString(data);
this.parent = parent;
this.children = new LinkedList<>();
}
//该构造函数返回一个带有父节点,有数据的节点,用于添加节点函数用
具体函数:
public MuxTree insert(String data, MuxTree parent){
MuxTree child = new MuxTree(data, parent);
parent.children.add(child);
return child;
}
//向一个父节点添加一个子节点,该子节点由一个String生成
public MuxTree insert(MyString myString){
String s = myString.getParent().getString();
MuxTree parent = this.search(new MyString(s));
if(parent != null)
return this.insert(myString.getString(), parent);
else return null;
}
//现在就是为了解决后面题目所创建的添加函数,根据要插入节点的数据信息查找父节点并插入
//(search();函数在后面实现,它返回是否查找成功,成功返回查找对象,失败返回null)
//就像"D:\新建文件夹"是在"D:\"文件夹下,也就是说要找到自己的父节点并插入到相应位置,找不到就直接返回null
删除节点:
public MuxTree delete(MuxTree parent, int index){
return parent.children.remove(index);
}
public boolean delete(MuxTree parent, MuxTree child){
return parent.children.remove(child);
}
//树类的子节点是List实现的,所以删除有两个方法
//一个根据下标索引返回被删除的对象,一个根据对象返回是否删除成功
查找函数实现:
public MuxTree search(MyString myString){
Queue<MuxTree> queue = new LinkedList<>();
MuxTree p = this;
String s = p.data.getString();
while(p != null){
if(p.data.getString().equals(myString.getString())){
return p;
}
if(p.children != null){
for(MuxTree temp : p.children){
((LinkedList<MuxTree>) queue).add(temp);
}
}
p = queue.poll();
}
return null;
}
//这是典型的广度优先遍历,由一个队列实现。
//从父节点开始便利,先判断是否与自己传入的参数相等,相等返回
//否则开始便利:将父节点add()进队列,如果该父节点有子节点
//就将父节点poll(),并将所有子节点add()进队列,之后执行上两步
//若找不到就直接返回null
前序便利:
public void preOrder(MuxTree temp){
if(temp == null)
return;
MuxTree p = temp;
int parentNum = 0;
if(p.parent != null){
while(p.parent != null){
parentNum += p.data.getString().length();
p = p.parent;
}
for(int i = 0; i < parentNum; i++){
System.out.print(" ");
}
System.out.println(temp.data);
}
for(MuxTree index : temp.children){
preOrder(index);
}
return ;
}
//这是深度优先遍历法,由传入的节点开始
//这里题目有一个要求,就是父节点和子节点有一个若干个空格距离的限制
//所以我才在类里引入了父节点,由当前节点开始,判断父节点是否为空
//不为空,则获取父节点的数据长度,重复上一步
剩下的函数:
public void preOrder(){
this.preOrder(this);
return ;
}
@Override
public String toString() {
return "MuxTree{" +
"data=" + data +
'}';
}
下面来看一个例题:
键盘键入一个String, 按要求输出
例:
输入:
“CC BB AA BB03 AA02 AA03 AA01 AA0303 CC01 AA0304 DD01”
输出:
(这里看到,DD01没有被打印出来,因为DD01没有合适的父目录)
思路:这是一个典型的树的应用题。首先,我们要判断插入的节点是否有自己的合适父节点,没有,则丢弃,有,则对应插入。用户键入的数据没有规律,如果“AA01” 在“AA”之前,则在遍历数组插入时,就会出现先遍历“AA01”,发现没有父节点,因为这时还没有插入“AA”,但之后“AA”是会被正常插入的,所以会出现露插入的情况。
那么怎么解决这个问题?
我们可以对用户输入的String转化成为String数组(split()),再经行排序。
排序的大小标准是什么?
首先,字符串长度较短的应该较小,因为一定是前面插入完了,后面才能正常插入。接着,相同长度,应该返回正常的String的比较大小。String的大小比较函数我们不能重载,所以我们新定义一个类实现Comparable接口,就是前面的MyString:
public class MyString implements Comparable<MyString> {
private String string;
public MyString(String s){
this.string = s;
}
public String getString(){
return this.string;
}
public MyString getParent(){
String parent = this.string.substring(0, string.length()-2);
return new MyString(parent);
}
//因为我们要根据自己的数据,找到自己的合适父节点。
//由题目的意思,自己的数据抹去后两位,就是自己的父节点的数据,所以根据数据返回父节点
@Override
public int compareTo(MyString o) {
if(this.string.length() > o.string.length())
return 1;
else if(this.string.length() < o.string.length())
return -1;
else {
if(this.string.compareTo(o.string) > 0)
return 1;
else if(this.string.compareTo(o.string) < 0)
return -1;
else return 0;
}
}
@Override
public String toString() {
return string;
}
}
接着就是主函数了:
为节约时间,我直接用定义好的MyString生成树,并遍历:
public static void main(String[] args) {
MyString[] myStrings = new MyString[]{new MyString("CC"),
new MyString("BB"), new MyString("AA"), new MyString("BB03"),
new MyString("AA02"), new MyString("AA03"),
new MyString("AA01"), new MyString("AA0303"), new MyString("CC01"),
new MyString("AA0304"), new MyString("DD01")};
Arrays.sort(myStrings);
MuxTree muxTree = new MuxTree();
for (MyString myString : myStrings) {
muxTree.insert(myString);
}
muxTree.preOrder();
}
至于键盘键入数据,将String转换成String[]就不写了。
源码链接:
Github:https://github.com/cjf354075714/MuxTree.git