import java.util.ArrayList;
public class treemodel {
/**
* 2014.6.10开始写
*
* 2014.6.21晚修改
*
* 普通树的Java实现
*
* 作者:张迪Victorz
*
* 参考:李刚《疯狂Java程序员的基本修养》
*
* %用一个节点数组保存树里面的节点,并让每个节点记录其父节点所在的组的索引即可(类似于主键和从建)
*
* 节点的维护有两种方法
*
* 1.维护父节点(找子节点很麻烦) 让每个节点都记住自己的父节点
*
* 2.维护子节点,让父节点记住子节点(类似临街链表的方式)
*
* 3.针对二叉树,(因为确定了子节点的个数 1 or 2 )采用数组就能实现存储
*
* 4.二叉树 还可有二叉树链表存储 【左指针】【数据】【右指针】
*
* 5.二叉树 还有进一步的链表存储 【父节点指针】【左指针】【数据】【右指针】
*
* %%涉及二叉树的先序遍历 中序遍历 后序遍历
*
* 暂时选用链表存储 【父节点指针】【左指针】【数据】【右指针】结构,默认从左插入
*
*
* 出现的问题:
*
* 1.开始插入的时候由于模糊,只能实现在根节点的插入。后来改为利用标号来插入
*
* 2.遍历知识混乱
*/
// 节点内部类
public class Node {
public Node father;// 父节点// 记录父节点的位置
public Node leftch;// 左节点
public Node rightch;// 右节点
public Object data;// 存储的数据
// 所有元素的构造方法
public Node(Node father, Node leftch, Node rightch, Object data) {
super();
this.father = father;
this.leftch = leftch;
this.rightch = rightch;
this.data = data;
}
// 默认构造方法
public Node() {
}
public Node(Node leftch, Node rightch, Object data) {
super();
this.leftch = leftch;
this.rightch = rightch;
this.data = data;
}
// 构造尾节点
public Node(Object data, Node father) {
super();
this.father = father;
this.data = data;
}
}
// 一些属性
private int nodenum;// 节点的个数
private int height;// 记录树的高度
private Node root;// 永远指向根节点
// private Node avli;
// 初始建立树
// 一些getter和setter方法
public int getNodenum() {
return nodenum;
}
public void setNodenum(int nodenum) {
this.nodenum = nodenum;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
// 默认构造方法
treemodel() {
if (root == null) {
root = new Node(null, null, null, null);
setHeight(1);// 高度为1
setNodenum(1);// 设置节点为1
}
}
treemodel(Object data) {
if (root == null) {
root = new Node(null, null, data);
setHeight(1);// 高度为1
setNodenum(1);// 设置节点为1
}
}
// 构造方法以指定的根节点和内容来创建树
treemodel(Node speroot, Object data) {
// 找到这个根节点,返回根节点
try {
Node node = find(speroot);
if (node != null) {
// 插入节点
add(data, node);
} else {
throw new Exception("没找到相关的根节点");
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
// 然后在这个根结点处插入相关的节点
}
// 为指定节点添加子节点(在father的节点插入节点,数据为data,默认从左面插入)
public void add(Object data, Node father) {
try {
// 查找这个根节点是否存在
if (!ishasrightnode(father)) {
// 插入左节点
father.leftch = new Node(father, null, null, data);
nodenum++;
height = (int) Math.floor(nodenum / 2) + 1;
} else if (!isfull(father)) {
// 插入右节点
father.rightch = new Node(father, null, null, data);
nodenum++;
height = (int) Math.floor(nodenum / 2) + 1;
} else {
throw new Exception("对不起,此根节点不能插入");
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
// 判断节点是否有左节点
public boolean ishasrightnode(Node node) {
boolean flag = false;
if (node.leftch != null) {
flag = true;
}
return flag;
}
// 判断给定根节点是否两个子节点都被占满
public boolean isfull(Node node) {
boolean flag = false;
if (node.leftch != null && node.rightch != null) {
flag = true;
}
return flag;
}
// 判断树是否为空
public boolean isEmpty() {
return nodenum == 1;
}
// 返回根节点函数
public Node getRoot() {
return root;
}
// 查找并返回特定的节点
// 遍历节点开始寻找
// 递归调用
public Node find(Node node) {
System.out.println(node.data);
Node t = getRoot();
find(t.leftch);
find(t.rightch);
if (t.data == node.data && t.leftch == node.leftch
&& t.rightch == node.rightch) {
return t;
}
return null;
}
// 主要用于查找插入的地方,用于编号
public Node find2(int location) {
Node ro = getRoot();
try {
if (location > nodenum) {
throw new Exception("超出范围");
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
for (int i = 1; i <= location;) {
if (ro.leftch != null) {
ro = ro.leftch;
i++;
} else if (ro.rightch != null) {
ro = ro.rightch;
i++;
} else {
ro = ro.father;
}
}
return ro;
}
// 删除相关的节点
public void delete(Node node) { // 找到这个点,如果有子节点,顺便把节点删下去
if (node == null) {
return;
}
delete(node.leftch);
delete(node.rightch);
{
node.data = null;
node.leftch = null;
node.rightch = null;
if (leftorright(node).equals("left")) {
node.father.leftch = null;
} else {
node.father.rightch = null;
}
}
}
// 判断节点是其父节点的左节点还是右节点
public String leftorright(Node node) {
if (node.father.leftch == node) {
return "left";
} else {
return "right";
}
}
// 修改相关的节点
public void update(int i, Object data) {
Node spe = find2(i);
spe.data = data;
}
// 返回指定节点的父节点
public Node returnfathernode(Node node) {
return node.father;
}
// 返回树的高度
public int height() {
return height;
}
// 返回包含指定值的节点
public ArrayList<Node> returnNodes(Object data) {
ArrayList<Node> list = new ArrayList<Node>();
Node t = getRoot();
find(t.leftch);// 左递归
find(t.rightch);// 右递归
if (t.data == data) {
list.add(t);// 将有特定值的点放入到线性表中
}
return list;
}
// 遍历所有树中的节点,用于查找和核对
public void showall(Node cur) {
// 采用先序序列遍历树(也可采用中序和后序)
if (cur == null) {
return;
}
System.out.println(cur.data);
showall(cur.leftch);
showall(cur.rightch);
}
}