吉林大学大数据专业数据结构算法实现-第五章-树与二叉树(part1二叉树)


前言

很忙,不写前言


--------------------------- 二叉树类-------------------------

typedef struct tree
{
	char val;
	struct tree* left;
	struct tree* right;
}Tree;

一、二叉树的先根遍历(递归/栈)

实现功能

以先根顺序遍历二叉树

ADL描述

请添加图片描述
用栈实现的非递归无adl描述

实现

1.递归

void Preorder(Tree* root)//上左右
{
	if (NULL == root) {
		return;
	}
	printf("%c ", root->val);//输出放在最前面
	Preorder(root->left);
	Preorder(root->right);
}

2.非递归

void NRO(Tree* root) { //树的先根遍历(栈)
	stack<Tree*> s;
	Tree* p = root;
	while (p != NULL || s.empty() == 0) { //遍历到节点为空或栈空
		while (p != NULL) {//节点不空,输出压栈,一直取左
			cout << p->val<<" ";
			s.push(p); 
			p = p->left; 
		}
		if (s.empty() == 0) {//左取光后,栈不空则弹栈取一次其右
			p = s.top();
			//cout << p->val;
			s.pop(); 
			p = p->right; 
		}
	}
	cout << endl;
}

二、二叉树的中根遍历(递归/栈)

实现功能

用中根顺序遍历二叉树

ADL描述

请添加图片描述
请添加图片描述

实现

1.递归

void InOrder(Tree* root)//左上右
{
	if (NULL == root) {
		return;
	}

	InOrder(root->left);
	printf("%c ", root->val);//输出放在中间
	InOrder(root->right);
}

2.非递归

void NIO(Tree* root) { //树的中序遍历(栈)
	stack<Tree*> s;
	Tree* p = root;
	while (p != NULL || s.empty() == 0) {
		while (p != NULL) {
			//这里不再像先根那样输出
			s.push(p);
			p = p->left;
		}
		if (s.empty() == 0) {
			p = s.top();
			cout << p->val<<" ";//在取右前输出就是中序遍历
			s.pop();
			p = p->right;
		}
	}
	cout << endl;
}

三、二叉树的后根遍历(递归/栈)

实现功能

后根顺序遍历二叉树

ADL描述

请添加图片描述
请添加图片描述

实现

1.递归

void PostOrder(Tree* root)//左右上
{
	if (NULL == root) {
		return;
	}

	PostOrder(root->left);
	PostOrder(root->right);
	printf("%c ", root->val);//输出放在最后
}

2.非递归

typedef pair<Tree*, int> ti;
void NPO(Tree* root) {
	if (!root)return;
	stack<ti> sta;
	sta.push({ root, 0 });
	while (sta.empty() == 0) {
		ti cur = sta.top();
		sta.pop();
		Tree* p = cur.first;
		int i = cur.second;
		if (i == 0)
		{//标记位为0时改成1压入,尝试压入左节点
			sta.push({ p,1 });
			if (p->left != NULL)
				sta.push({ p->left,0 });
		}
		else if (i == 1)
		{//标记位为1时改成2压入,尝试压入右节点
			sta.push({ p,2 });
			if (p->right != NULL)
				sta.push({ p->right,0 });
		}
		//标记位为2,输出
		else if (i == 2)cout << p->val << " ";
	}
	cout << endl;
}

四、二叉树的层序遍历

实现功能

一层一层的遍历二叉树

ADL描述

请添加图片描述

实现

void LevelOrder(Tree* root) {
	if (root == NULL)return;
	//进行了些许改进,令其遍历过一层后打出一个回车
	queue<Tree*> que;
	que.push(root);
	while (!que.empty())
	{
		int tmp = que.size();
		while (tmp--)
		{
			Tree* p = que.front();
			que.pop();
			cout << p->val << " ";
			if (p->left != NULL)que.push(p->left);
			if (p->right != NULL)que.push(p->right);
		}
		cout << endl;
	}
	cout << endl;
}

五、先根次序创建二叉树CBT

实现功能

