并查集 Python 版本
今天忽然诗意大发,“咳咳”,真的就是诗意大发。
数据结构也是也是比较单一的,elem, prev, ind。真正实施的时候,只需要前两个维度,为了让正确率更高,调试代码的速度变快,采用一些自己能掌握的指标。
并查集是使用树结构来解决,并集和查找元素的问题。在数据结构设计上,是 enough 的,因此,那种天真地想要从上至下输出或者遍历并查集是比较可笑的。这个问题很简单,如果你希望从上至下来遍历的话呢,你只需要使用 BST 二叉查找树,就能解决问题。记住,并查集,一定是,先确定元素,再自底向上搜索的。
预备数据集:
# 线性数组表示法 vec_elem=['A','B','C','D','E','F','G','H','I','J','K','L','M'] vec_prev=[-1,0,-1,-1,1,1,2,3,3,3,4,4,7] vec_tag=0 vec_grp=-1 disjoint_set=pd.DataFrame([]) disjoint_set['elem']=vec_elem disjoint_set['prev']=vec_prev disjoint_set['ind']=disjoint_set.index disjoint_set from IPython.display import Image Image("https://userspace1.oss-cn-beijing.aliyuncs.com/article/bingchaji_6.png",width=600,height=500) # REMARK:主要考察有几个 ELEMENT
数据集运行结果:
函数介绍:
1.为了用户更加快速地理解函数,我们写个说明书。主要的函数,是并集合,union_set() 以及查找元素 find_elem(),后者只需要一段代码即可解决。
2.其次,是确定辅助函数,例如,并集的时候,规定:矮的并入高的。因此,确定函数 swap_val(), 如果两棵树的高度反了话,再换回来。
3.确定函数 计算深度 cal_depth() 返回集合中所有的树,及对应深度。
4.计算函数子树是否已经被记录 is_existed() ,是的话返回该树坐标,否则 append
# --- FIND --- def find_elem(vec_in, elem_in): # --- Input: 元素所在集合,元素本身 # --- Ouput: 根所在 ind, 根所在的 elem, 根所在的 深度 for i in range(len(vec_in)): if(vec_in['elem'][i] == elem_in): tmp_elem_ind = i break cnt_iter=0 ind_prev=tmp_elem_ind while( int(vec_in['prev'][ind_prev])>-1 and cnt_iter< 50 ): ind_prev=vec_in['prev'][ind_prev] cnt_iter=cnt_iter+1 root_ind = ind_prev elem_out = vec_in['elem'][root_ind] depth_out = cnt_iter+1 return root_ind, elem_out, depth_out # --- UNION --- def swap_val(a, b): if(a>b): tmp=a; a=b; b=tmp return a, b def union_set(vec_in, root_1, root_2): if(root_1==root_2): return; else: # -- 保证 root_2 比较矮 vec_ind, vec_depth, vec_cnt = cal_depth(vec_in) ind_1=is_existed(vec_ind, root_1) ind_2=is_existed(vec_ind, root_2) # -- 互换 if (vec_depth[ind_1] < vec_depth[ind_2]): root_1, root_2 = swap_val(root_1, root_2) # --- root_2 必然是比较矮的树 vec_in['prev'][vec_in.ind==root_2]=root_1; return def is_existed(vec_in, elem_in): # input list ind_existed=-1 for i in range(len(vec_in)): if(elem_in == vec_in[i]): ind_existed=i break return ind_existed def cal_depth(vec_in): vec_root_ind=[] vec_root_depth=[] vec_root_cnt=[] for i in range(len(vec_in)): tmp_elem = vec_in['elem'][i] tmp_ind, tmp_root_elem, tmp_depth = find_elem(vec_in, tmp_elem) ind_root=is_existed(vec_root_ind, tmp_ind) if(ind_root>-1): vec_root_cnt[ind_root] = vec_root_cnt[ind_root]+1 if(vec_root_depth[ind_root] < tmp_depth ): vec_root_depth[ind_root]=tmp_depth else: vec_root_ind.append(tmp_ind) vec_root_depth.append(tmp_depth) vec_root_cnt.append(1) #print("Index of roots in forest: ", vec_root_ind) #print("Depth of trees: ", vec_root_depth) #print("#Node of trees: ", vec_root_cnt ) return vec_root_ind, vec_root_depth, vec_root_cnt
查找部分:
传入:集合,需要被查找的元素”I“
传出:根节点 ind, 根节点元素,元素到根的深度
root_1, elem_1, depth_1 = find_elem(disjoint_set,"I") print("Root/Elem of Input is: ", root_1, "/", elem_1, "/", depth_1)
运行结果:
并集合,使用到查找:
1.传入元素,返回根ind
2.将根 ind 传入 union_set(集合,根ind_1, 根ind_2)
# -- 左1 + 左2 e_1="B" e_2="G" r1,_,_ = find_elem(disjoint_set, e_1) r2,_,_ = find_elem(disjoint_set, e_2) print("The roots of '", e_1, "' & '", e_2, "' are: ", r1,r2) # ---- Union union_set( disjoint_set, r1, r2 ) print("Union 2 Trees and being shown as follows: \n") disjoint_set
运行结果:
1.数据集输出
2.图片展示
再并入一棵子树:
# -- 左1 + 左2 e_3="E" e_4="M" r3,_,_ = find_elem(disjoint_set, e_3) r4,_,_ = find_elem(disjoint_set, e_4) print("The roots of '", e_3, "' & '", e_4, "' are: ", r3, r4) union_set( disjoint_set, r3, r4 ) print("Union 2 Trees and being shown as follows: \n") disjoint_set
1.数据结构结果
2.图示
欢迎伙伴们关注 ShoelessCai.com 。