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

huangapple go评论65阅读模式
英文:

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

问题

Question: 查找节点是否位于节点root的左半子树或右半子树中。

Meaning of left half and right half: 假设节点root有n个子节点,每个子节点都有子树。

如果一个节点是从左到右编号为[1..(Math.floor(n/2))]的节点或是其中一个子树中的节点,那么它被认为位于root的左半子树中;否则,它位于root的右半子树中[(Math.floor(n/2) + 1)..n]

左半子树中的所有节点的key值都小于root,右半子树中的所有节点的key值都大于root

Idea: 预处理

对树进行中序遍历,并为adjacencyLists.node中的每个节点分配key(整数)。然后,在查询时比较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"
  }

Implementation:

var adjacencyLists = {
  root: 'A',
  nodes: {
    A: {
      id: 'A',
      connectedNodes: ['B', 'C']
    },
    // ... (其他节点的信息)
  }
}

var keyLookup = {};
var count = 0;

function inorderTraversalNumberingOfNodes(cur) {
  if (adjacencyLists.nodes[cur].connectedNodes.length) {
    // 递归左半子树
    for (let i = 0; i < Math.ceil(adjacencyLists.nodes[cur].connectedNodes.length / 2); i++) {
      inorderTraversalNumberingOfNodes(adjacencyLists.nodes[cur].connectedNodes[i]);
    }
    // 递归右半子树
    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)

// 查询节点是否位于根节点的左半部分或右半部分

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');

预期节点的key值: 对邻接列表进行中序遍历应为节点分配以下key值:

{
  "D": {
    "key": 1
  },
  "K": {
    "key": 3
  },
  "E": {
    "key": 4
  },
  "B": {
    "key": 2
  },
  // ... (其他节点的key值)
}

现在,在QUERY(A, D)上,输出应为queryNode is in left half of root,因为1 < 5。您之前未能获得预期的答案,因为未能正确分配节点的key值。

英文:

Question: To find whether a node is in the left half subtrees or the right half subtrees of a node root.


Meaning of left half and right half : Suppose a node root has n child and each of which has subtrees.

A node is said to be in the left half subtrees of root, if it is a node numbered [1..(Math.floor(n/2))] from left to right or it is a node in one of their subtrees, else it is in the right half subtrees of root [(Math.floor(n/2) + 1)..n].

All the nodes in the left half get key values less than root and all the nodes in the right half get key values greater than root.


Idea: Preprocessing

Do an inorder traversal of the tree and assign key(Whole numbers) to each node in adjacencyLists.node. Then on query, compare key values to determine whether a node is in the left half subtrees or right half subtrees:

Pseudo code:

QUERY(root, queryNode)
if (queryNode.key &lt; root.key) {
print &quot;queryNode is in left half of root&quot;
} else {
print &quot;queryNode is in the right half of root&quot;
}

Implementation:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

var adjacencyLists = {
root: &#39;A&#39;,
nodes: {
A: {
id: &#39;A&#39;,
connectedNodes: [&#39;B&#39;, &#39;C&#39;]
},
B: {
id: &#39;B&#39;,
connectedNodes: [&#39;D&#39;, &#39;E&#39;]
},
C: {
id: &#39;C&#39;,
connectedNodes: [&#39;F&#39;, &#39;G&#39;, &#39;H&#39;, &#39;Q&#39;, &#39;R&#39;]
},
D: {
id: &#39;D&#39;,
connectedNodes: []
},
E: {
id: &#39;E&#39;,
connectedNodes: [&#39;K&#39;]
},
F: {
id: &#39;F&#39;,
connectedNodes: [&#39;I&#39;]
},
G: {
id: &#39;G&#39;,
connectedNodes: [&#39;J&#39;, &#39;L&#39;, &#39;N&#39;, &#39;P&#39;]
},
H: {
id: &#39;H&#39;,
connectedNodes: [&#39;M&#39;, &#39;O&#39;]
},
K: {
id: &#39;K&#39;,
connectedNodes: []
},
I: {
id: &#39;I&#39;,
connectedNodes: []
},
J: {
id: &#39;J&#39;,
connectedNodes: []
},
L: {
id: &#39;L&#39;,
connectedNodes: []
},
M: {
id: &#39;M&#39;,
connectedNodes: []
},
N: {
id: &#39;N&#39;,
connectedNodes: []
},
O: {
id: &#39;O&#39;,
connectedNodes: []
},
P: {
id: &#39;P&#39;,
connectedNodes: []
},
Q: {
id: &#39;Q&#39;,
connectedNodes: []
},
R: {
id: &#39;R&#39;,
connectedNodes: []
},
}
}
var keyLookup = {};
var count = 0;
function inorderTraversalNumberingOfNodes(cur) {
if (adjacencyLists.nodes[cur].connectedNodes.length) {
// recurse left half subtrees
for (let i = 0; i &lt; 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 &lt; 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 &lt; 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(&#39;A&#39;, &#39;D&#39;);
query(&#39;M&#39;, &#39;C&#39;);

<!-- end snippet -->


Expected key values of nodes: An inorder traversal of the adjacency list should assign following key to nodes:

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

Now, on QUERY(A, D), the output should be queryNode is in left half of root, since 1 &lt; 5.

I don't get the expected answer since I am unable to assign correct key to nodes.

答案1

得分: 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')); // 或反之亦然...?
console.log(adjacencyLists);
.as-console-wrapper { max-height: 100% !important; top: 0; }
英文:

You could get the order first and then take the index value for getting the side.

<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
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(&#39;A&#39;)(&#39;A&#39;);
console.log(query(&#39;A&#39;, &#39;D&#39;)); // or vice versa ...?
console.log(adjacencyLists);

<!-- language: lang-css -->
.as-console-wrapper { max-height: 100% !important; top: 0; }
<!-- end snippet -->

huangapple
  • 本文由 发表于 2020年1月3日 19:08:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/59577515.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定