二叉树(创建与遍历)

递归建二叉树时遇到的问题:

#include <iostream>
#include <vector>
using namespace std;

typedef struct treenode{
    int val;
    struct treenode *left;
    struct treenode *right;
    treenode(int x): val(x), left(nullptr), right(nullptr) {} //默认结构体构造方法
}Tnode,*pnode;

void create_tree(pnode root, vector<int> &pre, vector<int> &mid, int a, int b, int c, int d)
{
    int tag = pre.at(a);
    root = new treenode(pre.at(a));
    // mid中第一次出现 tag的下标
    int flag = 0;
    for(int i = c; i<=d; i++)
    {
        if(mid.at(i) == tag)
        {
            flag = i;
            break;
        }
    }
    int left = flag - c;
    int right = d - flag;     // right + left = d-c +1
    if(left != 0)
    {
        create_tree(root->left, pre, mid, a+1, a+left, c, c+left-1);    //左子的  先序  中序
    }
    if(right != 0)
    {
        create_tree(root->right, pre, mid, a+left+1, b, c+left+1, d);   //
    }
}
void print_tree_pre(pnode root)
{
    if(root == nullptr)

        return;
    else{
        cout << root->val << ",";

        print_tree_pre(root->left);
        print_tree_pre(root->right);

    }
}
int main()
{
    vector<int> pre = {1,2,4,5,3,6,7};      // 中  左  右
    vector<int> mid = {4,2,5,1,6,3,7};      // 左  中  右
    pnode root = nullptr;
    create_tree(root,pre,mid,0,6,0,6);
    //print_tree_pre(root);
    cout << "Hello World!" << endl;
    cout << root->val << endl;
    return 0;
}

无法打印出1
原因:
传入指针做入参。
在子函数中改变指针指向 ,对main中指针指向不起作用, root任然为nullptr。
只有传入指针的地址 才能影响main中指针的指向。

想要改什么并且能在main中同步变,就要传入什么的地址。

例子:

#include <iostream>
using namespace std;

int m = 4;
void fun(int *p)
{
    p = &m;
    cout << *p <<endl;
}
int main(void)
{
    int a = 3;
    int *p = &a;
    fun(p); 			//4
    cout << *p << endl; //3
}

二叉树的代码修改后:

#include <iostream>
#include <vector>
using namespace std;

typedef struct treenode{
    int val;
    struct treenode *left;
    struct treenode *right;
    treenode(int x): val(x), left(nullptr), right(nullptr) {} //默认结构体构造方法
}Tnode,*pnode;

void create_tree(pnode *root, vector<int> &pre, vector<int> &mid, int a, int b, int c, int d)
{
    int tag = pre.at(a);
    *root = new treenode(pre.at(a));
    // mid中第一次出现 tag的下标
    int flag = 0;
    for(int i = c; i<=d; i++)
    {
        if(mid.at(i) == tag)
        {
            flag = i;
            break;
        }
    }
    int left = flag - c;
    int right = d - flag;     // right + left = d-c +1
    if(left != 0)
    {
        create_tree(&(*root)->left, pre, mid, a+1, a+left, c, c+left-1);    //左子的  先序  中序
    }
    if(right != 0)
    {
        create_tree(&(*root)->right, pre, mid, a+left+1, b, c+left+1, d);   //
    }
}
void print_tree_pre(pnode root)
{
    if(root == nullptr)

        return;
    else{
        cout << root->val << ",";

        print_tree_pre(root->left);
        print_tree_pre(root->right);

    }
}
int main()
{
    vector<int> pre = {1,2,4,5,3,6,7};      // 中  左  右
    vector<int> mid = {4,2,5,1,6,3,7};      // 左  中  右
    pnode root = nullptr;
    create_tree(&root,pre,mid,0,6,0,6);
    print_tree_pre(root);		//1,2,4,5,3,6,7
    cout << "Hello World!" << endl;
    //cout << root->val << endl;
    return 0;
}

运行成功

先序遍历栈实现

// 先序用栈
void print_tree_pre_no(pnode root)
{
    stack<pnode> a;
    pnode p = nullptr;
    a.push(root);
    while(!a.empty())
    {
        p = a.top();
        cout << a.top()->val <<",";
        a.pop();

        if(p->right)
            a.push(p->right);
        if(p->left)
            a.push(p->left);
    }
}