参照先根遍历的方法,构建一棵二叉树,#代表NULL

ADL描述

请添加图片描述

实现

Tree* CBT()	//先根次序构建二叉树
{
	Tree* root;
	char ch;
	cin>>ch;
	if (ch == '#') {//递归过程一旦读入#返回空值给上一层
		return NULL;
	}
	else {
		root = (Tree*)malloc(sizeof(Tree));
		root->val = ch;//构建根节点
		root->left = CBT();//构建左子树
		root->right = CBT();//构建右子树
		return root;
	}
}

六、复制二叉树

实现功能

将一个现有的二叉树复制给另一个二叉树

ADL描述

请添加图片描述
请添加图片描述

实现

Tree* Copy_Tree(Tree* oroot)
{
	if (oroot == NULL)return NULL;
	Tree* nroot = (Tree*)malloc(sizeof(Tree));
	nroot->val = oroot->val;//复制根节点
	nroot->left = Copy_Tree(oroot->left);//复制左子树
	nroot->right = Copy_Tree(oroot->right);//复制右子树
	return nroot;
}

七、查找给定节点的父亲

实现功能

返回指向结点p之父亲的指针

ADL描述

请添加图片描述

实现

Tree* Find_father(Tree* root, Tree* target) {//寻找一个节点的父亲
	if (NULL == root||target==NULL||target==root) {
		return NULL;
	}
	if (root->left == target || root->right == target)return root;
	Tree* left = Find_father(root->left, target);
	if (left != NULL)return left;
	Tree* right= Find_father(root->right, target);
	if (right != NULL)return right;
}

八、查找结点

实现功能

用先根遍历在二叉树中搜索符合数据条件(item)的结点p

ADL描述

请添加图片描述

实现

Tree* Find(Tree* root, char item) {
	if (root == NULL)return NULL;
	if (root->val == item)return root;//查找根节点,遍历过程中一旦找到目标就返回
	Tree* left = Find(root->left, item);//查找左子树
	if (left != NULL)return left;
	Tree* right = Find(root->right, item);//查找右子树
	if (right != NULL)return right;
}

九、释放二叉树

实现功能

释放以p指向结点为根的树

ADL描述

请添加图片描述

实现

void del_Tree(Tree* root)
{
	if (NULL == root) {
		return;
	}
	del_Tree(root->left);
	del_Tree(root->right);
	free(root);
}

十、插入节点

实现功能

在二叉树中插入结点p,作为结点s的左儿子,s原来的左儿子成为p的左儿子

ADL描述

在这里插入图片描述

实现

void insert(Tree* p, Tree* s)
{//将p插入到s节点的左侧,s原来的左子树作为p左子树
	if (!p || !s)return;
	p->left = s->left;
	s->left = p;
	return;
}

十一、删除节点及其左右子树

实现功能

root指向一棵二叉树T之根,本算法从T中删除给定结点t (t是指向该结点的指针)及其左右子树;DST是DelSubTree之缩写

ADL描述

请添加图片描述

实现

void DST(Tree* root, Tree* target)
{
	if (target == NULL)return;
	if (target == root) { free(target); }
	Tree* father = Find_father(root,target);
	if (father->left == target)father->left = NULL;
	if (father->right == target)father->right = NULL;
	free(target);
	return;
}

测试用例

int main()
{
	Tree* mytree = CBT();
	Preorder(mytree); cout << endl;
	NRO(mytree);
	InOrder(mytree); cout << endl;
	NIO(mytree);
	PostOrder(mytree); cout << endl;
	NPO(mytree);
	LevelOrder(mytree);
	Tree* yourtree = Copy_Tree(mytree);
	LevelOrder(yourtree);
	cout << Find_father(mytree, Find(mytree, 'h'))->val<<endl;
	insert(Find(mytree, 'i'), Find(yourtree, 'b'));
	LevelOrder(yourtree);
	DST(yourtree, Find(yourtree, 'b'));
	LevelOrder(yourtree);
	//输入这个试试
	//a b d # # e # # c h # # i # #
}

总结

很忙,不写总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值