資料結構3—java 樹 雙親表示法
阿新 • • 發佈:2019-02-20
假設以一組連續空間儲存樹的節點,同時在每個節點中,附設一個指示器指示其雙親結點到連結串列中的 的位置,也就是說,每個結點 知道自己是誰外,還知道雙親在哪裡。
雙親表示法根據結點的parent指標很容易找到它的雙親結點,所以時間複雜度為O[1],知道parent為-1,時,表示找到了根節點。可如果要找結點的孩子是什麼,需要遍歷整個結構才行。
一、定義介面(為什麼要用介面~)
public interface IBinaryTree<E> {
/**
* 新增子節點
* @param data 資料域
* @param parent 雙親節點E
*/
public void addNode(E data,MNode<E>parent);
/**
* 獲取根節點
* @return
*/
public MNode<E> getRoot();
/**
* 獲取雙親結點
* @param mNode
* @return
*/
public MNode<E>getParent(MNode<E>mNode);
public List<MNode<E>>getChild(MNode<E>mNode);
/**
* 獲取全部節點
* @param mNode
* @return
*/
public List<MNode<E>>getTreeNode();
/**
* 獲取指定結點的位置SDS
* @param mNode
* @return
*/
public int getPos(MNode<E>mNode);
public int getDeepth();
}
二、自定義Node類
/**
* 結點結構
* @author isc
*
* @param <T>
*/
public class MNode<E> {
private E data;//資料域
private int parent;//雙親
public E getData() {
return data;
}
public void setData(E data) {
this.data = data;
}
public int getParent() {
return parent;
}
public void setParent(int parent) {
this.parent = parent;
}
public MNode(E data,int parent){
this.data=data;
this.parent=parent;
}
public MNode(E data) {
this.data=data;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + parent;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MNode other = (MNode) obj;
if (data == null) {
if (other.data != null)
return false;
} else if (!data.equals(other.data))
return false;
if (parent != other.parent)
return false;
return true;
}
@Override
public String toString() {
return "MNode [data=" + data + ", parent=" + parent + "]";
}
}
三、定義樹結構
public class MyTree<E> implements IBinaryTree<E>{
int MAX_TREE_SIZE =100;
MNode<E>[] nodes; //定義結點陣列
int treeSize;
int nodeNums=0;
/**
* 指定根節點建立樹
* @param data
*/
public MyTree(E data){
treeSize = MAX_TREE_SIZE;
nodes = new MNode[treeSize]; //
nodes[0] = new MNode<E>(data,-1);//定義根節點
nodeNums++;
}
/**
* 指定根節點\指定結點數 建立樹
* @param data
*/
public MyTree(E data,int treeSize){
this.treeSize = treeSize;
nodes = new MNode[treeSize];
nodes[0] = new MNode<E>(data,-1);//定義根節點
nodeNums++;
}
/**
* 為指定結點新增子節點
*/
@Override
public void addNode(E data, MNode<E> parent) {
for(int i=0;i<treeSize;i++){
if(nodes[i]==null){
nodes[i]=new MNode<E>(data, getPos(parent));//指定值和雙親節點
nodeNums++;
return;
}
}
}
@Override
public MNode<E> getRoot() {
if(nodeNums>0){
return nodes[0];
}
return null;
}
@Override
public MNode<E> getParent(MNode<E> mNode) {
return nodes[mNode.getParent()];
}
//返回指定節點(非葉節點)的所有子節點
@Override
public List<MNode<E>> getChild(MNode<E> parent) {
List<MNode<E>> list = new ArrayList<MNode<E>>() ;
// for(int i=0;i<treeSize;i++){
// if(nodes[i]!=null&&nodes[nodes[i].getParent()].equals(mNode)){
// list.add(nodes[i]);
// }
// }
for (int i = 0; i < treeSize; i++) {
if (nodes[i] != null && nodes[i].getParent() == getPos(parent)) {
list.add(nodes[i]);
}
}
return list;
}
@Override
public int getPos(MNode<E> mNode) {
for(int i=0;i<treeSize;i++){
if(nodes[i].equals(mNode)){
return i;
}
}
return -1;
}
@Override
public int getDeepth() {
// 用於記錄結點的最大深度
int max = 0;
for (int i = 0; i < treeSize && nodes[i] != null; i++) {
// 初始化本結點的深度
int def = 1;
// m記錄當前結點的父結點的位置
int m = nodes[i].getParent();
// 如果其父結點存在
while (m != -1 && nodes[m] != null) {
// 向上繼續搜尋父結點
m = nodes[m].getParent();
def++;
}
if (max < def) {
max = def;
}
}
// 返回最大深度
return max;
}
@Override
public List<MNode<E>> getTreeNode() {
List<MNode<E>> list = new ArrayList<MNode<E>>() ;
for(int i=0;i<treeSize;i++){
if(nodes[i]!=null){
list.add(nodes[i]);
}
}
return list;
}
}
四、測試類
public class TestClass {
public static void main(String[] args){
TestClass ts = new TestClass();
ts.testTree();
}
public void testTree(){
Student data = new Student();
data.setId(1);
data.setName("JY");
data.setAge(22);
MyTree<Student> pTree = new MyTree<Student>(data);//利用值建立樹
// 拿到父結點
MNode<Student> parent = new MNode<Student>(data);
parent.setParent(-1);
// 新增子結點
Student data2 = new Student();
data2.setId(2);
data2.setName("LYH");
data2.setAge(23);
pTree.addNode(data2, parent);
Student data3 = new Student();
data3.setId(3);
data3.setName("YC");
data3.setAge(23);
pTree.addNode(data3, parent);
MNode<Student> parent2 = new MNode<Student>(data2);
Student data4 = new Student();
data4.setId(4);
data4.setName("LAF");
data4.setAge(23);
pTree.addNode(data4, parent2);
Student data5 = new Student();
data5.setId(5);
data5.setName("LAF3");
data5.setAge(23);
pTree.addNode(data5, parent2);
Student data6 = new Student();
data6.setId(6);
data6.setName("LAF3");
data6.setAge(23);
pTree.addNode(data6, parent2);
// 遍歷所有結點
List<MNode<Student>> children = pTree.getTreeNode();
System.out.println("樹的全部節點為:");
for(MNode<Student> node : children){
System.out.println(node.toString());
}
System.out.println("樹深為:"+pTree.getDeepth());
List<MNode<Student>> children2 = pTree.getChild(parent2);
System.out.println("節點為"+pTree.getPos(parent2)+"的子節點為:");
for (MNode<Student> node : children2) {
System.out.println(node.toString());
}
}
}
五、測試結果
樹的全部節點為:
MNode [data=Student [id=1, name=JY, age=22], parent=-1]
MNode [data=Student [id=2, name=LYH, age=23], parent=0]
MNode [data=Student [id=3, name=YC, age=23], parent=0]
MNode [data=Student [id=4, name=LAF, age=23], parent=1]
MNode [data=Student [id=5, name=LAF3, age=23], parent=1]
MNode [data=Student [id=6, name=LAF3, age=23], parent=1]
樹深為:3
節點為1的子節點為:
MNode [data=Student [id=4, name=LAF, age=23], parent=1]
MNode [data=Student [id=5, name=LAF3, age=23], parent=1]
MNode [data=Student [id=6, name=LAF3, age=23], parent=1]