[JS] Javascript递归问题 | Javascript遍历方式

递归涉及的问题

JS函数传值

【机制】对象传值都是引用传值,原变量与函数参数变量之间有引用关系,即值改变,原变量的值也会改变
【例子】array,string属于对象,会改变;int不会改变
这里写图片描述
【注意!】递归时,许多时候都需要用到局部变量,而不能改变到外面的值。这时为了函数参数不受引用关系影响,就要深度赋值这些变量

function dfs(array) {
	if (? > limit) {
		return ;
	}
	var tmpArray = [];
	for (var i in array) { //解决对象引用传入问题
		tmpArray.push(array[i]);
	}
	//对tmpArray操作
	dfs(tmpArray); //传tmpArray
}

遍历方式

遍历数组、对象等一定要用以下方式迭代

for (var i in array) {
	array[i];
}

【错误】用以下方式有意想不到的错误,array不会被完全遍历到

for (var i=0; i<array.length; i++) {
	array[i];
}

【补充】jQuery环境建议使用$.each函数:

$.each(array,function(index,value){
	//index下标
	//value值
})

示例

问题背景

小明来到厦门旅游,发现有很多景点,一个景点有它的官方评分(满分:100)与建议游玩的时间(单位:min),现在小明只有480分钟旅游,请问小明一共有几种路线选择,求出各个路线经过 景点的编号数组 、 路线分数(景点总分/景点个数) 、 游玩时间

测试数据说明:
景点个数
景点编号 景点评分 景点时间

测试数据:
7
1 76.16926103 120
2 66.10810811 60
3 68.10293094 30
4 93.30696203 400
5 88.32278481 90
6 76.52360588 180
7 55.05713308 360

例如输出:
1,2 71.13868457 180
1,2,3 70.12676669 210

递归代码

for (var i in selectedSpotsBuffer_spots) { //不会执行递归
   	console.log("|从:"+i+"位开始");
   	dfs(i,initTime,initTotal,initRoute);
   }
   function dfs(z, time, total, route) {
   	var tmpRoute = [];
   	for (var i in route) {
   		tmpRoute.push(route[i]);
   	}
   	console.log("  dfs:"+z+" "+time+" "+total+" "+tmpRoute);
       var thisTime = selectedSpotsBuffer_spotsMap[ selectedSpotsBuffer_spots[z]+"" ].attributes["recommendtime"]; //取出当前点的时间与分数
       var thisTotal = selectedSpotsBuffer_spotsMap[ selectedSpotsBuffer_spots[z]+"" ].attributes["total"];
       console.log("  这一次"+thisTime+" "+thisTotal);
       if (time + thisTime > plannedTime) {
       	console.log("  time+thisTime="+(time+thisTime)+"退出");
           return ;
       }
       tmpRoute.push(selectedSpotsBuffer_spots[z]);
       time += thisTime;
       total += thisTotal;
       allRoute.push({ array : tmpRoute,
           time : time,
           total : total
       });
       console.log(" 这一次之后的allRoute情况:"+tmpRoute+" "+time+" "+total);
       for (var i in selectedSpotsBuffer_spots) {
       	if (i>z) {
       		dfs(i,time,total,tmpRoute);
       	}
       }
   }

完整代码

<html>
<head>
	<title>路线推荐算法</title>	
</head>
<body>
	<div id="output"></div>
