c# for 和 while的区别

for 用来遍历,while 也用来遍历;看是功能相同的,但如果功能相同,为啥不剔除一个呢;(而且几乎所有编程语言都有这两个循环语句)

因为他们有不一样的地方呀,(感觉好像废话,我们还是具体看代码吧)

相同的地方;

      public static void TestLoop1()
        {
            int loopTimes = 4;
            int i;
            
            for(i = 0; i < loopTimes; i++)
            {
                //0
                //1
                //2
                //3
                //最后一次进来是 index=3;

                //出去的时候,index 还是3
            }
            //(累加=>停止循环的时候变成了4
            
            int index = 0;
            while (index < loopTimes)
            {
                //0
                //1
                //2
                //3
                //最后一次进来 index=3;
                index++;
               //累加 然后出去,index=4; 然后不满足条件;退出循环;
                
            }
            //眨眼一看,上面的写法没什么区别; BUT i 的叠加是在 {} 外部进行的,  index 的叠加是在 {} 内部进行的;
}

上面的写法,在开发中会遇到不同的问题,比如:

            //眨眼一看,上面的写法没什么区别; BUT i 的叠加是在 {} 外部进行的,  index 的叠加是在 {} 内部进行的;
            //这样会出现什么问题呢;
            Console.WriteLine("我们来遍历一次数组,就知道了");
            Console.WriteLine("for.......");
            var arr = new int[] {1,2,3,4};
            int len = arr.Length;
            for(int j = 0; j < len; j++)
            {
                Console.WriteLine(arr[j]);
                //这个数绝对安全的;
            }

            Console.WriteLine("while.....");
            int k = 0;
            while (k < len)
            {
                //k++; 如果k++放在前面,无法比那里k=0 这个数组不说,还会发生数组越界的异常;
                Console.WriteLine(arr[k]);
                k++;
                
            }

            Console.WriteLine("finall k index;"+k);  //最后这个index 会变成4 所以这样比那里数组是不安全的;

            //你以为区别就这一点吗? 太年轻了,接着看;

不同的地方;

        static void ForVSWhile()
        {

            var arr=new []{ 1,2,4,5,6};
            int len = arr.Length;
            int target = 4;
            for (int i = 0; i < len; i++)
            {
                if (arr[i] == target)
                {
                    break;
                }
            }

            //这个就相当于我们的while;
            int index = 0;
            while (arr[index] == target)  //找到我们想要的元素后,就立马停止;
            {
                index++;
            }

        }

不过,你也可以把他们写来一样,不过,感觉好别扭;

            var arr=new []{ 1,2,4,5,6};
            int len = arr.Length;
            int target = 4;
            for (int i = 0; i < len && arr[i] == target;  i++)
            {
             
            }

我们再来看一个容易出错的地方;

        /// <summary>
        /// 找出数组中小于target的值;
        /// 这个问题,我在快速排序的时候遇到的一个死循环;
        /// </summary>
        public static void TestLoop2()
        {
            var arr = new int[] { 1,2,1};
            int len = arr.Length;
            int target = 2;
            List<int> list = new List<int>(3); 
            List<int> list1 = new List<int>(3); 


            // 常规写法;
            for(int j = len-1; j>=0; j--)
            {
                if (arr[j] < target)
                {
                    list.Add(arr[j]);
                }
            }
           

            Console.WriteLine("while写法的结果--------------:");  //index=2;
            int k = len-1;
            //因为 arr[1]=2   不满足条件,然后就退出了循环;并没有遍历我们的整个数组;
            //并没有把我们的数组遍历完;
            while (arr[k] < target) 
            {
                 list1.Add(arr[k]);
                  k--;
            }
        }

其实,对这个问题的总结,来自我们的快速排序时,遇到的一个问题;

        static void TestLoop()
        {
            //在快速排序的过程中遇到一个问题;
            var arr = new[] { 5, 4,1 };
            int len = arr.Length;
            int high = len - 1;
            int low = 0;
            int middle = arr[1];

            while (low < high)
            {
                while (arr[high] > middle  && low<high)
                {
                    high--;
                }

                while (arr[low] < middle && low < high)
                {
                    low++;
                }
            }

           //高地址 middle=4 high=2; arr[2]=1 找到了小于 middle 的值; 这时候,我们的high=2;
           //底地址 middle=4 low=0;  arr[0]=5;找到了大于 middle 的值; 这时候  我们的low=0;
          // 这个时候,进行交换 arr[2] 和 arr [0]  数组变了 1 4 5
          // 但是 关键来了!!!!!!!!!!!!!!!
          // 进行寻址之后 我们的 high 和 low 没有 进行 递减 和 递增的操作, high还是2 low 还是 0
          //这样就形成了我们的死循环;窝草;
          //这样就被迫,我去思考一些基础性的问题;之前也遇到过 如 ++i 和 i++; 如 for 循环 和while 循环的区别;
        }

然后,这里我们再来复习一个非常简单的额问题;i++; 和 ++i;