中序遍历栈实现

void print_tree_mid_no(pnode root)  //左  中  右
{
    stack<pnode> a;
    pnode p = root;
    do      //遍历p的过程
    {
        while(p!=nullptr)   //走到最左
        {
            a.push(p);
            p = p->left;
        }
        //  没有左了  打印当前  遍历右(p指向当前的右)
        cout << a.top()->val <<","; //最左       //7
        p = a.top()->right;         //遍历当前的右子树
        a.pop();
    }while(!a.empty() || p!=nullptr);
}

后序遍历栈实现

//	正常的顺序思维  
void print_tree_back_no(pnode root)  //左  右  中
{
    stack<pnode> a;
    pnode p = root;
    pnode last = nullptr;
    do      //遍历p的过程
    {
        B:
        while(p!=nullptr)   //走到最左
        {
            a.push(p);
            p = p->left;
        }

        A:
        p = a.top();         
        if(p->right == nullptr)//遍历当前的右子树
        {
            cout << a.top()->val << endl;
            a.pop();
            last = p;
            goto A;
        }
        else if(p->right == last)
        {
            cout << a.top()->val << endl;
            a.pop();
            last = p;
            goto A;
        }
        else    //p的左遍历完  遍历p的右
        {
            p = p->right;
            goto B;
        }
    }while(!a.empty() || p!=nullptr);
}

思路

对1
–2—3
4 5 6 7
要遍历p:
124入栈;

取p = 4,

p右为空,(p的左右遍历完了)
取p;
last 记录4;(上一个遍历的是4

取p = 2;

p右为55入栈;		// p = p->right; goto B;

取p = 5;

p右为空,(p的左右遍历完了)
取p;
last 记录5;(上一个遍历的是5

取p = 2;

p右为5;
上一个遍历过5了
取2;
last记录2

取p= 1;仿照上面完成遍历;

整理后代码:

void print_tree_back_no(pnode root)  //左  右  中
{
    stack<pnode> a;
    pnode p = root;
    pnode last = nullptr;
    do      //遍历p的过程
    {
        while(p!=nullptr)   //走到最左
        {
            a.push(p);
            p = p->left;
        }
        A:
        p = a.top();
        if(p->right == nullptr || p->right == last) //右子树遍历好了
        {
            cout << a.top()->val << endl;
            a.pop();
            last = p;
            goto A;
        }
        else    //p的左遍历完  遍历p的右
        {
            p = p->right;
        }
    }while(!a.empty());
}

如果想再去掉goto A;代码如下:

void print_tree_back_no(pnode root)  //左  右  中
{
    stack<pnode> a;
    pnode p = root;
    pnode last = nullptr;
    do		//因为跳出是在里面进行的  这个循环可以改成 while(1)
    {
        while(p!=nullptr)   //走到最左
        {
            a.push(p);
            p = p->left;
        }
        while(a.top()->right == nullptr || a.top()->right == last) //右子树遍历好了
        {
            cout << a.top()->val << ",";
            last = a.top();
            a.pop();
            if(a.empty())       //a空则遍历完了
                return;
        }
        p = a.top()->right;     //遍历p的右
    }while(!a.empty());		
}

顺序遍历 队列实现:

// 顺序遍历 队列实现
void print_tree_order_no(pnode root)
{
    queue<pnode> a;
    pnode p = root;
    a.push(p);
    while(!a.empty())
    {
        p = a.front();
        cout << p->val << ",";
        if(p->left != nullptr)	//不可以写成   !p->left  
            a.push(p->left);
        if(p->right != nullptr)
            a.push(p->right);
        a.pop();
    }
}

后序遍历的其他方法:

将二叉树转为镜像二叉树,顺序遍历镜像二叉树后再reverse();

//	以下为转镜像二叉树
void mirror(pnode root)
{
    stack<pnode> a;
    pnode p = root;
    a.push(root);
    while(!a.empty())
    {
        p = a.top();
        pnode tmp = p->left;
        p->left = p->right;
        p->right = tmp;
        a.pop();
        if(p->left!=nullptr)
            a.push(p->left);
        if(p->right!=nullptr)
            a.push(p->right);
    }
    cout << "验证:";
    print_tree_pre(root);
}

完整代码:

#include <iostream>
#include <vector>
#include <stack>
#include <queue>
using namespace std;

typedef struct treenode{
    int val;
    struct treenode *left;
    struct treenode *right;
    treenode(int x): val(x), left(nullptr), right(nullptr) {} //默认结构体构造方法
}Tnode,*pnode;

void create_tree(pnode *root, vector<int> &pre, vector<int> &mid, int a, int b, int c, int d)
{
    int tag = pre.at(a);
    *root = new treenode(pre.at(a));
    // mid中第一次出现 tag的下标
    int flag = 0;
    for(int i = c; i<=d; i++)
    {
        if(mid.at(i) == tag)
        {
            flag = i;
            break;
        }
    }
    int left = flag - c;
    int right = d - flag;     // right + left = d-c +1
    if(left != 0)
    {
        create_tree(&(*root)->left, pre, mid, a+1, a+left, c, c+left-1);    //左子的  先序  中序
    }
    if(right != 0)
    {
        create_tree(&(*root)->right, pre, mid, a+left+1, b, c+left+1, d);   //
    }
}
void print_tree_pre(pnode root)
{
    if(root == nullptr)

        return;
    else{
        cout << root->val << ",";

        print_tree_pre(root->left);
        print_tree_pre(root->right);

    }
}

// 先序用栈
void print_tree_pre_no(pnode root)
{
    stack<pnode> a;
    pnode p = nullptr;
    a.push(root);
    while(!a.empty())
    {
        p = a.top();
        cout << a.top()->val <<",";
        a.pop();

        if(p->right)
            a.push(p->right);
        if(p->left)
            a.push(p->left);
    }
}

void print_tree_mid_no(pnode root)  //左  中  右
{
    stack<pnode> a;
    pnode p = root;
    do      //遍历p的过程
    {
        while(p!=nullptr)   //走到最左
        {
            a.push(p);
            p = p->left;
        }
        //  没有左了  打印当前  遍历右(p指向当前的右)
        cout << a.top()->val <<","; //最左       //7
        p = a.top()->right;         //遍历当前的右子树
        a.pop();
    }while(!a.empty() || p!=nullptr);
}

void print_tree_back_no(pnode root)  //左  右  中
{
    stack<pnode> a;
    pnode p = root;
    pnode last = nullptr;
    do
    {
        while(p!=nullptr)   //走到最左
        {
            a.push(p);
            p = p->left;
        }
        while(a.top()->right == nullptr || a.top()->right == last) //右子树遍历好了
        {
            cout << a.top()->val << ",";
            last = a.top();
            a.pop();
            if(a.empty())       //a空则遍历完了
                return;
        }
        p = a.top()->right;     //遍历p的右
    }while(!a.empty());
}

// 顺序遍历 队列实现
void print_tree_order_no(pnode root)
{
    queue<pnode> a;
    pnode p = root;
    a.push(p);
    while(!a.empty())
    {
        p = a.front();
        cout << p->val << ",";
        if(!p->left)
            a.push(p->left);
        if(!p->right)
            a.push(p->right);
        a.pop();
    }
}

// 转镜像二叉树 先序遍历  再reverse

void mirror(pnode root)
{
    stack<pnode> a;
    pnode p = root;
    a.push(root);
    while(!a.empty())
    {
        p = a.top();
        pnode tmp = p->left;
        p->left = p->right;
        p->right = tmp;
        a.pop();
        if(p->left!=nullptr)
            a.push(p->left);
        if(p->right!=nullptr)
            a.push(p->right);
    }
    cout << "验证:";
    print_tree_pre(root);
}


int main()
{
    vector<int> pre = {1,2,4,5,3,6,7};      // 中  左  右
    vector<int> mid = {4,2,5,1,6,3,7};      // 左  中  右
    pnode root = nullptr;
    create_tree(&root,pre,mid,0,6,0,6);
    print_tree_pre(root);
    cout << "Hello World!" << endl;
    //cout << root->val << endl;

    cout << "先序:";
    print_tree_pre_no(root);
    cout << endl;

    cout << "中序:";
    print_tree_mid_no(root);
    cout << endl;

    cout << "后序:";
    print_tree_back_no(root);
    cout << endl;

    cout << "顺序:";
    print_tree_order_no(root);
    cout << endl;

    cout << "mirror\n";
    mirror(root);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值