算法 Union-Find

Union-Find 动态连通性

动态连通性是计算机的一种数据结构,动态维护结构中相互链接的组信息。

通俗的说 : 就像朋友圈,在社交网络中,彼此熟悉的人与人之间组成的朋友圈,但是这个圈子是会逐渐扩大的,不一定是你扩大,有可能你的朋友认识了一个新的朋友,或者 “断袖” 了,这种变化是动态的,然而这个关系网是庞大的,连通的,这就是动态连通数据结构。

假设:我与用户A相识, 用户A 与 用户 B 相识,那么就会默认为我与用户B 可能是相识,所以是连接起来一个组别,我就可以看到用户B的信息,计算机网络中也大致如此。


计算机语言描述

给定一个整数队 [ A , B],如果A ,B尚未相连,则使二者相连(红娘介绍对象),A,B相识后,我们可以称 A,B同是一组内的。

当A ,B 互通,以下关系是可以成立的:

  • 自反性:AB自身是相连的
  • 对称性:如果AB相连,那么BA也是相连
  • 传递性:如果AB相连,BC相连,那么AC也是相连的

在一个圈子中,假设圈子容量是 N ,则可以定义一个从 0 到 N-1的整数队列表,A B是其中的值。然后进行如下操作

  • 断定A和B是否相连 bool
  • 如果AB已经相连,则没操作,未相连,则连接,并且归纳组
  • 查找A或B属于那个组(圈子)

  • Connected: 判断AB是否相互连接,同一组则相连。
  • Union: 如果AB没有连接,则连接AB,并且归纳组,反正不处理
  • Find: 查找AB所属圈子(组)
  • Count: 组的数量

图 1.5.2

1



public class UnionInfo
    {
        private int _group;

        private int _index;

        public int Group { get => _group; set => _group = value; }
        public int Index { get => _index; set => _index = value; }
    }

public class Union_Find
    {
        public List<UnionInfo> bytes_datas;

        public Union_Find(List<UnionInfo> init_Data)
        {
            bytes_datas = init_Data;

        }

        public Union_Find() { }

        public void AddPend(UnionInfo _temp)
        {
            if (bytes_datas == null) bytes_datas = new List<UnionInfo>();
            bytes_datas.Add(_temp);
        }

        public bool Connected(UnionInfo p, UnionInfo q)
        {
            if (p == null || q == null) throw new Exception("p or q is null");
            return p.Group == q.Group;
        }

        public UnionInfo Find(int by_index)
        {
            return bytes_datas[by_index];
        }

        public UnionInfo Find(UnionInfo p)
        {
            int by_index = p.Index;
            return Find(by_index);
        }

        public void Union(int by_index_p, int by_index_q)
        {
            UnionInfo p = Find(by_index_p);
            UnionInfo q = Find(by_index_q);
            int group = p.Group;
            if (!Connected(p, q))
            {
                List<UnionInfo>.Enumerator _union = bytes_datas.GetEnumerator();
                while (_union.MoveNext())
                {
                    if (_union.Current.Group == group)
                    {
                        _union.Current.Group = q.Group;//修改组别
                    }
                }
            }
        }


    }

Test Code

public class Program
    {
        static void Main(string[] args)
        {
            Union_Find un = new Union_Find();
            for (int i = 0; i < 10; i++)
            {
                UnionInfo _tempInfo = new UnionInfo();
                _tempInfo.Group = i;
                _tempInfo.Index = i;
                un.AddPend(_tempInfo);
            }
            List<int[]> list = new List<int[]>()
            {
                new int[]{ 4,3},
                new int[]{ 3,8},
                new int[]{ 6,5},
                new int[]{ 9,4},
                new int[]{ 2,1},
                new int[]{ 5,0},
                new int[]{ 7,2},
                new int[]{ 6,1}
            };
            object[] arg = new object[un.bytes_datas.Count];
            foreach (int[] k in list)
            {
                UnionInfo p = un.Find(k[0]);
                UnionInfo q = un.Find(k[1]);
                un.Union(k[0], k[1]);
                Console.WriteLine("{0} and {1} connected ? " + un.Connected(p, q), p.Index, q.Index);

            }
            for (int i = 0; i < un.bytes_datas.Count; i++)
            {
                arg[i] = un.bytes_datas[i].Group;
            }
            string str = "Final group list is ";
            Console.WriteLine(str + String.Join(" ", arg));

        }
    }

Run Result

1


[1.] 图1.5.2取自 《算法4》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值