二叉树总结版

结点的构建

class BiTreeNode {
public:
	char data;//存放数据,结点的数据域
	BiTreeNode* LeftChild;//左子树指针,结点指针域
	BiTreeNode* RightChild;//右子树指针,结点指针域
	BiTreeNode() { LeftChild = NULL; RightChild = NULL; }
	~BiTreeNode(){}
};

树的构建

//树构造
class BiTree {
private:
	BiTreeNode* Root;//根节点指针
	string strTree;//字符串
	int pos;
	BiTreeNode* CreateBiTree();//构造二叉树(先序遍历法)
	void PreOrder(BiTreeNode* t);//先序遍历
	void InOrder(BiTreeNode* t);//中序遍历
	void PostOrder(BiTreeNode* t);//后序遍历
public:
	void CreateTree(string TreeArray);//构造二叉树接口
	void PreOrder();//先序遍历接口
	void InOrder();//中序遍历接口
	void PostOrder();//后序遍历接口
};

利用先序遍历法构造二叉树

//利用先序遍历法构造二叉树
void BiTree::CreateTree(string TreeArray) {//共有函数,对外接口
	pos = 0;
	strTree.assign(TreeArray);//字符串复制
	Root = CreateBiTree();
}
BiTreeNode* BiTree::CreateBiTree() {//递归建树,私有函数,类内实现
	BiTreeNode* T;
	char ch;
	ch = strTree[pos++];//取字符串pos的位置元素,先赋值后加加
	if (ch == '0') {
		T = NULL;
	}
	else {
		T = new BiTreeNode();//构造新结点
		T->data = ch;//数据域赋值
		T->LeftChild = CreateBiTree();//指针域成为新的结点继续构造二叉树
		//左结点先构建完再构建右结点,为先序遍历法
		T->RightChild = CreateBiTree();//指针域成为新的结点继续构造二叉树
	}
	return T;
}

先序遍历法

//先序遍历
void BiTree::PreOrder() {
	PreOrder(Root);
}
void BiTree::PreOrder(BiTreeNode* t) {
	if (t) {
		cout << t->data;
		PreOrder(t->LeftChild);
		PreOrder(t->RightChild);
	}
}

中序遍历法

//中序遍历
void BiTree::InOrder() {
	InOrder(Root);
}
void BiTree::InOrder(BiTreeNode* t) {
	if (t) {
		InOrder(t->LeftChild);
		cout << t->data;
		InOrder(t->RightChild);
	}
}

后序遍历法

//后序遍历
void BiTree::PostOrder() {
	PostOrder(Root);
}
void BiTree::PostOrder(BiTreeNode* t) {
	if (t) {
		PostOrder(t->LeftChild);
		cout << t->data;
		PostOrder(t->RightChild);
	}
}

层次遍历法

从上到下,从左到右进行遍历输出

利用队列先进先出的性质:先把根节点放入队列中,把队首元素出队列,再把队首元素的左孩子和右孩子(如果存在的话)也放入队列中,依次进行遍历,直到队空。

//层次遍历,利用队列先进先出的性质
#include <queue>
void BiTree::LevelOrder() {
	LevelOrder(Root);
}
void BiTree::LevelOrder(BiTreeNode* t) {
	//用队列实现
	queue<BiTreeNode*> tq;//创建队列tq,队列的每个元素都是结点指针
	BiTreeNode* p = t;//p是指向当前变量的指针
	if (p) {
		tq.push(p);//若p不为空,则p进入队列
	}
	while (!tq.empty()) {
        //队列不为空时,循环
		p = tq.front();//p指向tq队列的头元素
		tq.pop();//弹出
		cout << p->data;
		if (p->LeftChild) {
			tq.push(p->LeftChild);//传入其左孩子
		}
		if (p->RightChild) {
			tq.push(p->RightChild);//传入其右孩子
		}
	}
	cout << endl;
}

后序非递归遍历

//后序非递归遍历,用到栈先进后出的性质
#include <stack>
void BiTree::void LastOrder() {
	LastOrder(Root);
}
}void BiTree::LastOrder(BiTreeNode* t) {
	int tag = 0;
	stack<BiTreeNode*> S1;//S1栈,用于存放结点
	stack<int> S2;//S2栈,用于存放tag值
	BiTreeNode* p = t;//结点p指向当前结点
	do {
		while (p) {
			S1.push(p);
			tag = 0;
			S2.push(tag);
			p = p->LeftChild;
			if (S1.empty()) {
				break;
			}
		}
		while (!p) {
			if (S2.top() == 0) {
                //访问完左子树
				S2.top() = 1;//把tag值改为1
				p = S1.top()->RightChild;//接下来访问右结点
			}
			else if (S2.top() == 1) {
                //访问完右子树,弹出结点并输出结点
				p = S1.top();
				S1.pop();
				S2.pop();
				cout << p->data;
				p = NULL;
			}
			if (S2.empty()) {
				break;
			}
		}
	} while (!S1.empty());
	cout << endl;
}