i++; 先进行赋值,然后再进行累加;

我们来看一个以此产生的死循环;

        /// <summary>
        /// 如果这样写,tad的就变成了死循环哈
        /// </summary>
        /// <param name="n"></param>
        static void TestRecursion(int n)
        {
            if (n > 0)
            {
                Console.WriteLine(n);
                TestRecursion(n--); //先将n进行函数赋值进行运算,然后再n--;如果这样搞就是死循环啊;
            }
        }

fix(这样就好了)

        /// <summary>
        /// 如果这样写,tad的就变成了死循环哈
        /// </summary>
        /// <param name="n"></param>
        static void TestRecursion2(int n)
        {
            if (n > 0)
            {
                Console.WriteLine(n);
                TestRecursion2(--n); //先将n进行函数赋值进行运算,然后再n--;如果这样搞就是死循环啊;
            }
        }

然后,我们再来看一个取值的问题;

        static void TestWhile()
        {
            var arr = new[] {1,2,3,4};
            int len = arr.Length;
            var newArr = new int[len];
            int index = 0;

            var newArr1 = new int[len];
            int index1 = 0;


            for (int i = 0; i < len; i++)
            {
                if (arr[i] % 2 == 0)
                {
                    
                    newArr[++index] = arr[i]; //从结果中可以看出,++i 是先累加,在赋值
                    newArr1[index1++] = arr[i]; //从结果中可以看出,i++ 是先赋值,在累加

                }
            }

            //然后我们来看这两个的区别;
            Console.WriteLine("++index");
            foreach (int i in newArr)
            {
                Console.WriteLine(i);
            }

            Console.WriteLine("index++");
            foreach (int i in newArr1)
            {
                Console.WriteLine(i);
            }


        }

结果:

 

然后,我们看看,在while 中应用,主要是是在我们的快速排序中;也就是修复我们前面那个快速排序中的死循环;

 

        static void TestLoop()
        {
            //在快速排序的过程中遇到一个问题;
            var arr = new[] { 5, 4,1 };
            int len = arr.Length;
            int high = len - 1;
            int low = 0;

            //这里写个重负代码,主要为了,看得清楚一点;
            high = high + 1;
            low = low - 1;

            int middle = arr[1];

            while (low < high)
            {
                while (arr[--high] > middle  && low<high)  //先尽心一次自减。再取值;
                {
                    int xx = 0;
                }

                while (arr[++low] < middle && low < high) ////先尽心一次自加。再取值; //这样,保证,我们每一次遍历,都在前进;就想我们的for循环;知道low 遇到我们的i
                {
                    int xx = 0;
                }


            }

 

然后,我们再来看一个具体的实例优化;找到元素应该插入的位置;如:target =2; 在 0 1 中,应该插入的位置就是2;如果用for来实现;则会出现如下的代码;

 /// <summary>
        /// 找到元素应该在的正确元素;
        /// 考虑下面三种情况;
        /// 1.数组长度就是1;
        /// 2.找完了,都没找到;
        /// 找到,应该插入的位置;。。。shit优化;
        /// </summary>
        public static int FindRightPostion(int [] arr,int target)
        {
            int len = arr.Length;
            int position =0;  //如果没有找到,就应该在第一个位置;最后一个步,却加了1,这样。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。、
            bool isFind = false;
            //正向寻找;
            for(int i = 0; i < len; i++)
            {
                //最后一次没有进来;对,i就是我们的待插入的位置;不过,最后一次的条件没有进来;
                if (arr[i]<target)  //最后一个找到,肯定是不满足条件的的;
                {
                    position = i; //不满足条件的值,没有进入这个赋值;所以,最后合适的位置就是;position+1
                    isFind = true;
                }
                else
                {
                    break;
                }
            }
            if (isFind == false)
                return position;
            else
            return position+1;
        }

        /// <summary>
        /// 这种方式也不错滴啊;
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static int FindRightPostion2(int[] arr, int target)
        {
            int len = arr.Length;
            int position = 0;  
            for (int i = 1; i < len; i++)
            {
                if (arr[i] < target) 
                {
                    position = i; 
                }
                else
                {
                    break;
                }
            }
            return position == 0 ? 0 : position + 1;
        }

 

然后,如果用我们的while 来实现,这样的方式,代码,好了很多;(这样,就完美多了)

        /// <summary>
        /// 这样写,比较合适,出来的时候,pointer 恰好;执向的是下一个位置;
        /// </summary>
        /// <param name="arr"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static int FindeRightPostion(int [] arr,int target)
        {
            int len = arr.Length;
            int pointer = 0;
            while (pointer < len && arr[pointer] < target)
            {
                pointer++;
            }
            return pointer;

        }

 

 

总结:for 循环,更多用于一个完整的遍历; while 更多是带有终止条件的遍历;

 

posted @ 2018-01-08 14:26  咕-咚  阅读(4019)  评论(0编辑  收藏  举报