一、递归法
1、解析/思路
children为Node指针数组
ret数组记录每个节点的val值
pos记录ret数组下一个待填入val值的下标
Recur函数功能:将root节点的val传入ret,并遍历其children
流程:
判断当前节点是否为空
为空 return
非空 记录当前节点val值 并且for循环遍历children
2、代码
void Recur(struct Node* root,int* ret,int* pos){
if(root==NULL) return;
ret[(*pos)++]=root->val;
for(int i=0;i<root->numChildren;i++){
Recur(root->children[i],ret,pos);
}
}
int* preorder(struct Node* root, int* returnSize) {
int * ret = (int *)malloc(sizeof(int) * 10000);
int pos=0;
Recur(root,ret,&pos);
*returnSize=pos;
return ret;
}
二、迭代法
1、解析/思路
Node栈:压入子节点尚未遍历完成的父节点
P_S_Top:栈顶下标
Flag栈:压入父节点即将遍历的下一个子节点下标
P_F_Top:栈顶下标
p指向当前节点
flag为当前p节点的即将遍历的子节点的下标
ret记录遍历的val值
流程:
判断root节点是否为空
为空 return
非空 p指向root节点 并记录val值
迭代开始
判断当前节点p即将遍历子节点下标flag是否小于其子节点个数
小于则说明当前节点p还有子节点未遍历
则将P_S_Top加1,当前节点p压入Node栈中
P_F_Top加1,flag+1压入Flag栈中(flag+1代表p下一遍历子节点)
p指向p[flag]
flag置为0(0当前p下一遍历子节点下标)
大于等于说明当前节点p无子节点
判断Node栈是否还有当前p节点的父节点(也就是Node栈是否为空)
非空则说明存在父节点
则将当前节点p指向Node栈顶,P_S_Top减1
flag=Flag栈顶元素,P_F_Top减1(Flag栈顶元素表示Node栈顶节点下一遍历子节点)
为空则说明当前节点p无父节点
无父无子表示遍历完成
补充:
1、最后的p节点一定指向root
2、只要理解了flag与p的关系,思路一目了然
2、代码
int* preorder(struct Node* root, int* returnSize) {
//Node栈
struct Node *P_Stack[10000];
int P_S_Top=-1;
//Flag栈
int P_Flag[10000];
int P_F_Top=-1;
//初始化
struct Node* p=root;
int flag=0;
int *ret=(int*)malloc(sizeof(int)*10000);
*returnSize=0;
if(root==NULL){
return ret;
}
p=root;
ret[(*returnSize)++]=p->val;
//迭代开始
while(1){
if(flag<p->numChildren){//还有未遍历的子节点,当前节点压栈,p指向子节点
P_Stack[++P_S_Top]=p;
P_Flag[++P_F_Top]=flag+1;
p=p->children[flag];
flag=0;
ret[(*returnSize)++]=p->val;
}
else{//没有待遍历的子节点,准备弹栈
if(P_S_Top!=-1){//栈不为空,p指向栈顶,并且弹栈
p=P_Stack[P_S_Top--];
flag=P_Flag[P_F_Top--];
}
else{//栈为空,程序结束
break;
}
}
}
return ret;
}