浅说细解如何设计程序c#



高山流水2014V4
2014年03月19日 16时33分59秒 星期三 双鱼座
二〇一四年二月十九[2014年03月19日000周岁]
甲午〖马〗丁卯月己丑日壬申时
命:土;五行:木火土水金;缺:无;
纳音五行:沙中金。

观世音菩萨圣诞大笑

提问是这样的:一个为100的一维数字数组输出其4个最大值位置(这里简略提问者的文字描述了)
好,来设计一个只考虑4最大值位置的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("请输入任意数字用于排序,数组用空格隔开,按回车键结束...");
            var 啊啊 = Console.ReadLine();/*获取控制台输入一行数据*/
            var 猜猜 = 啊啊.Split(" "[0]);/*分割数据*/
            var 得到 = 猜猜.OrderBy(啊 => 啊).ToArray();/*按升序进行排列,当然也可按降序*/
            int[] 集合 = new int[4];
            int 位置 = 1;
            foreach (var 啊 in 猜猜)/*由于没找到.IndexOf函数支持只能自己写循环*/
            {
                if (啊 == 得到[得到.Length - 1]) 集合[0] = 位置;
                if (啊 == 得到[得到.Length - 2]) 集合[1] = 位置;
                if (啊 == 得到[得到.Length - 3]) 集合[2] = 位置;
                if (啊 == 得到[得到.Length - 4]) 集合[3] = 位置;
                位置++;
            }
            Console.WriteLine("{0} {1} {2} {3}", 集合[0], 集合[1], 集合[2], 集合[3]);

            Console.Beep();
            Console.ReadLine();
        }
    }
}

验证代码运行是否达到需求:

好,可以看到程序证实达到设计目的;
然而,当多次任意输入不同数据会发现,如果数据存在重复,结果就不正确了,从程序代码也可看出这个缺陷存在,来看数据重复结果:

为了能够处理重复数据,分析寻求解决方案:
如果是人工操作的话,我们会怎么做?显然,动作应该是这样一个过程,首先逐个检查最大值并记录其所在位置,次按上述重复找次最大值,如此循环,直到完成工作。于是产生如下1的方案;由于计算机语言和自然语言操作起来结果有所区别,有相同位置的信息,那么,是否可以通过检查有无重复来处理?于是产生如下2的方案。
1. 每次只用一个值和一个存储位置,那么,就要对所有数据进行(4*数据量)次循环;
2. 只对所有数据进行一次循环来实现,若发现重复则保留其一,这只须循环4小次。
综合上述2种方案思考对比发现方案1循环次数显然比方案2要多,从优考虑决定设计方案2修改代码:

            int[] 集合 = Enumerable.Repeat(-1, 4).ToArray();/*限制标记*/
            int 位置 = 1;
            foreach (var 啊 in 猜猜)
            {
                if (啊 == 得到[得到.Length - 1]) if (集合[0] < 0) 集合[0] = 位置;
                if (啊 == 得到[得到.Length - 2]) if (集合[1] < 0) 集合[1] = 位置;
                if (啊 == 得到[得到.Length - 3]) if (集合[2] < 0) 集合[2] = 位置;
                if (啊 == 得到[得到.Length - 4]) if (集合[3] < 0) 集合[3] = 位置;
                if (集合.Count<int>(到 => 到 == 位置) > 1)/*处理重复问题,由于没找到.IndexOf类似函数支持只能自己写循环*/
                    foreach (var 得 in Enumerable.Range(0, 集合.Length))
                        if (集合[得] == 位置) { 集合[得] = -1; break; }
                位置++;
            }

运行验证:

结果正确;
但位置顺序未及美满,能不能位置按顺序?好,为了这个目的,重新改写:

            int 位置 = 1, 重复 = 0;
            foreach (var 啊 in 猜猜)
            {
                if (啊 == 得到[得到.Length - 1]) if (集合[0] < 0) 集合[0] = 位置;
                if (啊 == 得到[得到.Length - 2]) if (集合[1] < 0) 集合[1] = 位置;
                if (啊 == 得到[得到.Length - 3]) if (集合[2] < 0) 集合[2] = 位置;
                if (啊 == 得到[得到.Length - 4]) if (集合[3] < 0) 集合[3] = 位置;
                if (集合.Count<int>(到 => 到 == 位置) > 1)/*处理重复问题*/
                    foreach (var 得 in Enumerable.Range(0, 集合.Length))
                        if (集合[得] == 位置) { if (重复 > 0) { 集合[得] = -1; 重复 = 0; break; } 重复++; }
                位置++;
            }

运行验证:

运行正确;
以上只是用2个重复进行设计和测试,假若重复不止2个数据,明显以上代码无法解决,来验证一下推理是否正确:

果然证明对以上代码推理正确,的确无法完美解决2个以上重复数据;
那么,很自然就想到,假如去掉跳出循环的语句不就解决了?为了实现构思,修改代码:

            int 位置 = 1, 重复 = 0;
            foreach (var 啊 in 猜猜)
            {
                重复 = 0;
                if (啊 == 得到[得到.Length - 1]) if (集合[0] < 0) 集合[0] = 位置;
                if (啊 == 得到[得到.Length - 2]) if (集合[1] < 0) 集合[1] = 位置;
                if (啊 == 得到[得到.Length - 3]) if (集合[2] < 0) 集合[2] = 位置;
                if (啊 == 得到[得到.Length - 4]) if (集合[3] < 0) 集合[3] = 位置;
                if (集合.Count<int>(到 => 到 == 位置) > 1)/*处理重复问题*/
                    foreach (var 得 in Enumerable.Range(0, 集合.Length))
                        if (集合[得] == 位置) { if (重复 > 0) 集合[得] = -1; 重复++; }
                位置++;
            }

运行验证:


再来一个:

再来一个:

再来一个:

完美!世界大同,阿弥陀佛!!!
设计程序就是这样从易到难一步一步完成,不神秘也不一头雾水,当然会有难度,只能是花费精力和时间,分析、思考、验证、修改,再分析、思考、验证、修改。

最后再整理,有利于做成一个函数,把参数提取作为传参之用:
            Console.WriteLine("请输入任意数字用于排序,数组用空格隔开,按回车键结束...\n\r\n\r");
            var 猜猜 = Console.ReadLine().Split(" "[0]);
            var 得到 = 猜猜.OrderBy(啊 => 啊).ToArray();
            int[] 集合 = Enumerable.Repeat(-1, 4).ToArray();
            int 位置 = 1, 重复 = 0;
            foreach (var 啊 in 猜猜)
            {
                foreach (var 宝 in Enumerable.Range(0, 4))
                    if (啊 == 得到[得到.Length - 1 - 宝]) if (集合[宝] < 0) 集合[宝] = 位置;
                重复 = 0;
                if (集合.Count<int>(到 => 到 == 位置) > 1)/*处理重复问题*/
                    foreach (var 得 in Enumerable.Range(0, 集合.Length))
                        if (集合[得] == 位置) { if (重复 > 0) 集合[得] = -1; 重复++; }
                位置++;
            }
            Console.WriteLine("{0} {1} {2} {3}", 集合[0], 集合[1], 集合[2], 集合[3]);





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值