【问题标题】:In a tree with arbitrary number of children, find whether a node is in the left half subtrees or right half subtrees of a given node在具有任意数量子节点的树中,查找节点是在给定节点的左半子树还是右半子树中
【发布时间】:2020-01-03 11:08:04
【问题描述】:

问题:查找一个节点是在一个节点root的左半子树还是右半子树中。


左半边和右半边的含义:假设一个节点root有n个子节点,每个子节点都有子树。

如果一个节点是从左到右编号为[1..(Math.floor(n/2))] 的节点,或者它是它们的一个子树中的一个节点,则称该节点位于 root 的左半子树中,否则位于 root [(Math.floor(n/2) + 1)..n] 的右半子树中。

左半部分的所有节点的key 值都小于根,而右半部分的所有节点的key 值都大于根。


想法:预处理

对树进行中序遍历并将key(整数)分配给adjacencyLists.node 中的每个节点。然后查询时,比较key的值,判断一个节点是在左半子树还是右半子树:

伪代码:

QUERY(root, queryNode)
  if (queryNode.key < root.key) {
    print "queryNode is in left half of root"
  } else {
    print "queryNode is in the right half of root"
  }

实施:

var adjacencyLists = {
  root: 'A',
  nodes: {
    A: {
      id: 'A',
      connectedNodes: ['B', 'C']
    },
    B: {
      id: 'B',
      connectedNodes: ['D', 'E']
    },
    C: {
      id: 'C',
      connectedNodes: ['F', 'G', 'H', 'Q', 'R']
    },
    D: {
      id: 'D',
      connectedNodes: []
    },
    E: {
      id: 'E',
      connectedNodes: ['K']
    },
    F: {
      id: 'F',
      connectedNodes: ['I']
    },
    G: {
      id: 'G',
      connectedNodes: ['J', 'L', 'N', 'P']
    },
    H: {
      id: 'H',
      connectedNodes: ['M', 'O']
    },
    K: {
      id: 'K',
      connectedNodes: []
    },
    I: {
      id: 'I',
      connectedNodes: []
    },
    J: {
      id: 'J',
      connectedNodes: []
    },
    L: {
      id: 'L',
      connectedNodes: []
    },
    M: {
      id: 'M',
      connectedNodes: []
    },
    N: {
      id: 'N',
      connectedNodes: []
    },
    O: {
      id: 'O',
      connectedNodes: []
    },
    P: {
      id: 'P',
      connectedNodes: []
    },
    Q: {
      id: 'Q',
      connectedNodes: []
    },
    R: {
      id: 'R',
      connectedNodes: []
    },
  }
}

var keyLookup = {};
var count = 0;

function inorderTraversalNumberingOfNodes(cur) {
  if (adjacencyLists.nodes[cur].connectedNodes.length) {
    // recurse left half subtrees
    for (let i = 0; i < Math.ceil(adjacencyLists.nodes[cur].connectedNodes.length / 2); i++) {
      inorderTraversalNumberingOfNodes(adjacencyLists.nodes[cur].connectedNodes[i]);
    }
    // recurse right half subtrees
    for (let i = Math.ceil(adjacencyLists.nodes[cur].connectedNodes.length / 2); i < adjacencyLists.nodes[cur].connectedNodes.length; i++) {
      inorderTraversalNumberingOfNodes(adjacencyLists.nodes[cur].connectedNodes[i]);
    }
    count++;
    keyLookup[cur] = { key: count };
  } else {
    count++;
    keyLookup[cur] = {key : count };
  }
}

inorderTraversalNumberingOfNodes(adjacencyLists.root);
console.log(keyLookup)

// query to determine whether a node is in the left half or right half of root

function query(rootNodeId, queryNodeId) {
  if (keyLookup[queryNodeId].key < keyLookup[rootNodeId].key) {
    console.log(`query node ${queryNodeId} is in the left half of root node ${rootNodeId}`);
  } else {
    console.log(`query node ${queryNodeId} is in the right half of root node ${rootNodeId}`);
  }
}

