如何从一个非随机但是数学的顺序中选择一个数组

时间:2017-04-30 03:36:49

标签: javascript

我可以在没有公式的情况下完成此任务,但我正在努力创建一个数组选择方法,可以选择我称之为几乎随机的方法。原因是当数组以2的幂增长时,我需要选择一个。数组索引的内容无关紧要。

[0] // select index 0
[0,1] // select index 1 then 0
[0,1,2,3] // 3, 1, 2, 0
[0,1,2,3,4,5,6,7] // 7, 3, 5, 1, 6, 2, 4, 0
[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] // 15,7,11,3,13,5,9,1,14,6,12,4,10,2,8

我终于想出了这个模式,因为当数组扩展超过2的幂时它不会降级。选择保持不变。这与排序数组无关,而只是按特定顺序选择预​​排序数组。我已经看了很多可能的解决方案但是已经有一段时间了,因为我已经做了认真的数学运算,我确信这需要。

我能看到的模式并不明显,但我会尝试解释一下。它与二叉树有关。在root上你有[0]

                     [0]
                    [0,1]
                  [0,1,2,3]
               [0,1,2,3,4,5,6,7]
   // for example
                ___ 20 ___
               /          \
              10          30
            /    \       /    \
           5      15    25    35
          / \    / \    / \   / \
         1   7  12 18  23 27 31  37

我需要创建一个第三个数组,该数组具有正确的插入顺序而不会导致重新平衡。

[20,30,10,35,15,25,5,37,18,27,7,31,12,23,1]

此选择模型继续与Btree一起增长,这会导致树不能通过在自平衡树中插入这些值来重新平衡。

2 个答案:

答案 0 :(得分:1)

如果另一个数组实际上是一个AVL树,下面的函数会将一个已排序的数组按顺序推送到另一个数组中。它不是最有效的,但它显示了如何完成它的一个例子。

var sorted = [1, 5, 7, 10, 12, 15, 18, 20, 23, 25, 27, 30, 31, 35, 37];
console.log("sorted: ", sorted)

function insertBalanced(sortedArray, avlTree) {
  var size = sortedArray.length;
  var result = avlTree;
  var indexesUsed = [];
  function halfIndexes(depth) {
var slices = Math.pow(2, depth);
for(var i = 1; i < slices;i++) {
  var nextIndex = Math.floor(size * i / slices);
  if (!indexesUsed.includes(nextIndex)) {
    indexesUsed.push(nextIndex);
    result.push(sortedArray[nextIndex]);
  }
}
if (indexesUsed.length < size) {
  halfIndexes(depth + 1);
}
  };
  return halfIndexes(1);
}
var someEmptyAvlTree = [];
insertBalanced(sorted, someEmptyAvlTree);
console.log("avlTree", someEmptyAvlTree);

答案 1 :(得分:0)

我最终找到了一个更好的休闲模式,这在代码中更容易实现。它也不会降低。我会说DMoses方法也同样重要。我最终发现赔率甚至指数轮换的模式有所帮助。

            root             40
                  /                        \
                20                          60 
           /            \              /          \
           10           30           50           70
         /    \       /    \       /    \        /     \
        5     15     25    35     45    55      65     75
       / \   /  \   / \    / \   /  \   /  \   /  \   /  \
      3  7  12  17 23  27 33 37 43  47 52  57 62  67 72  77

首先将每一行分成一个数组。如果从平衡的BTree中拉出,则阵列已经被排序为最小到最大。

这是我使用的实际代码。

// array holding all elements
const allArray = [[40],[20,60],[10,30,50,70],[5,15,25,35,45,55,65,75],
                 [3,7,12,17,23,27,33,37,43,47,52,57,62,67,72,77]];
// create sorted reverse index array
const refA = [];
for (let i = 0; i < allArray.length; i++) {
    refA.push([]);
    for(let j = allArray[i].length - 1; j >= 0; j--) {
        refA[i].push(j);
    }
}
const fillRefA = (prev: number[], current: number[]): number[] => {
    const a = [];
    const prefAOdds = prev.filter((val: number) => (val % 2) !== 0);
    const prefAEvens = prev.filter((val: number) => (val % 2) === 0);
    const currentAOdds = current.filter((val: number) => (val % 2) !== 0);
    const currentAEvens = current.filter((val: number) => (val % 2) === 0);
    const newAOdds = currentAOdds.filter((val: number) => !prefAOdds.includes(val));
    const newAEvens = currentAEvens.filter((val: number) => !prefAEvens.includes(val));

    for (let i = 0; i < prefAOdds.length; i++) {
        a.push(newAOdds[i]);
        a.push(prefAOdds[i]);
    }
    for (let i = 0; i < prefAOdds.length; i++) {
        a.push(newAEvens[i]);
        a.push(prefAEvens[i]);
    }
    return a;
};

for (let i = 2; i < refA.length; i++) {
    refA[i] = fillRefA(refA[i - 1], refA[i]);
}
// Then finally put all the arrays into a master array in order of proper insertion.
const final = [];
for (let i = 0; i < allArray.length; i++) {
    for (let j = 0; j < allArray[i].length; j++) {
        final.push(a[i][refA[i][j]]);
    }
}

//为了解释这里发生了什么,我可以展示一个简短的索引路径。

//first you cannot work this method on the first item so you need to start at index of 2
// second you have to break evens and odds up but keep the order of previous insertion
[1,0] // odds [1], evens [0]
[3,2,1,0] // odds [3,1], evens [1,0];
// but extract previous array odds and evens 
// so [3], [2]. and you have the previous odds and evens [1], [0]
// and insert them in order, odds then evens. 
[3,1,2,0]
// again with the next row
[7,5] [6,4] [3,1] [2,0]
[7,3,5,1,6,2,4,0] // first you take the current then the previous
// and the next row. 
  [15,13,11,9] [14,12,10,8] [7,3,5,1] [6,2,4,0]
  [15,7,13,3,11,5,9,1,14,6,12,4,10,2,8,0]

// This way no same node is on a branch is filled up before all nodes
// on the row at least have 1 filled then continue filling the leftovers.
// final insertion array
[40,60,20,70,30,50,10,75,35,55,15,65,25,45,5,77,37,67,17,57,27,47,
7,72,33,62,23,52,12,43,3]