Algorithm 查找每个节点的大小
我在Algorithm 查找每个节点的大小,algorithm,recursion,graph,Algorithm,Recursion,Graph,我在1上有一棵树,我需要找到每个节点的大小。 我使用这个递归调用是为了 find_size(int curr , int parent){ S[curr]=1 for(int j:Children[curr]){ if(j==parent) continue; find_size(j,curr) S[curr]+=S[j]; } } 如何使用堆栈或其他方法将我
1
上有一棵树,我需要找到每个节点的大小。
我使用这个递归调用是为了
find_size(int curr , int parent){
S[curr]=1
for(int j:Children[curr]){
if(j==parent) continue;
find_size(j,curr)
S[curr]+=S[j];
}
}
如何使用堆栈或其他方法将我的解决方案简化为非递归的解决方案?由于递归解决方案不适用于大型数据集。我将描述一种可能的迭代方法,包括两个步骤:
对于步骤1:
- 最初,只将根节点添加到队列中,并用depth=0标记它
- 当队列不为空时,从队列中提取第一个节点,查看其深度(此处表示为
),并通过使用currentDepth
=childDepth
+1标记每个节点,将其子节点添加到队列的末尾currentDepth
- 按相反的深度顺序处理节点。节点的处理包括计算其子树大小,方法是将所有子节点的大小相加(当前节点加1)
- 请注意,每次处理一个节点时,子节点都已被处理(因为所有深度更高的节点都已被处理),因此我们已经知道子子树的大小
备注: 对于步骤2,通过使用一个我们从未从中实际删除元素的列表(例如,可以使用指针保持队列头,并且在轮询时只能增加该指针)实现步骤1中的队列,可以有效地按深度递减顺序对节点进行排序 以相反的顺序处理此列表是以递减的深度顺序遍历节点所需的全部。因此,实际上没有必要显式使用
深度
字段
上述想法的实施情况如下所示:
void find_size(){
//第一步
int队列[节点];
队列[0]=1;//在队列中添加根
int start=0;
int-end=1;
while(开始<结束){
int node=queue[start++];//从队列中轮询一个节点
对于(int i:Children[node]){//将其子项添加到末尾
队列[end++]=i;
}
}
//步骤2
对于(int i=end-1;i>=0;i--){
int节点=队列[i];
S[node]=1;
for(int j:子节点[节点]){
S[node]+=S[j];
}
}
}
您通过索引来表示节点,因此我猜您将它们表示为两个数组,如下所示:
int[]父项;//父项索引(根的父项为负,例如-1)
int[][]子项;//每个节点的子节点索引
您可以从叶节点开始收集和,并在知道所有子节点O(n)的结果后立即向上进行:
s=newint[parent.length];
int[]已处理=新int[parent.length];//正在处理的子级数
for(int i=0;i=0&&processed[j]==children[j].length){//所有子项都被处理
s[p]+=s[j];//调整家长分数
已处理的[p]+;//增加父节点的已处理子节点数
j=p;//父节点成为当前节点
p=parent[j];//其父对象为父对象
}
}
}
但是时间竞争性是O(N*N)
@NarendraModi它是O(N),编辑了答案,对根的检查丢失了。它在返回时模仿DFS的第二部分(因此从叶子而不是根开始),节点将以完全相同的顺序处理。