1、建树
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
//树节点
struct TreeNode{
int val;
TreeNode *left;//左孩子
TreeNode *right;//右孩子
TreeNode() :left(nullptr), right(nullptr) {}
};
//已单个节点插入的形式建立二叉搜索树
TreeNode* CreateTreeNode(TreeNode* node, int num){
//创建根节点
if(node == nullptr)
{
node = new TreeNode();
node->val = num;
return node;
}
if(num < node->val)
node->left = CreateTreeNode(node->left, num);
else if(num > node->val)
node->right = CreateTreeNode(node->right,num);
return node;
}
int main(){
vector<int>nums = {5,3,2,8,9,6,1,7};
TreeNode* node = nullptr;
for (int i = 0; i < nums.size(); i++)//建树
{
node = CreateTreeNode(node,nums[i]);
}
return 0;
}
2、前序遍历
前序遍历是访问根节点后,先对其左子树进行遍历后对其右子树进行遍历的一种遍历方式。
俗称:根左右
对图上二叉树遍历结果:{5,3,2,1,8,6,7,9}
2.1递归方式实现
void getDlr(vector<int>& ret, TreeNode* root){
TreeNode* p = root;
if(p)
{
ret.push_back(p->val);//根节点输出
getDlr(ret,p->left);//遍历左子树
getDlr(ret,p->right);//遍历右子树
}
}
//统一接口
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ret;
getDlr(ret,root);
return ret;
}
2.2迭代方式实现(利用栈)
vector<int> preorderTraversal(TreeNode* root) {
vector<int> ret;
TreeNode *p = root;
stack<TreeNode*> stk;
stk.push(p);
while(!stk.empty())
{
p = stk.top();
if(p == NULL)continue;
ret.push_back(p->val);//根节点输出
stk.push(p->right);//右孩子入栈
stk.push(p->left);//左孩子入栈
}
return ret;
}
由于栈为先入后出的数据结构,故先将右子树入栈,后将左子树入栈。
3、后序遍历
后序遍历是先对其左子树进行遍历后对其右子树进行遍历,直到左右子树都遍历完毕才访问根节点的一种遍历方式。
俗称:左右根
对图上二叉树遍历结果:{1,2,3,7,6,9,8,5}
3.1递归方式实现
void getLrd(vector<int>& ret, TreeNode* root){
if(root == NULL)return;
TreeNode* p = root;
getLrd(ret,p->left);//左
getLrd(ret,p->right);//右
ret.push_back(p->val);//根
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
getLrd(ret,root);
return ret;
}
3.2迭代方式实现(利用前序遍历)
vector<int> postorderTraversal(TreeNode* root) {
vector<int> ret;
TreeNode *p = root;
stack<TreeNode*> stk;
stk.push(p);
while(!stk.empty())
{
p = stk.top();
stk.pop();
if(p == NULL)continue;
ret.push_back(p->val);//根
stk.push(p->left);//左
stk.push(p->right);//右
}
//翻转
reverse(ret.begin(),ret.end());
return ret;
}
前序遍历的输出顺序为根左右,而后序遍历的输出顺序为左右根,我们只需调整一下前序遍历,将其变成根右左,然后翻转一下输出数组,即变成了左右根。
4、中序遍历
中序遍历是先对其左子树进行遍历后,左子树遍历完后访问根节点,然后对对其右子树进行遍历的遍历方式。
俗称:左根右
对图上二叉树遍历结果:{1,2,3,5,6,7,8,9}
4.1递归方式实现
void getLdr(vector<int>& ret, TreeNode* root){
if(root == NULL)return;
TreeNode* p = root;
getLdr(ret,p->left);//左
ret.push_back(p->val);//根
getLdr(ret,p->right);//右
}
vector<int> inorderTraversal(TreeNode* root) {
vector<int>ret;
getLdr(ret,root);
return ret;
}
4.2迭代方式实现
vector<int> inorderTraversal(TreeNode* root) {
stack<TreeNode*>stk;
vector<int>ret;
TreeNode* now = root;
while(now || !stk.empty())
{
while(now)//遍历完左子树
{
stk.push(now);
now = now->left;
}
ret.push_back(stk.top()->val);//访问根节点
now = stk.top()->right;//访问右子树
stk.pop();
}
return ret;
}