二叉树遍历时,递归法代码相对简单,递归法是方便程序员自身读取,其保存函数指针到栈等操作相比非迭代法来说,空间损耗严重。
递归法基本写法如下:
TreeNode * preordertraverse(TreeNode * root)
{
if(root==NULL)
{
return root;
}
//前序遍历可以执行的一些计算逻辑,注意是计算而不是判断逻辑
preordertraverse(root->left);
//中序遍历可以执行的一些计算逻辑,注意是计算而不是判断逻辑
preordertraverse(root->right);
//后序遍历可以执行的一些计算逻辑,注意是计算而不是判断逻辑
return root;
}
二叉树的数据结构在笔面试也是自己必须手写的,如下:
struct TreeNode
{
int val;
TreeNode * left;
TreeNode * right;
TreeNode(){};
TreeNode(int v):val(v),left(NULL),right(NULL){};
TreeNode(int v,TreeNode * &l,TreeNode * &r):val(v),left(l),right(r);
}
这里面之所以C++结构体可以使用构造函数,是因为C++的结构体本质上与函数没有区别,只是初始时结构体的访问类型为public。
前中后序遍历写法很多,但是统一写法有助于理解:
TreeNode * ordertraverse(TreeNode * root)
{
if(root == NULL)
{
return root;
}
stack<TreeNode *> st;
st.push(root);
while(!st.empty())
{
TreeNode * Node = st.top();
if(Node!=NULL)
{
st.pop()
st.push(Node); //后序遍历
st.push(NULL); //后序遍历
if(Node->right)
{
st.push(Node->right);
}
st.push(Node); //中序遍历
st.push(NULL); //中序遍历
if(Node->left)
{
st.push(Node->left);
}
st.push(Node); //前序遍历
st.push(NULL); //前序遍历
}else
{
st.pop();
//这里一般是定义个变量接收Node的节点,然后进行一定的逻辑
st.pop();
}
}
}
从代码可以发现,其实我们仅仅是使用了NULL来进行对节点访问的控制,当然这与栈的特性也有关。
层次遍历则是使用了队列的尺寸特性:
TreeNode* leverordertraverse(TreeNode * root)
{
if(root==NULL)
{
return root;
}
queue<TreeNode *> que;
que.push(root);
while(!que.empty())
{
int size = que.size();
for(int i = 0;i < size;i++)
{
TreeNode * Node = que.front();
que.pop();
if(Node->left)
{
que.push(root->left);
}
if(Node->right)
{
que.push(root->right);
}
//这里一般进行一些计算,比如每层第一个左叶子等
}
}
}
构造二叉树只有中序遍历和后序遍历结合、中序遍历和前序遍历结合,两者差距不大,仅是前、后序遍历删除当前父节点的方式有所区别,同时方法有很多,本文介绍常用整形和向量表示方式:
向量表达方式,不常用,且每次递归需要创建vector向量,开销较大。
TreeNode* createBinaryTree(vector<int> &preorder,vector<int> &inorder)
{
TreeNode * Node = new TreeNode(preorder[0]);
if(preorder.size()==0)
{
return NULL;
}else if(preorder.size()==1)
{
return Node;
}
int index = 0;
for(index;index<inorder.size();index++)
{
if(preorder[0]==inorder[index])
{
break;
}
}
vector<int> leftinorder(inorder.begin(),inorder.begin()+index);
vector<int> rightinorder(inorder.begin()+index+1,inorder.end());
vector<int> preorder_new(preorder.begin()+1,preorder.end());
Node->left = createBinaryTree(preorder_new,leftinorder);
Node->right = createBinaryTree(preorder_new,rightinorder);
return Node;
}
整形表示方式:
TreeNode * createBinaryTree(vector<int> preorder,int preleft,int preright,vector<int> inorder,int inorderleft,int inorderright)
{
TreeNode * Node = new TreeNode[preorder[preleft]];
if(preright == preleft)
{
return NULL;
}else if
{
return Node;
}
int index = 0;
for(;index<inorder.size();index++)
{
if(preorder[preleft]==inorder[index])
{
break;
}
}
inorderleft_left = inorderleft;
inorderleft_right = index;
inorderright_left = index + 1;
inorderright_right = inorderright;
preorderleft_left = preleft + 1;
preorderleft_right = preleft + 1 + (inorderleft_right-inorderleft_left);
preorderright_left = preleft + 1 + (inorderleft_right-inorderleft_left);
preorderright_right = preright;
Node->left = createBinaryTree(preorder,preorderleft_left,preorderleft_right,inorder,inorderleft_left,inorderleft_right);
Node->right = createBinaryTree(preorder,preorderright_left,preorderright_right,inorder,inorderright_left,inorderright_right);
return Node;
}