1.树的遍历
树的前序、中序后序遍历本质上其实差不多(如果用递归的方法),只需要改变递归时的语句顺序即可。(无非是中左右 左中右 左右中三种情况 ) 其实如果不固定左先于右子树的顺序会有更多种,但是左右子树其实也是等价的,为了算法的简洁性和一致性,规定左先于右。以先序遍历举例:首先判断结点是否为空,不为空将值放入数组,然后故技重施遍历左右子树。
下面是三种遍历方式,大差不差,挺简单的就不放LeetCode链接了。
void preorder(struct TreeNode *obj,int *result,int *returnS)
{
if(obj==NULL)
{
return;
}
result[(*returnS)++]=obj->val;
preorder(obj->left,result,returnS);
preorder(obj->right,result,returnS);
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
int *real_result=(int*)malloc(sizeof(int)*120);
*returnSize=0;
preorder(root,real_result,returnSize);
return real_result;
}
void middleTravel(struct TreeNode *obj,int *result,int *returnSize)
{
if(obj==NULL)
{
return;
}
middleTravel(obj->left,result,returnSize);
result[(*returnSize)++]=obj->val;
middleTravel(obj->right,result,returnSize);
}
int* inorderTraversal(struct TreeNode* root, int* returnSize){
int *result=(int*)malloc(sizeof(int)*120);
*returnSize=0;
middleTravel(root,result,returnSize);
return result;
}
void lastTravel(struct TreeNode *obj,int *result,int *returnSize)
{
if(obj==NULL)
{
return;
}
lastTravel(obj->left,result,returnSize);
lastTravel(obj->right,result,returnSize);
result[(*returnSize)++]=obj->val;
}
int* postorderTraversal(struct TreeNode* root, int* returnSize){
int *result=(int*)malloc(sizeof(int)*120);
*returnSize=0;
lastTravel(root,result,returnSize);
return result;
}
2.迭代法遍历
虽然递归很方便也很简单,但是它的时间复杂度还是有点高,如果将递归变成非递归,这种算法一定会借助栈的帮助。所以这里直接介绍统一迭代法。
栈是后进先出(LIFO),所以我们考虑遍历顺序就得反过来,首先遍历结点的右子树,并把值加入栈内,然后再将结点的值加进去,加完之后向栈内压入一个NULL,作为分隔符,然后再遍历左子树(原理同上)。最后出栈顺序就为中序遍历的顺序。