Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 生成字符串排列的递归函数 //==================================================== 函数getPermutations(str){ //内部递归函数permutate()使用的封闭数据: var permutations=[],//生成的置换存储在此处 nextWord=[],//下一个单词在这里建立 chars=[]//每个递归级别的集合 ; //--------------------- //将单词或数字拆分为字符数组 如果(typeof str==='string')chars=str.split(“”); else if(typeof str=='number'){ str=str+“”;//将数字转换为字符串 chars=str.split(“”);//将字符串转换为字符数组 } //================两个声明======== 置换(chars); 返回置换; //==================发动机罩下=========== 函数置换(chars){//递归:生成置换 if(chars.length==0)置换.push(nextWord.join(“”)); 对于(变量i=0;i_Javascript_String - Fatal编程技术网

Javascript 生成字符串排列的递归函数 //==================================================== 函数getPermutations(str){ //内部递归函数permutate()使用的封闭数据: var permutations=[],//生成的置换存储在此处 nextWord=[],//下一个单词在这里建立 chars=[]//每个递归级别的集合 ; //--------------------- //将单词或数字拆分为字符数组 如果(typeof str==='string')chars=str.split(“”); else if(typeof str=='number'){ str=str+“”;//将数字转换为字符串 chars=str.split(“”);//将字符串转换为字符数组 } //================两个声明======== 置换(chars); 返回置换; //==================发动机罩下=========== 函数置换(chars){//递归:生成置换 if(chars.length==0)置换.push(nextWord.join(“”)); 对于(变量i=0;i

Javascript 生成字符串排列的递归函数 //==================================================== 函数getPermutations(str){ //内部递归函数permutate()使用的封闭数据: var permutations=[],//生成的置换存储在此处 nextWord=[],//下一个单词在这里建立 chars=[]//每个递归级别的集合 ; //--------------------- //将单词或数字拆分为字符数组 如果(typeof str==='string')chars=str.split(“”); else if(typeof str=='number'){ str=str+“”;//将数字转换为字符串 chars=str.split(“”);//将字符串转换为字符数组 } //================两个声明======== 置换(chars); 返回置换; //==================发动机罩下=========== 函数置换(chars){//递归:生成置换 if(chars.length==0)置换.push(nextWord.join(“”)); 对于(变量i=0;i,javascript,string,Javascript,String,nextWord.pop()如何被多次调用? 不会置换(字符片(1));不让nextWord.pop()执行,因为它将带您返回到permutate函数的顶部 另外,当chars从调用其上的slice变为空时,permutate(chars.slice(1));谁又在填充字符?是否由nextWord.pop()填充字符;因为pop正在将值返回给置换函数 在chrome调试器中单步执行此代码并不清楚。它将在premutate()返回后执行。但我想从代码上看这是显而易见的。我想你的问题是,premut

nextWord.pop()如何被多次调用? 不会置换(字符片(1));不让nextWord.pop()执行,因为它将带您返回到permutate函数的顶部

另外,当chars从调用其上的slice变为空时,permutate(chars.slice(1));谁又在填充字符?是否由nextWord.pop()填充字符;因为pop正在将值返回给置换函数


在chrome调试器中单步执行此代码并不清楚。

它将在
premutate()返回后执行。但我想从代码上看这是显而易见的。我想你的问题是,premutate怎么能再回来?答案是查看
for
循环

因为我们每次调用
premutate()
时少了一个字符。在某个时刻,我们对
premutate()
的一个调用将使用空数组进行调用,这是有道理的:

//====================================================
function getPermutations(str){
    //Enclosed data to be used by the internal recursive function permutate():
    var permutations = [],  //generated permutations stored here
        nextWord = [],      //next word builds up in here     
        chars = []          //collection for each recursion level
    ;
    //---------------------
    //split words or numbers into an array of characters
    if (typeof str === 'string') chars = str.split(''); 
    else if (typeof str === 'number') {
      str = str + ""; //convert number to string
      chars = str.split('');//convert string into char array
    }
    //============TWO Declaratives========
    permutate(chars);
    return permutations;
    //===========UNDER THE HOOD===========
    function permutate(chars){ //recursive: generates the permutations
        if(chars.length === 0)permutations.push(nextWord.join(''));            
        for (var i=0; i < chars.length; i++){
            chars.push(chars.shift());  //rotate the characters
            nextWord.push(chars[0]);    //use the first char in the array            
            permutate(chars.slice(1));  //Recurse: array-less-one-char
            nextWord.pop();             //clear for nextWord (multiple pops)
        }
    }
    //--------------------------------
}//==============END of getPermutations(str)=============
现在,让我们看看发生这种情况时会发生什么:

premutate([]); // happens when chars.slice(1) gives us an empty array
chars.slice(1)
是从位置1开始的字符数组
chars
,即第二个字符,因此调用
permutate(chars.slice(1))以少1个字符的方式递归

最后,
chars.slice(1)
将返回零个字符,此时
permutations.push(nextWord.join(“”))i
的初始值为
0
chars.length
也为零时,代码>将被执行,并且
for(var i=0;ii
将已经为假

所以这个递归函数的终止条件是当它在当前字中用完字符时


permutate
函数最终返回时,
nextWord.pop()
将在每次调用
permutate
时被调用一次。

递归调用
permutate
位于循环内,每次执行时都将其放在调用堆栈上。多次调用
nextWord.pop
,以完成堆栈上的每个递归调用。您可以使用此工具可视化递归。如果您有Webstorm之类的工具,可以在调试器中运行它,以查看在第一次调用
nextWord.pop
时堆栈中有三个permutate()调用

调用permutate不会将您重置在permutate的顶部。(正如joe所提到的)它只需等待这个子调用完成,然后继续执行该方法

我认为您的递归置换可以简化:

function permutate(chars){
    if(chars.length === 0)permutations.push(nextWord.join(''));
    for (var i=0; i < chars.length; i++){
        chars.push(chars.shift());
        nextWord.push(chars[0]);
        permutate(chars.slice(1));  // This have returned..
        nextWord.pop();             // so execute this line
    }

    // and return so that other calls to us can also execute pop()
}
//假设input=“abc”
置换(chars){
if(chars.length==2)返回[chars,chars[0]+chars[1]};
var arr=permutate(chars.slice(1))//返回[“bc”,“cb”]
var out=[]
对于(变量i=0;i
对于那些因为涉及递归而无法理解这一点的人,我发现了一个页面,该页面使用交互式动画演示了算法流程


只需单击“播放”并观察变量的变化,同时排列函数不断调用自身。还可以观察何时找到新排列以及何时将其添加到结果排列数组中。

您接受答案了吗?
function permutate(chars){
    if(chars.length === 0)permutations.push(nextWord.join(''));
    for (var i=0; i < chars.length; i++){
        chars.push(chars.shift());
        nextWord.push(chars[0]);
        permutate(chars.slice(1));  // This have returned..
        nextWord.pop();             // so execute this line
    }

    // and return so that other calls to us can also execute pop()
}
// suppose input = "abc"
permutate(chars) {
  if(chars.length === 2) return [chars, chars[0] + chars[1]};
  var arr = permutate(chars.slice(1)) // returns ["bc", "cb"]
  var out = []    
  for (var i=0; i < arr.length; i++) {
    for (var j = 0; j < chars.length - 1; ++j) {
      out.push(arr[i].split(0,j) + chars[0] +  arr[i].split(j)) // "a" gets inserted at every possible position in each string
    }
  }
  // result here is ["abc", "bac", "bca", "acb", "cab", "cba"]
  return out
}
function permutate(left, used, result) { 
    // If there are no more characters left to permute 
    if (0 == left.length) { 
       result.push(used); 
    } 

    // Iterate over all characters in the 'left' string
    for (var i = 0; i < left.length; ++i) { 
       // Read the character we are going to work with in this iteration 
       var iObject = left[i]; 

       // Create a new_left string that contains all the characters 
       // of the 'left' string without the one we are going to use now 
       var new_left = ''; 
       for (j = 0; j < left.length; ++j) { 
          if (j != so.i) new_left += so.left[j]; 
       } 

       // Create a new_used string that has all the characters of 'used'  
       // plus the one we are going to use now 
       var new_used = so.used + iObject; 

       // Call permute with new_left and new_used strings 
       permutate(new_left, new_used, result); 
    } 
} 
permutate('abcd', '', []);