Java 树的构造算法

18 篇文章 0 订阅

连通的定义:从A定点出发能到达B定点,则称A-B连通

连通的基本性质:

  • 自反性:A一定连通A(ps:自己可以和自己PY交易)
  • 对称性:如果A和B连通,则B和A也连通(无向的情况下)
  • 传递性:如果A连通B,B连通C,则A连通C

树:

  • 大小(size):树的节点数量
  • 深度(depth):某个节点到根节点的链接路径的数量
  • 高度(height):树所有节点中深度最大的值

森林的构造(目标:深度尽量小,树尽量少):

  • quick-find
  • quick-union
  • 加权quick-union
  • 路径压缩

实现

  • quick-find算法(所有具有连通关系的触点都指向终触点,查找触点很快,但连通触点较慢)

class UF {
	int[] id;
	int count;

	UF(int N) {
		id = new int[N];
		count = N;
	}
        
        //将所有连通触点指向最后的触点


        int find(int p) {
		return id[p];
	}

	void union(int p, int q) {
		int pID = find(p);//获取起触点
		int qID = find(q);//获取终触点

		if (pID == qID) {//如果已经连通,结束
			return;
		}
		for (int i = 0; i < id.length; i++) {//遍历所有触点
			if (id[i] == pID) {//如果有触点指向起触点,说明起触点之前已经和其他触点连接
				id[i] = qID; //将所有指向起触点的触点指向终触点
				count--;//连通数量减一
			}
		}
	}

	
	boolean connection(int p, int q) {
		return id[p] == id[q];
	}

	int count() {
		return count;
	}

}
  • quick-union(所有具有连通关系的触点都指向自己的终触点,连通触点很快,但查找触点较慢)
class UF1 {
	int[] id;
	int count;

	UF1(int N) {
		id = new int[N];
		count = N;
	}

        
        //查找触点的根触点,类似递归回溯
        int find(int p) {
		while(p!=id[p]) p = id[p];
		return id[p];
	}

	void union(int p, int q) {
		int pRoot = find(p);
		int qRoot = find(q);

		if (pRoot == qRoot) {
			return;
		}
		id[pRoot] = qRoot;//直接将新节点指向根节点
	}

	

	boolean connection(int p, int q) {
		return id[p] == id[q];
	}

	int count() {
		return count;
	}

}

 

  •  加权quick-union(在quick-union的基础上将小树挂在根节点上,而不是挂在子树上,减少了数的深度,最常用)
package chapter1_5;

/**
 * @author : jeasion
 * @name
 * @comment
 * @return
 */
public class WeightQuickUnion {
	int[] id;
	int count;
	int[] size;

	public WeightQuickUnion(int N) {
		id = new int[N];
		size = new int[N];
		count = N;
		for (int i = 0; i < id.length; i++) {
			id[i] = i;
			size[i] = 1;
		}

	}

	void union(int p, int q) {
		int pRoot = find(p);
		int qRoot = find(q);

		if (pRoot == qRoot) {
			return;
		}
        //如果p树的size小于q树的size,说明q树比p树大,则将p树挂到p树上
		if (size[pRoot] <= size[qRoot]) {
	//将p树的根节点qRoot赋给q树的根节点,使q树成为p树根节点的直接子节点
                        id[pRoot] = qRoot;
			size[qRoot] += size[pRoot];
		} else {
			id[qRoot] = pRoot;
			size[qRoot] += size[pRoot];
		}
	}

	int find(int p) {
		while (p != id[p])
			p = id[p];
		return id[p];
	}

	boolean connection(int p, int q) {
		return id[p] == id[q];
	}

	int count() {
		return count;
	}

}
  • 路径压缩(将所有节点链接到一个根节点,树上完全扁平的,所有节点的深度都是1,树的高度也为1)

实现:在查找find()的同时直接将节点链接到根节点,最优算法(PS:我也不知道为啥好像不实用)

 

图解:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值