二叉树的基础知识 C++实现 最简单的二叉树 二叉排序树 BFS和DFS

实现了一颗简单的二叉树的建立和访问
用递归和迭代实现BFS、DFS

最简单的构造、遍历一个二叉树

递归是容易写出来和理解的方式;
为了让树长得更均衡一点,一个?代表一个空节点;

这颗树的节点是一个character;

#include<iostream>
using namespace std; 
//树的一个节点
struct TreeNode {
    char data;
    TreeNode* leftNode;
    TreeNode* rightNode;
    TreeNode(char c) : data(c), leftNode(NULL), rightNode(NULL) {}
};

用递归的方式先序遍历这棵树;

void preOrder(TreeNode* root) {
    if (root == NULL) {
     //   cout << 66 << endl; 
        return;
    }
    cout << root->data << endl;
    preOrder(root->leftNode);
    preOrder(root->rightNode);
    return;
}

建造一颗二叉树;如果一直用先序的方法建造,最后这棵树会变成只有左子树;
所以读入一个?表示这是一个空节点,就会转而建造右子树;

TreeNode* build(int& posi, string s, int& n) {
    if (posi > n)return NULL;
    char c = s[posi++];
    if (c=='?')return NULL;
    TreeNode* t = new TreeNode(c);
    t->leftNode = build(posi, s, n);
    t->rightNode = build(posi, s, n);
    return t;
}

先读取一个字符串,然后用这个字符串建造一个二叉树;
建造完成后用先序遍历的方式打印他;
因为建造和打印的方式都是先序,所以输入和输出的顺序应该是一样的;
但是问号除外,因为把有问号的地方建造成了一个空节点。

int main() {
    int position = 0;
    string str;
    cin >> str;
    int n = str.size() - 1;
    TreeNode* t1 = build(position, str, n);
    preOrder(t1);
	return 0;
}

二叉排序树

构造一个二叉排序树。也使用递归的方法;
构造的同时把爸爸节点打印出来。

#include<iostream>
using namespace std; 
//树的一个节点
#define MAX 6
struct TreeNode {
    int data;
    TreeNode* leftNode;
    TreeNode* rightNode;
    TreeNode(int c) : data(c), leftNode(NULL), rightNode(NULL) {}
};

树的节点结构和刚才类似,除了数据类型变成了integer;
先序遍历的方法也没有变,除了格式做了一些调整;

void preOrder(TreeNode* root) {
    if (root == NULL) {
     //   cout << 66 << endl; 
        return;
    }
    cout << root->data << ',';
    preOrder(root->leftNode);
    preOrder(root->rightNode);
    return;
}

中序遍历,这样打印的二叉树才是由小到大的顺序;

void midOrder(TreeNode* root) {
    if (root == NULL) {
        //   cout << 66 << endl; 
        return;
     }
    midOrder(root->leftNode);
    cout << root->data <<' ';
    midOrder(root->rightNode);
    return;
}

建造一颗有顺序的二叉树,并且建造的时候打印出来建造的节点和他的爸爸节点。
当然啦是没必要打印的,只是为了能看到这棵树的结构是怎样的;

TreeNode* build(TreeNode* root, int x, int father) {
    if (root == NULL) {
        root = new TreeNode(x);
        cout << "in: "<< x<<endl;
        cout <<"                    father:"<< father << endl;
    }
    else if (x < root->data) root->leftNode = build(root->leftNode, x, root->data);
    else root->rightNode = build(root->rightNode, x, root->data);
    return root;
}

在main函数里建造一颗二叉排序树,并且用中序遍历和先序遍历的方法把他打印出来;
输入完数字后CTRL+Z表示输入完成;

int main() {
    int x = 0;

    TreeNode* t1 = NULL;
    while(cin>>x)t1=build(t1, x, -1);
    midOrder(t1);
    cout << endl;
    preOrder(t1);
	return 0;
}

最后的运行结果:
在这里插入图片描述

如果把这棵树画出来:
在这里插入图片描述

树的遍历方法——BFS DFS

树的遍历方法可以用深度和宽度两种方法。
(1)dfs
用递归的方法可以以前序、中序、后序三种方式搜索一颗树,上面用到的就是递归的方法。
非递归的方法可以用栈来实现,前序的非递归方法有两个编码思路:
访问栈顶,然后把他的左右节点入栈;
根节点入栈以后,进入循环。依次把栈里的内容弹出,然后把弹出的节点右节点和左节点入栈(如果不为空);

void preOrder(TreeNode* root) {
    if (!root) {
        cout << "empty tree";
        return;
    }
    stack<TreeNode*> s;
    s.push(root);
    while (!s.empty())
    {
        TreeNode* t = s.top();
        s.pop();
        cout << t->data;
        if (t->rightNode!=NULL)s.push(t->rightNode);
        if (t->leftNode!=NULL)s.push(t->leftNode);
    }
}

另一种思路是顺着左边的分支访问、入栈,直到遇到了空节点,就访问栈顶的右子树;
在循环里这个右子树也顺着左边的分支。

void preOrder(TreeNode* root) {
    stack<TreeNode*> s;
    TreeNode* p = root;
    while (p != NULL || s.empty() != NULL)
    {
        if (p != NULL) {
            cout << p->data;
            s.push(p);
            p = p->leftNode;
        }
        else {
            p = s.top();
            s.pop();
            p = p->rightNode;
        }
    }
}

(2)bfs
可以用队列实现。访问队头的结点,把他的左右子树加到队尾,这样就是一层一层的遍历了;

> void bfs(TreeNode* root) {
>     if (root == NULL)return;
>     queue<TreeNode*> q;
>     q.push(root);
>     while (!q.empty()) {
>         TreeNode* t;
>         t = q.front();
>         q.pop();
>         cout << t->data;
>         if (t->leftNode != NULL)q.push(t->leftNode);
>         if (t->rightNode != NULL)q.push(t->rightNode);
>     } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值