树与等价问题的Java实现

来源:互联网 发布:数据挖掘会议 2017 编辑:程序博客网 时间:2024/05/12 05:02
核心: 1:  根据给定等价关系划分等价类. 
         2: 用树来实现集合和集合操作.
         3:为了便于实现集合操作, 树采用 "双亲表示法存储"; 


确定等价类的算法:(这里可以搜索详细的算法描述)
    1:构造单个元素集合;
    2:重复读入偶对,判定所属集合,进行合并;


划分等价类的三个集合操作:
    1: 构造只含单个成员的集合.
    2:判定某个单元素所在集合.
    3:归并两个互不相交的集合为一个集合.

//树的表示. 一个集合就是一棵树;
1
2
3
4
5
6
7
8
//树的表示: 双亲表示法
class ParentTree{
    Object data; //数据
     
    ParentTree parent; //该节点的父亲
}
 
    


以此为例来进行说明和程序演示:
    假设集合S= {x | 1<= x <=8 } R是 S上的一个等价关系:
    R = {(1,2),(3,4),(5,6),(7,8),(1,3),(5,7),(1,5)};

    如题: 如果函数div_equalClass() 调用 find_mfset() 和 merge_mfset() 确定等价类,结果生成的树如下:



Java代码实现如下:
import java.util.ArrayList; //树与等价问题; MFset表示集合,它由n个子集合构成.//以此为例来进行说明和程序演示:   //假设集合S= {x | 1<= x <=8 } R是 S上的一个等价关系:    //R = {(1,2),(3,4),(5,6),(7,8),(1,3),(5,7),(1,5)}; public class MFset {    //n个子集合,一个集合就是一棵树    private int n;    private ParentTree[] mfSet;         public MFset(Object[] Xi){        this.n = Xi.length;        mfSet = new ParentTree[n+1];                 initial(Xi);    }         //初始化操作,构造一个由n个子集Si...Sn(每个子集只含单个成员Xi)构成的集合S。    private void initial(Object[] Xi){        for(int i=0;i<Xi.length;i++){            mfSet[i+1] = new ParentTree(Xi[i]);//构造一个只含单个成员Xi的集合        }    }         //查找函数,确定x所属集合Si    public ParentTree find_mfset(Object x){        ParentTree si = null;                 //找到存储x的节点        for(ParentTree ele : mfSet){            if(ele!=null && ele.toString().equals(x.toString())){                si = ele; break;            }        }                 if(si == null) return si;//x不存在                 while(si.parent != null){            si = si.parent;        }                 return si;    }         //查找函数 增强版,确定x所属集合Si,压缩路径:并将从i至根路径上的所有节点都变成根的孩子节点    public ParentTree fix_mfset(Object x){        ParentTree si = null;                 //找到存储x的节点        for(ParentTree ele : mfSet){            if(ele!=null && ele.toString().equals(x.toString())){                si = ele; break;            }        }        if(si == null) return si;//x不存在                 ArrayList<ParentTree> path = new ArrayList<>();//存储搜索路径         while(si.parent != null){            path.add(si);            si = si.parent;        }                 for(ParentTree ele : path)//将从i至根路径上的所有节点都变成根的孩子节点            ele.parent = si;                 return si;    }         //合并函数,将子集合Si和Sj中的一个并入另一个中,Si和Sj为子树根节点。    public void merge_mfset(ParentTree Si,ParentTree Sj){        if(Si == null || Sj==null)return;        Sj.parent = Si;    }         //合并函数增强版, 并之前判断子集中所含成员的数目,然后令成员少的子树并入到含成员多的子树      // 因此需要修改存储结构,令根节点的parent域存储子集中所含成员数目的负值。初始为-1    // 另一种方法: 增加一个存储数目的域count     //    public void mix_mfset(ParentTree Si,ParentTree Sj){        //Si和Sj为子树根节点。        if(Si == null || Sj==null)return;                 if(Si.count > Sj.count){            Si.count += Sj.count;            Sj.parent = Si;        }        else{            Sj.count += Si.count;            Si.parent = Sj;        }    }         //根据等价关系划分等价类,即   2:重复读入偶对,判定所属集合,进行合并;    public  void div_equalClass(NumPair[] numPairs){        for(int i=0;i<numPairs.length;i++){            ParentTree S1 = fix_mfset(numPairs[i].x);//增强版查找函数            ParentTree S2 = fix_mfset(numPairs[i].y);                         /*ParentTree S1 = find_mfset(numPairs[i].x);//原版查找函数            ParentTree S2 = find_mfset(numPairs[i].y);*/                         if(S1 != S2){                merge_mfset(S1,S2);//合并普通版                //mix_mfset(S1,S2);//合并增强版            }        }    }         public static void main(String[] args){        //演示集合{1,2,3,4,5,6,7,8}        Integer[] S = new Integer[8];        for(int i=0;i<8;i++)            S[i] = new Integer(i+1);                 MFset example = new MFset(S);//        //等价关系 R = {(1,2),(3,4),(5,6),(7,8),(1,3),(5,7),(1,5)};                 //确定等价类        NumPair[] numPairs = new NumPair[]{new NumPair(1, 2),new NumPair(3, 4),new NumPair(5, 6),new NumPair(7,8)        ,new NumPair(1,3),new NumPair(5, 7),new NumPair(1, 5),new NumPair(8,9)};                 example.div_equalClass(numPairs);//确定等价类             }}   //数对class NumPair{    Object x;    Object y;         public NumPair(Object x,Object y){        this.x = x; this.y = y;    }} //树的表示: 双亲表示法class ParentTree{    Object data ; //数据    int count = -1;//该树的元素数目         ParentTree parent = null; //该节点的父亲         public ParentTree(){};         public ParentTree(Object data){        this.data = data;    }         public String toString(){        return ""+data;    }}


0 0
原创粉丝点击