/** * ���ýڵ���� * * @param clusteringFeature ��ǰ�ڵ� * @param level ��ǰ���ֵ */ private void setTreeLevel(ClusteringFeature clusteringFeature, int level) { LeafNode leafNode = null; NonLeafNode nonLeafNode = null; if (clusteringFeature instanceof LeafNode) { leafNode = (LeafNode) clusteringFeature; } else if (clusteringFeature instanceof NonLeafNode) { nonLeafNode = (NonLeafNode) clusteringFeature; } if (nonLeafNode != null) { nonLeafNode.setLevel(level); level++; // �����ӽڵ� if (nonLeafNode.getNonLeafChilds() != null) { for (NonLeafNode n1 : nonLeafNode.getNonLeafChilds()) { setTreeLevel(n1, level); } } else { for (LeafNode n2 : nonLeafNode.getLeafChilds()) { setTreeLevel(n2, level); } } } else { leafNode.setLevel(level); level++; // �����Ӿ۴� for (Cluster c : leafNode.getClusterChilds()) { c.setLevel(level); } } }
/** * ����CF���������� * * @return */ private ClusteringFeature buildCFTree() { NonLeafNode rootNode = null; LeafNode leafNode = null; Cluster cluster = null; for (String[] record : totalDataRecords) { cluster = new Cluster(record); if (rootNode == null) { // CF��ֻ��1���ڵ��ʱ������ if (leafNode == null) { leafNode = new LeafNode(); } leafNode.addingCluster(cluster); if (leafNode.getParentNode() != null) { rootNode = leafNode.getParentNode(); } } else { if (rootNode.getParentNode() != null) { rootNode = rootNode.getParentNode(); } // �Ӹ�ڵ㿪ʼ����������Ѱ�ҵ��������Ŀ��Ҷ�ӽڵ� LeafNode temp = rootNode.findedClosestNode(cluster); temp.addingCluster(cluster); } } // ���������ҳ�������Ľڵ� LeafNode node = cluster.getParentNode(); NonLeafNode upNode = node.getParentNode(); if (upNode == null) { return node; } else { while (upNode.getParentNode() != null) { upNode = upNode.getParentNode(); } return upNode; } }
public void add(double x, double y, int depth, LeafNode<T> value) { if ((depth % 2) == 0) { // current node is split on X axis if (x < splitValue) { // left subtree if (left == null) { left = value; } else { if (left.isLeaf()) { // left == leaf node , split at Y-axis and re-insert final LeafNode<T> tmp = (LeafNode<T>) left; if (tmp.x == x && tmp.y == y) { if (!tmp.supportsMultipleValues()) { left = new MultiValuedLeafNode<>((SingleValueLeafNode<T>) tmp); } left.add(x, y, depth, value); } else { final double splitY = (tmp.y + y) / 2.0; final NonLeafNode<T> newNode = new NonLeafNode<>(splitY); newNode.add(tmp.x, tmp.y, depth + 1, tmp); newNode.add(x, y, depth + 1, value); left = newNode; } } else { left.add(x, y, depth + 1, value); } } } else { // right subtree if (right == null) { right = value; } else { if (right.isLeaf()) { // right == leaf node , split at Y-axis and re-insert final LeafNode<T> tmp = (LeafNode<T>) right; if (tmp.x == x && tmp.y == y) { if (!tmp.supportsMultipleValues()) { right = new MultiValuedLeafNode<>((SingleValueLeafNode<T>) tmp); } right.add(x, y, depth, value); } else { final double splitY = (tmp.y + y) / 2.0; final NonLeafNode<T> newNode = new NonLeafNode<>(splitY); newNode.add(tmp.x, tmp.y, depth + 1, tmp); newNode.add(x, y, depth + 1, value); right = newNode; } } else { right.add(x, y, depth + 1, value); } } } } else { // current node is split on Y axis if (y < splitValue) { // left subtree if (left == null) { left = value; } else { if (left.isLeaf()) { // left == leaf node , split at X-axis and re-insert final LeafNode<T> tmp = (LeafNode<T>) left; if (tmp.x == x && tmp.y == y) { if (!tmp.supportsMultipleValues()) { left = new MultiValuedLeafNode<>((SingleValueLeafNode<T>) tmp); } left.add(x, y, depth, value); } else { final double splitX = (tmp.x + x) / 2.0; final NonLeafNode<T> newNode = new NonLeafNode<>(splitX); newNode.add(tmp.x, tmp.y, depth + 1, tmp); newNode.add(x, y, depth + 1, value); left = newNode; } } else { left.add(x, y, depth + 1, value); } } } else { // right subtree if (right == null) { right = value; } else { if (right.isLeaf()) { // right == leaf node , split at X-axis and re-insert final LeafNode<T> tmp = (LeafNode<T>) right; if (tmp.x == x && tmp.y == y) { if (!tmp.supportsMultipleValues()) { right = new MultiValuedLeafNode<>((SingleValueLeafNode<T>) tmp); } right.add(x, y, depth, value); } else { final double splitX = (tmp.x + x) / 2.0; final NonLeafNode<T> newNode = new NonLeafNode<>(splitX); newNode.add(tmp.x, tmp.y, depth + 1, tmp); newNode.add(x, y, depth + 1, value); right = newNode; } } else { right.add(x, y, depth + 1, value); } } } } }
/** * ��ʾCF���������� * * @param rootNode CF����ڵ� */ private void showCFTree(ClusteringFeature rootNode) { // �ո���������� int blankNum = 5; // ��ǰ����� int currentLevel = 1; LinkedList<ClusteringFeature> nodeQueue = new LinkedList<>(); ClusteringFeature cf; LeafNode leafNode; NonLeafNode nonLeafNode; ArrayList<Cluster> clusterList = new ArrayList<>(); String typeName; nodeQueue.add(rootNode); while (nodeQueue.size() > 0) { cf = nodeQueue.poll(); if (cf instanceof LeafNode) { leafNode = (LeafNode) cf; typeName = LEAFNODE; if (leafNode.getClusterChilds() != null) { for (Cluster c : leafNode.getClusterChilds()) { nodeQueue.add(c); } } } else if (cf instanceof NonLeafNode) { nonLeafNode = (NonLeafNode) cf; typeName = NON_LEAFNODE; if (nonLeafNode.getNonLeafChilds() != null) { for (NonLeafNode n1 : nonLeafNode.getNonLeafChilds()) { nodeQueue.add(n1); } } else { for (LeafNode n2 : nonLeafNode.getLeafChilds()) { nodeQueue.add(n2); } } } else { clusterList.add((Cluster) cf); typeName = CLUSTER; } if (currentLevel != cf.getLevel()) { currentLevel = cf.getLevel(); System.out.println(); System.out.println("|"); System.out.println("|"); } else if (currentLevel == cf.getLevel() && currentLevel != 1) { for (int i = 0; i < blankNum; i++) { System.out.print("-"); } } System.out.print(typeName); System.out.print("N:" + cf.getN() + ", LS:"); System.out.print("["); for (double d : cf.getLS()) { System.out.print(MessageFormat.format("{0}, ", d)); } System.out.print("]"); } System.out.println(); System.out.println("*******���շֺõľ۴�****"); // ��ʾ�Ѿ��ֺ���ľ۴ص� for (int i = 0; i < clusterList.size(); i++) { System.out.println("Cluster" + (i + 1) + "��"); for (double[] point : clusterList.get(i).getData()) { System.out.print("["); for (double d : point) { System.out.print(MessageFormat.format("{0}, ", d)); } System.out.println("]"); } } }
// 节点分裂 @Override public void split() { int c1 = 0; int c2 = 0; double maxDist = 0; int length = this.getChildrenList().size(); for (int i = 0; i < length - 1; i++) { for (int j = i + 1; j < length; j++) { double dist = this.getChildrenList() .get(i) .getClusterFeature() .getDistanceTo(this.getChildrenList().get(j).getClusterFeature()); if (dist > maxDist) { maxDist = dist; c1 = i; c2 = j; } } } // 以距离最远的孩子节点为中心,把B+1个孩子分为两个大簇,其中一个簇仍留做本节点的孩子,另一个新建一个节点来领养它们 LeafNode newNode = new LeafNode(); newNode.addChild(this.getChildrenList().get(c2)); // 如果本节点已经是root节点,则需要创建一个新的root节点 if (this.getParent() == null) { NonLeafNode root = new NonLeafNode(); root.setN(this.getN()); root.setLS(this.getLS()); root.setSS(this.getSS()); this.setParent(root); root.addChild(this); } // 建立新节点和本节点的父节点的父子关系 newNode.setParent(this.getParent()); ((NonLeafNode) this.getParent()).addChild(newNode); // 把离newNode节点近的孩子归属到这个newNode簇里面 for (int i = 0; i < length; i++) { if (i != c1 && i != c2) { if (this.getChildrenList() .get(i) .getClusterFeature() .getDistanceTo(this.getChildrenList().get(c2).getClusterFeature()) < this.getChildrenList() .get(i) .getClusterFeature() .getDistanceTo(this.getChildrenList().get(c1).getClusterFeature())) { newNode.addChild(this.getChildrenList().get(i)); } } } // 把离newNode近的孩子从本节点中删除 for (MinCluster cluster : newNode.getChildrenList()) { newNode.addCF(cluster.getClusterFeature(), true); this.deleteChild(cluster); this.addCF(cluster.getClusterFeature(), false); } // 把新增加的LeafNode添加到LeafNode的双向链表中 if (this.getNext() != null) { newNode.setNext(this.getNext()); this.getNext().setPre(newNode); } this.setNext(newNode); newNode.setPre(this); // 如果本节点的分裂导致了父节点的孩子书超过了分支因子,则引发父节点的分裂 NonLeafNode pn = (NonLeafNode) this.getParent(); if (pn.getChildrenList().size() > pn.getB()) { this.getParent().split(); } }