query('A', 'D');
query('M', 'C');

节点的预期键值:邻接表的中序遍历应该为节点分配以下键:

{
  "D": {
    "key": 1
  },
  "K": {
    "key": 3
  },
  "E": {
    "key": 4
  },
  "B": {
    "key": 2
  },
  "I": {
    "key": 6
  },
  "F": {
    "key": 7
  },
  "J": {
    "key": 8
  },
  "L": {
    "key": 9
  },
  "N": {
    "key": 11
  },
  "P": {
    "key": 12
  },
  "G": {
    "key": 10
  },
  "M": {
    "key": 14
  },
  "O": {
    "key": 16
  },
  "H": {
    "key": 15
  },
  "Q": {
    "key": 17
  },
  "R": {
    "key": 18
  },
  "C": {
    "key": 13
  },
  "A": {
    "key": 5
  }
}

现在,在QUERY(A, D) 上,输出应该是queryNode is in left half of root,因为1 &lt; 5。

我没有得到预期的答案,因为我无法将正确的key 分配给节点。

【问题讨论】:

  • 问题是什么,上面的结果是什么意思?
  • 上述结果是adjacencyLists中key的期望值,分配给adjacencyLists.node中的每个节点。我做了一些修改,现在清楚了吗?
  • 我仍然对左右两侧的位置以及数字的含义有疑问。请添加想要的结果。
  • 好的,我将编辑问题并添加一些代码 sn-ps
  • 顺便说一句,我得到以下顺序:A:5 B:2 D:1 E:4 K:3 C:8 F:7 I:6 G:10 J:9 L:11 N : 12 P: 13 H: 15 M: 14 O: 16 Q: 17 R: 18

标签: javascript node.js algorithm data-structures tree


【解决方案1】:

您可以先获取订单,然后获取索引值。

var adjacencyLists = { root: 'A', nodes: { A: { id: 'A', connectedNodes: ['B', 'C'] }, B: { id: 'B', connectedNodes: ['D', 'E'] }, C: { id: 'C', connectedNodes: ['F', 'G', 'H', 'Q', 'R'] }, D: { id: 'D', connectedNodes: [] }, E: { id: 'E', connectedNodes: ['K'] }, F: { id: 'F', connectedNodes: ['I'] }, G: { id: 'G', connectedNodes: ['J', 'L', 'N', 'P'] }, H: { id: 'H', connectedNodes: ['M', 'O'] }, K: { id: 'K', connectedNodes: [] }, I: { id: 'I', connectedNodes: [] }, J: { id: 'J', connectedNodes: [] }, L: { id: 'L', connectedNodes: [] }, M: { id: 'M', connectedNodes: [] }, N: { id: 'N', connectedNodes: [] }, O: { id: 'O', connectedNodes: [] }, P: { id: 'P', connectedNodes: [] }, Q: { id: 'Q', connectedNodes: [] }, R: { id: 'R', connectedNodes: [] } } },
    index = 0,
    getOrder = parent => value => {
        if (!adjacencyLists.nodes[value].connectedNodes.length) {
            adjacencyLists.nodes[value].index = adjacencyLists.nodes[value].index || ++index;
        }
        adjacencyLists.nodes[value].connectedNodes.forEach(getOrder(value));
        adjacencyLists.nodes[parent].index = adjacencyLists.nodes[parent].index || ++index;
    },
    query = (a, b) => a === b
        ? 'middle'
        : adjacencyLists.nodes[a].index < adjacencyLists.nodes[b].index
            ? 'left'
            : 'right';

getOrder('A')('A');

console.log(query('A', 'D')); // or vice versa ...?
console.log(adjacencyLists);
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • getOrder('A')('A')线上有错字吗?
  • 不行,因为签名是交出一个父节点,是同一个节点。
  • ...?。答:queryNode 始终是rootNode 的后代
猜你喜欢
  • 1970-01-01
  • 2014-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多