二叉树的数组存储

用数组的形式表示树,并根据数组进行遍历输出

用到二叉树的性质5:左子树=根节点*2,右子树=根节点*2+1

因为用到的是数组,数组下标是从0开始的,因此左子树=根节点*2+1,右子树=根节点*2+2

题目描述:

二叉树可以采用数组的方法进行存储,把数组中的数据依次自上而下,自左至右存储到二叉树结点中,一般二叉树与完全二叉树对比,比完全二叉树缺少的结点就在数组中用0来表示。

如下图所示:

从上图可以看出,右边的是一颗普通的二叉树,当它与左边的完全二叉树对比,发现它比完全二叉树少了第5号结点,所以在数组中用0表示,同样它还少了完全二叉树中的第10、11号结点,所以在数组中也用0表示。结点存储的数据均为非负整数。

输入:

第一行输入一个整数t,表示有t个二叉树

第二行起,每行输入一个数组,先输入数组长度,再输入数组内数据,每个数据之间用空格隔开,输入的数据都是非负整数

连续输入t行

输出:

每行输出一个示例的先序遍历结果,每个结点之间用空格隔开

输入样例:

3
3 1 2 3
5 1 2 3 0 4
13 1 2 3 4 0 5 6 7 8 0 0 9 10
输出样例:

1 2 3 
1 2 4 3 
1 2 4 7 8 3 5 9 10 6 

#include <iostream>
using namespace std;
class Tree {
private:
	int len;
	int* root;//存储数组
public:
	void set(int a[],int n) {
		len = n;
		root = new int[n];
		for (int i = 0; i < n; i++) {
			root[i] = a[i];
		}
	}
	void PreOrder(int i) {
		if (i < len && root[i] != 0) {
			cout << root[i] << " ";//根节点
			PreOrder(i * 2 + 1);//左孩子
			PreOrder(i * 2 + 2);//右孩子
		}
	}
};
int main()
{
	int t;
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		int* a = new int[n];
		for (int i = 0; i < n; i++) {
			cin >> a[i];
		}
		Tree tree;
		tree.set(a, n);
		tree.PreOrder(0);
		cout << endl;
	}
}

二叉树的父子结点

寻炸二叉树的叶子结点及叶子节点的父亲结点。

叶子结点的寻并不困难,但是寻找完的叶子节点后如何返回寻找父亲节点就是一个难题

在这里,我运用了一个队列来对父亲节点进行存储,队列有先进先出的性质,符合题意

题目描述:

给定一颗二叉树的逻辑结构如下图,(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构。

编写程序输出该树的所有叶子结点和它们的父亲结点

输入:

第一行输入一个整数t,表示有t个二叉树

第二行起,按照题目表示的输入方法,输入每个二叉树的先序遍历,连续输入t行

输出:

第一行按先序遍历,输出第1个示例的叶子节点

第二行输出第1个示例中与叶子相对应的父亲节点

以此类推输出其它示例的结果

输入样例:

3
AB0C00D00
AB00C00
ABCD0000EF000

输出样例: 

C D 
B A 
B C 
A A 
D F 
C E

#include <iostream>
#include <string>
#include <queue>
using namespace std;
class BiTreeNode {
public:
	char data;
	BiTreeNode* LeftChild;
	BiTreeNode* RightChild;
    BiTreeNode(){LeftChild = NULL,RightChild = NULL;}
};

queue <BiTreeNode*> qu;//用队列来对父亲结点进行保存
BiTreeNode* Q;

class BiTree {
private:
	int pos;
	int len;
	BiTreeNode* Root;
	string strTree;
	BiTreeNode* CreateTree() {
		BiTreeNode* T;
		char ch;
		ch = strTree[pos++];
		if (ch == '0') {
			T = NULL;
		}
		else {
			T = new BiTreeNode();
			T->data = ch;
			T->LeftChild = CreateTree();
			T->RightChild = CreateTree();
		}
		return T;
	}
	void findleave(BiTreeNode* t) {
		if (t->LeftChild) {
			Q = t;//寻找父亲结点
			findleave(t->LeftChild);
		}
		if (t->RightChild) {
			Q = t;//寻找父亲节点
			findleave(t->RightChild);
		}
		if (!t->LeftChild && !t->RightChild) {
			qu.push(Q);//父亲节点进入队列
			cout << t->data << " ";
		}
	}
public:
	void CreateTree(string str) {
		int pos = 0;
		strTree.assign(str);
		Root = CreateTree();
	}
	void findleave() {
		findleave(Root);
		cout << endl;
		while (!qu.empty()) {
			cout << qu.front()->data << " ";
			qu.pop();
		}
		cout << endl;
	}
};
int main()
{
	int t;
	cin >> t;
	while (t--) {
		string str;
		cin >> str;
		BiTree tree;
		tree.CreateTree(str);
		tree.findleave();
	}
}

二叉树的最大路径

题目描述:

给定一颗二叉树的逻辑结构(先序遍历的结果,空树用字符‘0’表示,例如AB0C00D00),建立该二叉树的二叉链式存储结构

二叉树的每个结点都有一个权值,从根结点到每个叶子结点将形成一条路径,每条路径的权值等于路径上所有结点的权值和。编程求出二叉树的最大路径权值。如下图所示,共有4个叶子即有4条路径,

路径1权值=5 + 4 + 11 + 7 = 27          路径2权值=5 + 4 + 11 + 2 = 22

路径3权值=5 + 8 + 13 = 26                路径4权值=5 + 8 + 4 + 1 = 18

可计算出最大路径权值是27。

该树输入的先序遍历结果为ABCD00E000FG00H0I00,各结点权值为:

A-5,B-4,C-11,D-7,E-2,F-8,G-13,H-4,I-1

输入:

第一行输入一个整数t,表示有t个测试数据

第二行输入一棵二叉树的先序遍历,每个结点用字母表示

第三行先输入n表示二叉树的结点数量,然后输入每个结点的权值,权值顺序与前面结点输入顺序对应,以此类推输入下一棵二叉树。

输出:

每行输出每棵二叉树的最大路径权值,如果最大路径权值有重复,只输出1个

输入样例:

2
AB0C00D00
4 5 3 2 6
ABCD00E000FG00H0I00
9 5 4 11 7 2 8 13 4 1

输出样例:

11
27

 

#include <iostream>
#include <string>
#include <stack>
using namespace std;
stack <int> st;//用栈对叶子节点进行存储,便于后续比较权值大小
class BiTreeNode {
public:
	char data;
	int weight;
	BiTreeNode* LeftChild;
	BiTreeNode* RightChild;
	BiTreeNode() { LeftChild = NULL, RightChild = NULL; }
};
class BiTree {
private:
	int pos1;
	int pos2;
	string strTree;
	int* wei;
	BiTreeNode* Root;
	BiTreeNode* CreateTree() {
		BiTreeNode* T;
		char ch;
		ch = strTree[pos1++];
		if (ch == '0') {
			T = NULL;
		}
		else {
			T = new BiTreeNode();
			T->data = ch;
			T->weight = wei[pos2++];
			T->LeftChild = CreateTree();
			T->RightChild = CreateTree();
		}
		return T;
	}
	void findmax(BiTreeNode* t) {
		if (t->LeftChild && t->RightChild) {
			t->LeftChild->weight += t->weight;
			t->RightChild->weight += t->weight;
		}
		else if (t->LeftChild) {
			t->LeftChild->weight += t->weight;
		}
		else if (t->RightChild) {
			t->RightChild->weight += t->weight;
		}
		if (t->LeftChild) {
			findmax(t->LeftChild);
		}
		if (t->RightChild) {
			findmax(t->RightChild);
		}
	}
	void displaymax(BiTreeNode* t) {
		if (t->LeftChild) {
			displaymax(t->LeftChild);
		}
		if (t->RightChild) {
			displaymax(t->RightChild);
		}
		if (!t->LeftChild && !t->RightChild) {
			st.push(t->weight);
		}
	}
public:
	void CreateTree(string str,int n,int a[]) {
		wei = new int[n];
		for (int i = 0; i < n; i++) {
			wei[i] = a[i];
		}
		pos1 = 0;
		pos2 = 0;
		strTree.assign(str);
		Root = CreateTree();
	}
	void findmax() {
		findmax(Root);
	}
	void displaymax() {
		displaymax(Root);
		int max = 0;
		while (!st.empty()) {
			if (st.top() > max) {
				max = st.top();
			}
			st.pop();
		}
		cout << max << endl;
	}
};
int main()
{
	int t;
	cin >> t;
	while (t--) {
		string str;
		cin >> str;
		int n;
		cin >> n;
		int* a = new int[n];
		for (int i = 0; i < n; i++) {
			cin >> a[i];
		}
		BiTree tree;
		tree.CreateTree(str, n, a);
		tree.findmax();
		tree.displaymax();
	}
	return 0;
}

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值