</body>
<script type="text/javascript">
	//模拟项目中的数据
	var selectedSpots = [1]; //用户选择的景点
	var selectedSpotsBuffer_spots = [5,6,9,2,10,3]; //周边景点集
	var selectedSpotsBuffer_spotsMap =  { //景点的数据
		'1' : {
			attributes :  {
				id : 1,
				name :"白石炮台遗址",
				recommendtime:120,
				total:76.16926103,
				x:118.13214548600001,
				y:24.424820321000027
			}
		},
		'2' : {
			attributes :  {
				id : 2,
				name :"斋盛楼",
				recommendtime:0,
				total:66.10810811,
				x:118.1275653560001,
				y:24.42838708200003
			}
		},
		'3' : {
			attributes :  {
				id : 3,
				name :"厦门书法广场",
				recommendtime:30,
				total:0,
				x:118.11455650700009,
				y:24.430312792000052
			}
		},
		'5' : {
			attributes :  {
				id : 5,
				name :"厦门台湾民俗村",
				recommendtime:400,
				total:93.30696203,
				x:118.13572801700002,
				y:24.433014653000043
			}
		},
		'6' : {
			attributes :  {
				id : 6,
				name :"启明寺",
				recommendtime:90,
				total:88.32278481,
				x:118.11964657700003,
				y:24.434867303000033
			}
		},
		'9' : {
			attributes :  {
				id : 9,
				name :"金山松石景区",
				recommendtime:180,
				total:76.52360588,
				x:118.1344477560001,
				y:24.43688852300005
			}
		},
		'10' : {
			attributes :  {
				id : 10,
				name :"厦门台湾民俗村金山松石风景区",
				recommendtime:0,
				total:55.05713308,
				x:118.13357146600003,
				y:24.437024483000073
			}
		}
	};
	var allRoute = []; //存放所有的路线
	var plannedTime = 360; //计算的时间

	selectedSpotsBuffer_spots = insertSort(selectedSpotsBuffer_spots,selectedSpotsBuffer_spotsMap); //selectedSpotsBuffer_spots按分数排列
	console.log("排序之后:"+selectedSpotsBuffer_spots);

    var initTotal=0.0,initTime = 0;
    //初始化分数与时间,考虑已选的点
    var initRoute = [];
    for (var i=0; i<selectedSpots.length; i++) {
        initTotal += selectedSpotsBuffer_spotsMap[ selectedSpots[i]+"" ].attributes["total"]; //初始化的分数
        initTime += selectedSpotsBuffer_spotsMap[ selectedSpots[i]+"" ].attributes["recommendtime"]; //初始化的时间
        initRoute.push(selectedSpots[i]);
    }
    for (var i in selectedSpotsBuffer_spots) { //不会执行递归
    	console.log("|从:"+i+"位开始");
    	dfs(i,initTime,initTotal,initRoute);
    }
    function dfs(z, time, total, route) {
    	var tmpRoute = [];
    	for (var i in route) {
    		tmpRoute.push(route[i]);
    	}
    	console.log("  dfs:"+z+" "+time+" "+total+" "+tmpRoute);
        var thisTime = selectedSpotsBuffer_spotsMap[ selectedSpotsBuffer_spots[z]+"" ].attributes["recommendtime"]; //取出当前点的时间与分数
        var thisTotal = selectedSpotsBuffer_spotsMap[ selectedSpotsBuffer_spots[z]+"" ].attributes["total"];
        console.log("  这一次"+thisTime+" "+thisTotal);
        if (time + thisTime > plannedTime) {
        	console.log("  time+thisTime="+(time+thisTime)+"退出");
            return ;
        }
        tmpRoute.push(selectedSpotsBuffer_spots[z]);
        time += thisTime;
        total += thisTotal;
        allRoute.push({ array : tmpRoute,
            time : time,
            total : total
        });
        console.log(" 这一次之后的allRoute情况:"+tmpRoute+" "+time+" "+total);
        for (var i in selectedSpotsBuffer_spots) {
        	if (i>z) {
        		dfs(i,time,total,tmpRoute);
        	}
        }
    }
    //按成绩从大到小排序
    function insertSort(array,infoMap) {
        var i = 1,
            j, step, objectId, len = array.length;
        for (; i < len; i++) {
            step = j = i;
            objectId = array[j];
            while (--j > -1) {
                if (infoMap[array[j]+""]["attributes"]["total"] < infoMap[objectId+""]["attributes"]["total"]) {
                    array[j + 1] = array[j];
                } else {
                    break;
                }
            }
            array[j + 1] = objectId;
        }
        return array;
    }
</script>
</html>

这里写图片描述

问题记录

  1. 结果出错
    问题:递归时操作到全局对象,导致出错
    说明:
    这里写图片描述
    allRoute是一个数组,里面放了map,这是一个对allRoute赋值的语句。
    调试语句输出的情况是这样的
    这里写图片描述
    也就是说allRoute里有4个对象,每个对象值是后面相应的数值。
    这里写图片描述
    这里写图片描述
    但是结果,里面array的值全是一样,并且是最后一种1,6,2,10,3。而time,total值是正常的

  2. 遍历数组出错(只执行了一层,不会递归下去)
    说明:selectedSpotsBuffer_spots为数组
    问题:使用length遍历

     for (var j=z+1; j<selectedSpotsBuffer_spots.length; j++) {
     	console.log("  继续走");
     	dfs(j,time,total,tmpRoute);
     }
    

结果:
这里写图片描述
修改:

	for (var i in selectedSpotsBuffer_spots) {
    	if (i>z) {
    		dfs(i,time,total,tmpRoute);
    	}
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

geodoer

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值