C# 将数组值平均分配的方法

用处1:小组有N个耗时不等的任务,小组有M个能力不等的人,将任务进行合理的平均分配。
用处2:数据库表的关系表需要分表,如漫画的图片链接表每个漫画的图片数量不同,按服务器的性能进行分配数据。

计算推导

分数值:33,47,22,6,38,56
序号及权重:A:1 B:2 C:3
1.每人轮流按顺序拿
A: 33,6
B:47,38
C:22,56

2.将任务耗时降序排序按ABC顺序轮询拿
分数值:56,47,38,33,22,6
序号及权重:A:1 B:2 C:3
A: 56,33
B: 47,22
C: 38,6

3.在2的基础上ABC每轮询一次后按拿的分数升序,分数低的先拿(贪婪分配?这时候权重算是1:1了)
分数值:56,47,38,33,22,6
序号及权重:A:1 B:2 C:3
A: 56,6
B: 47,22
C: 38,33
(开始平均了)

4.在3的基础上为ABC加入权重,但是轮询一次后已拿的分数除以权重(权重分数)再进行升序
因为数据量不大,跟3的结果一样,但是用代码随机生成测试,分配不是很合理

5.将权重看作次数,分数按顺序分配,按权重分数升序拿,每拿一次权重减1,某个单位权重为0时分数不分配给该单位。全部单位权重都为0时恢复权重值重新轮询一次,就是下面代码的逻辑,分配还算平均

    public class Services
    {
        /// <summary>
        /// 权重
        /// </summary>
        public int Weight { get; set; }

        /// <summary>
        /// 权重计算
        /// </summary>
        public int WeightCalc { get; set; }

        /// <summary>
        /// 权重分数
        /// </summary>
        public decimal WeightScore { get; set; }

        /// <summary>
        /// 序号
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 做个记录
        /// </summary>
        public List<int> ScopeRecord { get; set; } = new List<int>();
    }

    class Program
    {
        static void Main(string[] args)
        {
            //待分配的数据组数
            int dataGroupCount = 100;
            //服务器数量
            int servicesCount = 7;

            //需要平均分配的数据  22,66,4,7,863
            List<int> DataCount = new List<int>();
            List<Services> Service = new List<Services>();

            //生成随机数据
            for (int i = 0; i < dataGroupCount; i++)
            {
                DataCount.Add(new Random().Next(0,123));
            }

            //生成服务器随机数据
            for (int i = 0; i < servicesCount; i++)
            {
                var weight = new Random().Next(1, servicesCount);
                Service.Add(new Services()
                {
                    Id = i,
                    Weight = weight, /*new Random().Next(1, servicesCount),*/ //随机权重
                    WeightCalc = weight,
                    WeightScore = 0
                });
            }

            //数据组排序
            DataCount = DataCount.OrderByDescending(q => q).ToList();


            //轮询拿数据组数值  每轮询一次 根据权重分数重新分配先拿的人 且先拿高分数
            //因为是数据组是降序最后分配不够拿时按权重分配也会将差距缩小

            //用数据组进行轮询  也可以用服务器组轮询
            foreach (var scope in DataCount)
            {
                //可优化
                var empty = Service.OrderBy(q => q.WeightScore / q.Weight).FirstOrDefault(q => q.WeightCalc > 0);

                empty.WeightScore += scope;
                empty.ScopeRecord.Add(scope);
                empty.WeightCalc--;

                if (Service.Count(q=>q.WeightCalc>0)<=0)
                {
                    Service.ForEach(q=>{q.WeightCalc = q.Weight;});
                }
            }

            //打印服务器数据
            foreach (var item in Service.OrderBy(q=>q.Id))
            {
                Console.WriteLine($"服务器号:{item.Id},服务器权重:{item.Weight},服务器分数:{item.WeightScore}");
                Console.WriteLine($"分数记录:{string.Join(",",item.ScopeRecord)}");
                Console.WriteLine();
            }

            //打印数据组数据
            int colum = 10;
            Console.WriteLine("数据组数据:");
            for (int i = 0; i <= DataCount.Count / colum; i++)
            {
                Console.WriteLine($"{string.Join(",", DataCount.Skip(i * colum).Take(colum))}");
            }

        }
    }

猜你喜欢

转载自blog.csdn.net/qq_30174147/article/details/107788773
今日推荐