您的位置:首页 > 编程语言 > C#

c# for 和 while的区别

2018-01-08 14:26 411 查看
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 更多是带有终止条件的遍历;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: