之前也练习了Stack和Queue,之后就开始练习我认为数据结构中最难的东西——树。
可能是一颗无序树吧,代码如下:
package dataStructureSamples;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.security.auth.Destroyable;
/**
* 这可能是棵树,而且也不是二叉树。
* @author Miko
*
* @param <T> 界定树中存储数据的类型(有这个必要吗)。
*/
public class Tree<T> implements Destroyable{
/**
* 节点的数据。
* @see #getAllDataOfTreeByAfterOrder()
* @see #getAllDataOfTreeByPreOrder()
* @see #visitAllByAfterOrder(List)
* @see #visitAllByPreOrder(List)
*/
private T data;
/**
* 树的子节点集。
* @see #addNode(Tree)
* @see #removeNode(Tree)
* @see #getNodeByIndex(int)
*/
private List<Tree<T>> childs;
/**
* 父节点。
*/
private Tree<T> parent;
/**
* 构造一颗空树。
*/
public Tree() {
data = null;
childs = new ArrayList<Tree<T>>();
parent = null;
}
/**
* 构造一个叶子节点。
* @param data 节点数据
*/
public Tree(T data) {
this.data = data;
childs = new ArrayList<Tree<T>>();
this.parent = null;
}
/**
* 获取子树。
* @return
*/
public List<Tree<T>> getChilds(){
return this.childs;
}
/**
* 获取树的数据。
* @return data
*/
public T getData() {
return data;
}
/**
* 设定树的数据,如果是空树将会成为叶子节点。
* @param data 树的数据
*/
public void setData(T data) {
this.data = data;
}
/**
* 获取父节点。
* @return 父节点。
*/
public Tree<T> getParent() {
return parent;
}
/**
* 设置父节点。
* @param parent
*/
public void setParent(Tree<T> parent) {
this.parent = parent;
}
/**
* 为一些树的根节点添加父节点,这个节点将成为新树的根节点。
* @param data 节点数据
* @param childs 子节点
*/
public Tree(T data, List<Tree<T>> childs) {
this.data = data;
this.childs = childs;
for (Tree<T> tree : childs) {
tree.setParent(this);
}
}
/**
* 获取当前树节点的度。
* @return 节点的度
* @see #childs
*/
public int getNodeDegree() {
return childs.size();
}
/**
* 判断是否是空树。
* @return 是否空树。
* @see #size()
*/
public boolean isEmptyTree() {
return size() == 0;
}
/**
* 判断是否是叶子节点。
* @return 是否是叶子
* @see #getNodeDegree()
*/
public boolean isLeaf() {
return getNodeDegree() == 0 && data != null;
}
/**
* 获取树的深度。<br>
* @return 树的深度
* @see #childs
*/
public int getDepth() {
if(isEmptyTree()) {
return 0;
}else if(isLeaf()) {
return 1;
}else {
int degree = getNodeDegree();
int depth[] = new int[degree];
int i = 0;
for(Tree<T> tree : childs) {
depth[i] = tree.getDepth();
i++;
}
Arrays.sort(depth);
return depth[degree - 1] + 1;
}
}
/**
* 获取节点总数。
* @return 节点总数
*/
public int size() {
int size = 0;
if(isLeaf()) {
size = 1;
}else {
for (Tree<T> tree : childs) {
size += tree.size();
}
if(data != null)
size++;
}
return size;
}
public int getLeafCount() {
int count = 0;
if(!isLeaf()) {
for (Tree<T> tree : childs) {
count += tree.getLeafCount();
}
}else {
count = 1;
}
return count;
}
/**
* 获取树的度。
* @return 树的度
* @see #childs
*/
public int getDegree() {
if(isEmptyTree()) {
return 0;
}else if(isLeaf()) {
return 1;
}else {
int countOfNodes = childs.size();
int degrees[] = new int[countOfNodes];
int i = 0;
for (Tree<T> subTree : childs) {
degrees[i] = subTree.getDegree();
i++;
}
Arrays.sort(degrees);
if(countOfNodes > degrees[countOfNodes - 1]) {
return countOfNodes;
}else {
return degrees[countOfNodes - 1];
}
}
}
/**
* 获取某棵子树。<br>
* 如果是空树或叶子节点则抛出<code>{@link NullPointerException}</code>。<br>
* 如果输入值大于或等于节点数则抛出<code>{@link ArrayIndexOutOfBoundsException}</code>。
* @param index 要查询的子树的索引
* @return 子树
* @see #childs
*/
public Tree<T> getChilds(int index){
if(isEmptyTree()) {
throw new NullPointerException("无法在空树中获取子树。");
}else if(isLeaf()) {
throw new NullPointerException("叶子节点中无子树。");
}else if(index >= getDegree() - 1 || index < 0) {
throw new ArrayIndexOutOfBoundsException();
}else {
return childs.get(index);
}
}
/**
* 获取第一个孩子节点。<br>
* 若是空节点或叶子节点则抛出<code>{@link NullPointerException}</code>。
* @return 大哥节点
* @see #childs
*/
public Tree<T> getEldestSubNode(){
if(isEmptyTree()) {
throw new NullPointerException("空树中无节点。");
}
if(isLeaf()) {
throw new NullPointerException("叶子节点中无子节点。");
}
return childs.get(0);
}
/**
* 获取可能是自己的最终节点。<br>
* 若是空节点则抛出<code>{@link NullPointerException}</code>。
* @return 最终节点
*/
public Tree<T> getYoungestNode(){
if(isEmptyTree()){
throw new NullPointerException("空树中无节点。");
}else if(isLeaf()) {
return this;
}else {
List<Tree<T>> list = getAllTrees();
Tree<T> last = null;
for (Tree<T> tree : list) {
last = tree;
}
return last;
}
}
/**
* 检测树中是否有该节点。
* @param subTree 受检节点
* @return 是否有该节点
*/
public boolean isSubTreeExists(Tree<T> subTree) {
boolean flag = false;
if(subTree == this) {
return true;
}else {
for (Tree<T> tree : childs) {
if(tree == subTree) {
return true;
}else if(!tree.isLeaf()) {
if(!flag) {
flag = tree.isSubTreeExists(subTree);
}else {
return flag;
}
}
}
}
return flag;
}
/**
* 查询整棵树中是否有该节点。
* @param tree 受检节点
* @return FLAG
* @see #isSubTreeExists(Tree)
*/
public boolean isNodeExistsInGlobalTree(Tree<T> tree) {
if(parent == null) {
return isSubTreeExists(tree);
}else if(this == tree) {
return true;
}else {
return parent.isNodeExistsInGlobalTree(tree);
}
}
/**
* 通过索引来获取某个节点。<br>
* 空树会抛出<code>{@link NullPointerException}</code>。<br>
* 越界抛出<code>{@link ArrayIndexOutOfBoundsException}</code>。
* @param index 查询索引
* @return 节点
* @throws Exception
* @see #isEmptyTree()
* @see #size()
*/
public Tree<T> getNodeByIndex(int index) throws Exception{
if(isEmptyTree()) {
throw new NullPointerException("不能从空节点中获取指定索引的节点。");
}else if(index >= size() || index < 0) {
throw new ArrayIndexOutOfBoundsException();
}else if(index == 0) {
return this;
}else {
int index2 = 0;
List<Tree<T>> trees = getAllTrees();
for (Tree<T> tree : trees) {
if(index2 == index) {
return tree;
}
index2++;
}
}
throw new Exception("其他错误!");
}
/**
* 为这棵树添加节点/子树。<br>
* 树的深度会增加。
* 如果这棵树是空树或子节点是空树将抛出<code>{@link NullPointerException}</code>。<br>
* 如果将存在的节点插入到树中将抛出<code>{@link IllegalArgumentException}</code>。
* @param subTree 子节点/子树
* @return flag
* @see #childs
* @see #isNodeExistsInGlobalTree(Tree)
*/
public int addNode(Tree<T> subTree) {
if(isEmptyTree()) {
throw new NullPointerException("不能为空树增加子节点!");
}else if(subTree.isEmptyTree()){
throw new NullPointerException("不能增加空树为子节点!");
}else if(isNodeExistsInGlobalTree(subTree)){
throw new IllegalArgumentException("不能增加已存在的节点!");
}else {
childs.add(subTree);
subTree.setParent(this);
}
return 1;
}
/**
* 删除树中的指定节点。<br>
* 如果树中无此节点,则抛出<code>{@link NullPointerException}</code>。
* @param subTree 要删除的节点
* @return FLAG
* @see #isSubTreeExists(Tree)
*/
public int removeNode(Tree<T> subTree) {
if(isSubTreeExists(subTree)) {
subTree.getChilds().clear();
subTree.clear();
System.out.println(subTree.size());
subTree.destroy();
childs.remove(subTree);
}else {
throw new NullPointerException("该树中无此节点。");
}
return 1;
}
/**
* 删除指定索引的节点。
* @param index 索引
* @return FLAG
* @throws Exception
* @see #getNodeByIndex(int)
* @see #removeNode(Tree)
*/
public int removeNode(int index) throws Exception {
removeNode(getNodeByIndex(index));
return 1;
}
/**
* 先根遍历添加列表元素。
* @param list 列表
* @see #getAllDataOfTreeByPreOrder()
*/
private void visitAllByPreOrder(List<T> list) {
list.add(data);
if(!isLeaf()) {
for (Tree<T> tree : childs) {
tree.visitAllByPreOrder(list);
}
}
}
/**
* 先根遍历,将数据添加在表中。
* @return 带有数据的表
* @see #visitAllByPreOrder(List)
*/
public List<T> getAllDataOfTreeByPreOrder(){
List<T> datas = new ArrayList<T>();
visitAllByPreOrder(datas);
return datas;
}
/**
* 遍历所有的树。
* @param list 列表
* @see #getAllTrees()
*/
private void visitAllTrees(List<Tree<T>> list) {
list.add(this);
if(!isLeaf()) {
for(Tree<T> tree : childs) {
tree.visitAllTrees(list);
}
}
}
/**
* 遍历所有的树,将树打包成为一个列表。
* @return 带有树的表
* @see #visitAllTrees(List)
*/
public List<Tree<T>> getAllTrees(){
List<Tree<T>> trees = new ArrayList<Tree<T>>();
visitAllTrees(trees);
return trees;
}
/**
* 后根遍历添加列表元素。
* @param list 列表
* @see #getAllDataOfTreeByAfterOrder()
*/
private void visitAllByAfterOrder(List<T> list) {
if(!isLeaf()) {
for (Tree<T> tree : childs) {
tree.visitAllByPreOrder(list);
}
}
}
/**
* 后根遍历,将数据添加在表中。
* @return 带有数据的表
* @see #visitAllByAfterOrder(List)
*/
public List<T> getAllDataOfTreeByAfterOrder(){
List<T> datas = new ArrayList<T>();
visitAllByAfterOrder(datas);
datas.add(data);
return datas;
}
/**
* 置空树。
*/
public void clear() {
data = null;
if(!isLeaf()) {
for (Tree<T> tree : childs) {
tree.clear();
tree.destroy();
childs.remove(tree);
}
}
childs.clear();
}
/**
* 销毁一颗空树。
* @see {@link #isEmptyTree()}
*/
@Override
public void destroy() {
if(isEmptyTree()) {
data = null;
childs = null;
try {
super.finalize();
System.out.println("砍树。");
}catch(Throwable e) {
System.out.println("对象无需销毁。");
}
}else {
try {
throw new Exception("无法销毁非空树!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
public String toString() {
String info = "";
if(isEmptyTree()) {
info = "这是一颗空树。";
}else if(isLeaf()) {
info = "这是一个叶子节点,它的值为" + data;
}else {
info = "该树的数据值为" + data + "。\n结点度为:" + getNodeDegree()
+ "。\n度为:" + getDegree() + "。\n深度为:" + getDepth() + "。\n拥有"
+ size() + "个结点。\n其中有" + getLeafCount() + "个叶子节点。";
}
return info;
}
}