让每一个值进行”车轮战”, 失败即停, 下位”选手”继续, 成功就不停, 车轮战战到最后, 排出最正确的 从小到大 或者 从大到小 的顺序

  1. 比如 一个简单五位数字的数组

    1. [1,3,2,5,4]
  2. 我们可以设置一个for循环来获取每个值

    1. 设置一个变量代表数组, 不同的语言有不同的写法, 以下以JS为例

      let numberArray=[1,3,2,5,4];
      
    2. 比如, 我们要想争抢谁最大(从小到大的排序), 可以写以下内容

      if(index1>index2){
      	//如果比下一位大, 跟它换位置
      	let max=index1;//将大值赋给max
      	let min=index2;//将小值赋给min
      	index1=min;//让下标在前的(小下标), 等于小值
      	index2=max;//让下标在后的(大下标), 等于大值
      }
      /*如何验证这个if的作用, 我们可以假设两组数据, [1,3],[4,2],
      	我们发现, 
      	1和3比, 没有3大, 直接无法进入if判断, 最大值在后面
      	4和2比, 会被调换位置, 变成 [2,4], 也是大值在后面
      	这样一来, 我们让从小到大的基础判断就做好了
      	*/
      
      • (回顾)老师, 我想从大到小怎么做? 好问题
  3. 添加第一层循环

    1. 让 最大或者最小的值 排到最后, 设置一个循环, 从index 0 到 数组的长度 -1

      for (var innerLoopIndex= 0; innerLoopIndex < numberArray.length-1;innerLoopIndex++){
      	console.log(innerLoopIndex);
      	/*依次打印 0,1,2,3,4 长度虽然是5, 但是下标index从0开始, 到3就会结束
      		总共进行4次对比, 因为第四次对比已经是第四位元素(index3)和第五位元素(index4)对比
      }
      
      1. 为什么长度要减一, 这是因为编程界主流语言的下标index都是从0开始, 我们对于for循环的变量 innerLoopIndex设置也是如此, 如果不想-1, 可以让innerLoopIndex从1开始
    2. 结合上面的if判断, 写出以下方法

      let numberArray=[1,3,2,5,4];
      for (var innerLoopIndex= 0; innerLoopIndex < numberArray.length-1;innerLoopIndex++){
      		if(numberArray[innerLoopIndex]>numberArray[innerLoopIndex+1]){
      			let max=numberArray[innerLoopIndex];//将大值赋给max
      			let min=numberArray[innerLoopIndex+1];//将小值赋给min
      			numberArray[innerLoopIndex]=min;//让下标在前的(小下标), 等于小值
      			numberArray[innerLoopIndex+1]=max;//让下标在后的(大下标), 等于大值
      		}
      }
      /*数组[1,3,2,5,4];
      第一次, 下标0和下标1的值对比, 不进if, 因为1没3大
      第二次, 下标1和下标2的值对比, 进if, 换位置, 数组发生变化, 
      	[1,2,3,..] 3和2调换位置, 3打赢了车轮战, 变成index2
      第三次, 下标2和下标3的值对比, 不进if, 因为3没5大
      第四次, 下标3和下标4的值对比, 进if, 换位置, 数组发生变化
      	[...,4,5] 5和4调换位置, 5打赢了车轮战, 变成index4
      */
      
    3. 我们发现, 这一个for循环后, 数组已然成功排序 [1,2,3,4,5], 那么我们的方法完善了吗, 我们多输入几个数组来验证

      1. 例如: numberArray2=[6,7,5,3,4,2]

      2. 我们发现, 经过我们的循环之后, 数组的顺序仍然不是按照从小到大的顺序排的, 这是因为, 我们内循环, 每次仅排出一位选手, 比如这次, 结果是

        console.log(numberArray2);
        //打印 [6,5,3,4,2,7]
        
    4. 其实它仅仅排出了”第一名”, 我们现在就来观看下变化的过程 (第一轮战斗)

      //[6,7,5,3,4,2]
      /*第一次, 6和7比, 没有进入if, 数组不变化
      	第二次, 7和5比, 7大, 进入if, 调换位置, 数组发生变化
      		[6,5,7...], 7和5的位置调换,7打赢了战斗, 变成index2
      	第三次, 7和3比, 7大, 进入if, 调换位置, 数组发生变化
      		[...3,7...], 7和3的位置调换,7打赢了战斗, 变成index3
      	第四次, 7和4比, 7大, 进入if, 调换位置, 数组发生变化
      		[...4,7...], 7和4的位置调换,7打赢了战斗, 变成index4
      	第四次, 7和2比, 7大, 进入if, 调换位置, 数组发生变化
      		[...2,7], 7和2的位置调换,7打赢了战斗, 变成index5
      	*/
      	//结果[6,5,3,4,2,7]
      
  4. 当我们想要排出所有的顺序, 其实就需要每个数字争抢第二名, 第三名, 我们可以添加外层循环, 控制第二轮战斗, 第三轮战斗, …直到排出你想要的顺序, 仍然以第一次数组为例, 我们已经排出第一名了

    第一轮战斗: 其实它仅仅排出了”第一名”, 我们现在就来观看下变化的过程 (第一轮战斗)

    即排出第二名需要什么, 需要让”争夺第一的失败数字”参加第二次战斗

    let numberArray=[6,7,5,3,4,2];
    **for(var outerLoopIndex=0;outerLoopIndex<2,outerLoopIndex++){**
    	for (var innerLoopIndex= 0; innerLoopIndex < numberArray.length-1;innerLoopIndex++){
    			if(numberArray[innerLoopIndex]>numberArray[innerLoopIndex+1]){
    				let max=numberArray[innerLoopIndex];//将大值赋给max
    				let min=numberArray[innerLoopIndex+1];//将小值赋给min
    				numberArray[innerLoopIndex]=min;//让下标在前的(小下标), 等于小值
    				numberArray[innerLoopIndex+1]=max;//让下标在后的(大下标), 等于大值
    			}
    	}
    }
    /*我们在最外层又增添了一个循环, 我们通过查看循环参数和结束循环条件, 发现一共可以循环两次
    	第一次, outerLoopIndex=0, 满足循环条件, 第二次, outerLoopIndex=1, 仍然满足条件, 当第二次后
    	outerLoopIndex++之后就变成了2, outerLoopIndex也就是2并不满足循环条件 "<2"小于2, 不能进入第三次循环
    	我们刚才说了, 外层循环控制战斗的轮数, 我们打断点来检查是否是这样的
    	当outerLoopIndex=0, 满足循环条件, 进入外层循环的执行层, 也就是外面for循环的里面, 我们可以看到
    	是另一个for循环, 也就是内层循环, 进入循环, 然后查看变量变化
    		下标为0的和下标为1的进行判断, 不满足
    		下标为1的和下标为2的....
    		我们发现, 这和之前看到的重复了, 也就是我们所说的 "第一轮"战斗
    		我们跳过这个块, 进入下一次外层循环, 第二次外层循环之前, 我们的数组已经发生变化,即
    			[6,5,3,4,2,7]
    		然后代入第二次外循环, 又是重复从index0开始比较
    			第二次外循环的第一次内循环, index0和index1比较, 6比5大, 满足判断条件, 进入if, 调换位置
    				6成为index1, 5成为index0, 数组变化为 [5,6...]
    			二外二内次, index1和index2比, 6>3 仍然满足条件, 进入if, 调换位置, 6成为index2, 
    				3成为index1, 数组变化为 [5,3,6...]
    			二外三内次, index2和index3比, 6>4 仍然满足条件, 进入if, 调换位置, 6成为index3,
    				4成为index2, 数组变化为 [...4,6...]
    			二外四内次, index3和index4比, 6>2 仍然满足条件, 进入if, 调换位置, 6成为index4, 
    				3成为index3, 数组变化为 [...2,6...]
    			二外五内次, index4和index5比, 6<7 不满足条件
    			经过多次的第二次外循环的内循环后, 我们发现, 数组最终为
    				[5,3,4,2,6,7]
    			也就是说, 第二次的外循环, 我们排出了第二名
    		*/
    
  5. 我们说外层的循环控制的是”车轮战”的场次, 一共N场, 分别争抢 第一名, 第二名…第N名, 我们可以通过多次检查来判断代码是否符合说法, 这次, 我们将外循环跳转为循环数组的长度次, 即排出所有的名次

    let numberArray=[6,7,5,3,4,2];
    for(var outerLoopIndex=**0**;outerLoopIndex<**numberArray.length-1**,outerLoopIndex++){
    	for (var innerLoopIndex= 0; innerLoopIndex < numberArray.length-1;innerLoopIndex++){
    			if(numberArray[innerLoopIndex]>numberArray[innerLoopIndex+1]){
    				let max=numberArray[innerLoopIndex];//将大值赋给max
    				let min=numberArray[innerLoopIndex+1];//将小值赋给min
    				numberArray[innerLoopIndex]=min;//让下标在前的(小下标), 等于小值
    				numberArray[innerLoopIndex+1]=max;//让下标在后的(大下标), 等于大值
    			}
    	}
    }
    /* 第一轮战斗分出第一名, 第二轮分出第二名, 我们先忽略, 看看每轮执行的结果是否符合预期
    		第一轮[6,5,3,4,2,7]
    		第二轮[5,3,4,2,6,7]
    		第三轮[3,4,2,5,6,7]
    		第四轮[3,2,4,5,6,7]
    		第五轮[2,3,4,5,6,7]
    		第六轮[2,3,4,5,6,7]
    		我们会发现, 当第五轮之后, 其实所有的值都和index0比过了, 即第五轮过后, index0已经是最小值
    	没有必要再让它和其他值对比, 而不同长度不同数量的数组怎么判断这个"第五轮", 其实就是长度-1轮
    	所以我们可以控制外层循环次数为 长度-1次, 但是由于我们的外层循环index是从0开始的, 那么我们的
    	循环条件可以写为
    			**for(var outerLoopIndex=0;outerLoopIndex<numberArray.length-1,outerLoopIndex++)** 
    		亦或者
    			**for(var outerLoopIndex=1;outerLoopIndex<numberArray.length,outerLoopIndex++)**
    		我们如果代入进每次的内循环会发现, 除了第一轮, 之后的每一轮好像都让我们的"选手"再次受伤,
    	明明第一次已经产生"第一名"了, 但是除了第一轮外的每一轮, 后续"选手"还和已经获得名次的选手匹配,
    		以下是"赛事记载":
    			第一轮, 没有名次, 值7在战斗多次后成功获得第一名的名次
    			但是第二轮的时候, 值6仍和第一名值7打
    				第三轮, 值5 仍和 有名次的 6,7打
    				第四轮, 值4 仍和 有名次的 5,6,7打
    				第五轮, 值3 仍和 有名次的 4,5,6,7打
    */
    
  6. 所以, "为了维护已得到名次的值的名誉, 为了保护弱小的值不再受伤", 我们决定剔除 "数组长度-1轮"和 "再次对比已有名次的值", 本次武林大赛, 做出以下更新;

    1. 外循环减少一次, 使得 “循环次数”为 数组长度-1
    2. 内循环递减, “不得和已获得名次的值再次比对”

    于是乎, 编码更新如下

    let numberArray=[6,7,5,3,4,2];
    for(var outerLoopIndex=**0**;outerLoopIndex<**numberArray.length-1**,outerLoopIndex++){
    	for (var innerLoopIndex= 0; innerLoopIndex < numberArray.length-**outerLoopIndex**-1;innerLoopIndex++){
    			if(numberArray[innerLoopIndex]>numberArray[innerLoopIndex+1]){
    				let max=numberArray[innerLoopIndex];//将大值赋给max
    				let min=numberArray[innerLoopIndex+1];//将小值赋给min
    				numberArray[innerLoopIndex]=min;//让下标在前的(小下标), 等于小值
    				numberArray[innerLoopIndex+1]=max;//让下标在后的(大下标), 等于大值
    			}
    	}
    }