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 更多是帶有終止條件的遍歷;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM