• 二叉树创建,递归遍历,非递归遍历


    二叉树


    博主是一个大一刚刚放暑假的大学生,大学我们只学习了c语言,现在这么卷只学c语言肯定不够,所以博主打算从零开始恶补c++顺便写文章记录一下,另外博主这个暑假还想记录一些算法基础内容欢迎关注哦。这些是是一些算法的记录和整理总结笔记要是什么时候忘记了这个算法那个算法怎么做就重新来看看,在csdn上面发是为了利用网址来编写思维导图的话比! 较方便~~~如果大家想跟着我一起学习也可以关注我~或者给这个文章点赞~~~谢谢大家了~

    请添加图片描述


    二叉树的初始化

    首先我们要先声明一个二叉树类里面要有数据节点,左节点,右节点

    #include 
    #include 
    using namespace std;
    
    class BinaryTree
    {
    public:
        char data;
        BinaryTree* left;
        BinaryTree* right;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    二叉树的创建

    递归创建二叉树(‘#’表示节点为空):

    void CreatBinaryTree(BinaryTree* &root) {//就相当于建立了一个root指针然后让root指针当一个tree的别名,root指针的本质就是对象指针
    	char c;
    	cin >> c;
    	if (c == '#')	//当遇到#时,令树的根节点为NULL,从而结束该分支的递归
    		root = NULL;
    	else
    	{
    		root = new BinaryTree;//用指针存放new出来的对象的地址这个指针就相当于新对象的指针。
    		root->data = c;	//指针指向对象中的data也可以写成(*root).data
    		CreatBinaryTree(root->left);//递归构建左子树
    		CreatBinaryTree(root->right);//递归构建右子树
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    二叉树的遍历

    前序遍历二叉树(先根再左再右)

    //前序遍历二叉树
    
    void Preorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		path.push_back(root->data);//在vector的末尾添加一个数就是按序排列(后来的插在后面)
    		Preorder(root->left, path);//访问左儿子
    		Preorder(root->right, path);//访问右儿子
    	}
    }//调用完了vector中就有数字了~
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    中序遍历二叉树(先左再根再右)

    //中序遍历二叉树
    
    void Inorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		Preorder(root->left, path);//访问左儿子
            path.push_back(root->data);//在vector的末尾添加一个数就是按序排列(后来的插在后面)
    		Preorder(root->right, path);//添加右儿子
    	}
    }//调用完了vector中就有数字了~
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    后序遍历二叉树(先左再右再根)

    //后序遍历二叉树
    
    void Postorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		Preorder(root->left, path);//访问左儿子
            Preorder(root->right, path);//访问右儿子
            path.push_back(root->data);//在vector的末尾添加这个节点 就是按序排列(后来的插在后面)
    		
    	}
    }//调用完了vector中就有数字了~
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    整个代码如下

    #include
    #include
    
    using namespace std;
    
    //声明类
    class BinaryTree {
    public:
    	char data;
    	BinaryTree* left, * right;
    };
    
    //按照前序遍历创建二叉树
    void CreatBinaryTree(BinaryTree* &root) {//就相当于建立了一个root指针然后让root指针当一个tree的别名,root指针的本质就是对象指针
    	char c;
    	cin >> c;
    	if (c == '#')	//当遇到#时,令树的根节点为NULL,从而结束该分支的递归
    		root = NULL;
    	else
    	{
    		root = new BinaryTree;//用指针存放new出来的对象的地址这个指针就相当于新对象的指针。
    		root->data = c;	//指针指向对象中的data也可以写成(*root).data
    		CreatBinaryTree(root->left);//递归构建左子树
    		CreatBinaryTree(root->right);//递归构建右子树
    	}
    }
    
    void PrintBinaryTree(vector<int> path);//声明打印二叉树函数
    
    //前序遍历二叉树
    
    void Preorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		path.push_back(root->data);//在vector的末尾添加一个数就是按序排列(后来的插在后面)
    		Preorder(root->left, path);//访问左儿子
    		Preorder(root->right, path);//访问右儿子
    	}
    }//调用完了vector中就有数字了~
    
    //中序遍历二叉树
    
    void Inorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		Inorder(root->left, path);//访问左儿子
            path.push_back(root->data);//在vector的末尾添加一个数就是按序排列(后来的插在后面)
    		Inorder(root->right, path);//添加右儿子
    	}
    }//调用完了vector中就有数字了~
    
    //后序遍历二叉树
    
    void Postorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		Postorder(root->left, path);//访问左儿子
            Postorder(root->right, path);//访问右儿子
            path.push_back(root->data);//在vector的末尾添加这个节点 就是按序排列(后来的插在后面)
    
    	}
    }//调用完了vector中就有数字了~
    //打印函数
    void PrintBinaryTree(vector<char> path) {
    	int n = path.size();
    	for (int i = 0;i < n;++i) {
    		cout << path[i]<<' ';
    	}
    	cout<<endl;
    }
    
    
    int main()
    {
    	vector<char> path1, path2, path3;
    	cout << "请使用前序遍历创建二叉树(若节点为空输入#代替):" << endl;
    	BinaryTree* root = NULL;
    	CreatBinaryTree(root);
    	cout << "二叉树创建完成!" << endl;
    	cout << "前序遍历二叉树结果为:" << endl;
    	Preorder(root, path1);
    	PrintBinaryTree(path1);
    	cout << "中序遍历二叉树结果为:" << endl;
    	Inorder(root, path2);
    	PrintBinaryTree(path2);
    	cout << "后序遍历二叉树结果为:" << endl;
    	Postorder(root, path3);
    	PrintBinaryTree(path3);
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92

    输出结果为:

    请添加图片描述

    这样二叉树最简单的部分就学完了~~

    测试数据:

    1
    2
    3
    # #
    4
    # #
    5
    6
    # #
    7
    # #
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    二叉树的非递归遍历:

    非递归先序遍历

    怎么实现?先准备一个栈,然后把头解点放进去

    1. 从栈中弹出一个节点
    2. 打印处理节点
    3. 先右再左
    4. 重复
    //先序遍历非递归
    void preOrderUnRecur (BinaryTree root){
        cout<< "非递归先序遍历" << endl;
    	BinaryTree *root1 = new BinaryTree;
    	*root1 = root;
        if (root1 != NULL)
        {
    		
    		stack<BinaryTree> stack;
    		stack.push(*root1);
    		while (!stack.empty())
    		{
    
    			*root1 = stack.top();
    			stack.pop();
    			cout << root1->data <<' ';
    			if (root1->right != NULL)
    			{
    				stack.push(*root1->right);
    			}
    			if (root1-> left != NULL)
    			{
    				stack.push(*root1->left);
    			}
    		}
    		cout<< endl; 
                
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    非递归后序遍历

    • 先序遍历的顺序不是头左右嘛,把左右换一下不就是头右左了嘛把头右左压到另一个栈里面不就是左右头了嘛,左右头不就是后序遍历了嘛~ 再把那个栈输出一遍不就完事了嘛~
    //后序遍历非递归
    void postOrderUnRecur(BinaryTree * root){
     cout<< "非递归后序遍历" << endl;
    		BinaryTree *root1 = root;
        if (root1 != NULL)
        {
    
    		stack<BinaryTree *> stack,stack2;
    		stack.push(root1);
    		while (!stack.empty())
    		{
    
    			root1 = stack.top();
    			stack.pop();
    			stack2.push(root1);
    			if (root1-> left != NULL)
    			{
    				stack.push(root1->left);
    			}
    			if (root1->right != NULL)
    			{
    				stack.push(root1->right);
    			}
    
    		}
    		while (!stack2.empty())
    		{
    			cout << stack2.top()->data << " ";
    			stack2.pop();
    		}
    
    		cout<< endl;
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    非递归中序遍历

    逮住一棵树,先把左边界压到栈里去在弹出每一个节点的过程中让他的右树也这么干

    • 每棵子树,整棵树左边界进栈,然后依次弹出节点的过程打印中对弹出节点的右树重复
    void inOrderUnRecur (BinaryTree* root){
        cout<< "非递归中序遍历" << endl;
    	BinaryTree *root1 = root;//建个指针对象指向根节点
    	stack<BinaryTree*> stack2;//建个栈
        if (root1 != NULL)//如果根节点不为空的话
        {
    
    		while ( !stack2.empty() || root1)//当栈不为空并且根节点不为空时
    		{
    			if (root1)//如果这个节点不为空就把他压栈并且去看看他的左节点(不停地把左边界进栈)
    			{
    				stack2.push(root1);
    				root1 = root1->left;
    			}
    			else//左边界为空了就开始弹出节点
    			{
                    root1 = stack2.top();
    				cout << root1->data << ' ';
    				stack2.pop();//弹出节点并打印
    				root1 = root1->right;//对右树周而复始压左树
    			}
    
    		}
    
    
        }
    		cout << endl;
    }
    //前左再头的弄出来但是右树后干这件事
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    本文全部代码:

    #include
    #include
    #include
    
    using namespace std;
    
    //声明类
    class BinaryTree {
    public:
    	char data;
    	BinaryTree* left, * right;
    };
    
    stack<BinaryTree> stack2;
    //按照前序遍历创建二叉树
    void CreatBinaryTree(BinaryTree* &root) {//就相当于建立了一个root指针然后让root指针当一个tree的别名,root指针的本质就是对象指针
    	char c;
    	cin >> c;
    	if (c == '#')	//当遇到#时,令树的根节点为NULL,从而结束该分支的递归
    		root = NULL;
    	else
    	{
    		root = new BinaryTree;//用指针存放new出来的对象的地址这个指针就相当于新对象的指针。
    		root->data = c;	//指针指向对象中的data也可以写成(*root).data
    		CreatBinaryTree(root->left);//递归构建左子树
    		CreatBinaryTree(root->right);//递归构建右子树
    	}
    }
    
    void PrintBinaryTree(vector<int> path);//声明打印二叉树函数
    
    //前序遍历二叉树
    
    void Preorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		path.push_back(root->data);//在vector的末尾添加一个数就是按序排列(后来的插在后面)
    		Preorder(root->left, path);//访问左儿子
    		Preorder(root->right, path);//访问右儿子
    	}
    }//调用完了vector中就有数字了~
    
    //中序遍历二叉树
    
    void Inorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		Inorder(root->left, path);//访问左儿子
            path.push_back(root->data);//在vector的末尾添加一个数就是按序排列(后来的插在后面)
    		Inorder(root->right, path);//添加右儿子
    	}
    }//调用完了vector中就有数字了~
    
    //后序遍历二叉树
    
    void Postorder(BinaryTree* root, vector<char> &path)//path作为形参的传递方式
    {
    	if (root != NULL) {
    		Postorder(root->left, path);//访问左儿子
            Postorder(root->right, path);//访问右儿子
            path.push_back(root->data);//在vector的末尾添加这个节点 就是按序排列(后来的插在后面)
    
    	}
    }//调用完了vector中就有数字了~
    //打印函数
    void PrintBinaryTree(vector<char> path) {
    	int n = path.size();
    	for (int i = 0;i < n;++i) {
    		cout << path[i]<<' ';
    	}
    	cout<<endl;
    }
    //先序遍历非递归
    void preOrderUnRecur (BinaryTree *root){
        cout<< "非递归先序遍历" << endl;
    	BinaryTree *root1 = root;
        if (root1 != NULL)//排除头结点为空的情况
        {
    
    		stack<BinaryTree *> stack;//建栈
    		stack.push(root1);//压头结点
    		while (!stack.empty())//如果栈不为空就弹栈
    		{
    
    			root1 = stack.top();
    			stack.pop();
    			cout << root1->data <<' ';//打印了头结点
    			if (root1->right != NULL)
    			{
    				stack.push(root1->right);
    			}
    			if (root1-> left != NULL)
    			{
    				stack.push(root1->left);
    			}//这里是右边先进栈但是后出栈
    		}
    
    		cout<< endl;
    
        }
    
    }
    //中序遍历非递归
    void inOrderUnRecur (BinaryTree* root){
        cout<< "非递归中序遍历" << endl;
    	BinaryTree *root1 = root;//建个指针对象指向根节点
    	stack<BinaryTree*> stack2;//建个栈
        if (root1 != NULL)//如果根节点不为空的话
        {
    
    		while ( !stack2.empty() || root1)//当栈不为空并且根节点不为空时
    		{
    			if (root1)//如果这个节点不为空就把他压栈并且去看看他的左节点(不停地把左边界进栈)
    			{
    				stack2.push(root1);
    				root1 = root1->left;
    			}
    			else//左边界为空了就开始弹出节点
    			{
                    root1 = stack2.top();
    				cout << root1->data << ' ';
    				stack2.pop();//弹出节点并打印
    				root1 = root1->right;//对右树周而复始压左树
    			}
    
    		}
    
    
        }
    		cout << endl;
    }
    //前左再头的弄出来但是右树后干这件事
    
    //后序遍历非递归
    void postOrderUnRecur(BinaryTree * root){
     cout<< "非递归后序遍历" << endl;
    		BinaryTree *root1 = root;
        if (root1 != NULL)
        {
    
    		stack<BinaryTree *> stack,stack2;
    		stack.push(root1);
    		while (!stack.empty())
    		{
    
    			root1 = stack.top();
    			stack.pop();
    			stack2.push(root1);
    			if (root1-> left != NULL)
    			{
    				stack.push(root1->left);
    			}
    			if (root1->right != NULL)
    			{
    				stack.push(root1->right);
    			}
    
    		}
    		while (!stack2.empty())
    		{
    			cout << stack2.top()->data << " ";
    			stack2.pop();
    		}
    
    		cout<< endl;
    
        }
    }
    int main()
    {
    	vector<char> path1, path2, path3;
    	cout << "请使用前序遍历创建二叉树(若节点为空输入#代替):" << endl;
    	BinaryTree* root = NULL;
    	CreatBinaryTree(root);
    	BinaryTree* root_save = root;
    
    	cout << "二叉树创建完成!" << endl;
    	
    	
    	cout << "前序遍历二叉树结果为:" << endl;
    	Preorder(root, path1);
    	PrintBinaryTree(path1);
    	preOrderUnRecur(root);
    
    	cout << "中序遍历二叉树结果为:" << endl;
    	Inorder(root, path2);
    	PrintBinaryTree(path2);
    	inOrderUnRecur(root);
    
    	cout << "后序遍历二叉树结果为:" << endl;
    	Postorder(root, path3);
    	PrintBinaryTree(path3);
        postOrderUnRecur(root);
    
    	system("pause");
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198

    热爱可抵岁月漫长

  • 相关阅读:
    springboot海纳部门人事管理系统毕业设计源码
    国标GB28181协议客户端开发(三)查询和实时视频画面
    Github每日精选(第71期):自动网页抓取和浏览crawlee
    208道Java中高级高频面试题(含答案)
    矩阵乘法的性质
    数据库mysql详细教学
    git实现服务器自动push拉取代码--webhooks
    安全测试BurpSuite-抓包篡改数据
    为什么要学Selenium自动化测试?
    【kaggle】AI Report 2023概览
  • 原文地址:https://blog.csdn.net/m0_63830846/article/details/126513221