二叉树C++实现数据结构实验

#include <iostream>
#include <string.h>
#include <stack>
#include <queue>
using namespace std;
template<class T>
struct BiNode								//二叉数节点
{
	T data;
	BiNode<T>* lchild, *rchild;

};

template<class T>							//模板类
class BiTree
{
public:
	BiTree();								//默认构造函数
	~BiTree();								//析构函数
	BiNode<T>* GetRoot();					//返回根节点
	void PreOrder(BiNode<T>* node);			//先序遍历
	void InOrder(BiNode<T>* node);			//中序遍历
	void PostOrder(BiNode<T>* node);		//后序遍历
	void LevelOrder(BiNode<T>* node);		//层次遍历


	//选做非递归实现
	void PreOrderNonRec(BiNode<T>* node);	//先
	void InOrderNonRec(BiNode<T>* node);	//中
	void PostOrderNonRec(BiNode<T>* node);	//后


	//选做深度,节点数,叶子节点数,
	int NodesNum(BiNode<T>* node);			//节点数
	int TreeDepth(BiNode<T>* node);			//深度
	int LeafNum(BiNode<T>* node);			//叶子节点数


	//选做交换子树
	void SwapChild(BiNode<T>* node);		//交换子树


private:
	BiNode<T>* m_root;						//获取根节点
	BiNode<T>* Create();					//创建二叉树
};

template<class T>
BiTree<T>::BiTree()
{
	m_root = new BiNode<T>;
	m_root = Create();
}

template<class T>
BiTree<T>::~BiTree(){}

template<class T>
BiNode<T>* BiTree<T>::Create()				//1. 按先序序列构造一棵二叉链表表示的二叉树T;
{
	char ch=getchar();
	BiNode<T>* pnode;

	if (ch == ' ')
		pnode = NULL;
	else
	{
		pnode = new BiNode<T>;
		pnode->data = ch;
		pnode->lchild = Create();
		pnode->rchild = Create();
	}
	return pnode;
}

template<class T>
BiNode<T>* BiTree<T>::GetRoot()
{
	return m_root;
}

template<class T>
void BiTree<T>::PreOrder(BiNode<T>* node)
{
	if (!node)
		return;
	else
	{
		cout << node->data;
		PreOrder(node->lchild);
		PreOrder(node->rchild);
	}
}

template<class T>
void BiTree<T>::InOrder(BiNode<T>* node)
{
	//前后定根,中序定左右
	if (!node)
		return;
	else
	{
		InOrder(node->lchild);
		cout << node->data;
		InOrder(node->rchild);
	}

}

template<class T>
void BiTree<T>::PostOrder(BiNode<T>* node)
{
	if (!node)
		return;
	else
	{
		PostOrder(node->lchild);
		PostOrder(node->rchild);
		cout << node->data;
	}

}

template<class T>
void BiTree<T>::LevelOrder(BiNode<T>* node)
{
	//层次遍历需要queue来实现,思路:
	//@1初始化queue
	//	if root为空 返回
	//@2 push(root)
	//@3 while(queue不为空)
	//		s <-- queue.front()
	//		queue.pop()
	//		输入s.data
	//		if(s的左子树不空)
	//			s的左子树入队
	//		if(s的右子树不空)
	//			s的右子树入队

	queue<BiNode<T>*> q;
	BiNode<T>* s = node;
	if (!s)
		return;
	q.push(s);
	while (!q.empty())
	{
		s = q.front();
		q.pop();
		cout << s->data;
		if (s->lchild)
			q.push(s->lchild);
		if (s->rchild)
			q.push(s->rchild);

	}
}


//先序遍历非递归需要借助stack s来实现,模拟递归调用
//总的循环边界是当前节点不为空或者stack不空,
template<class T>
void BiTree<T>::PreOrderNonRec(BiNode<T>* node)
{
	stack<BiNode<T>*> s;
	BiNode<T>* p = node;
	while (p|| !s.empty())
	{
		/*
		@1.每次找当前的节点的左子节点直到左为空,经过的节点入栈,
		@2.然后弹出当前节点,搜索一次右节点,如果p为空并且s空则退出否则继续@1
		*/
		while (p)//这里执行VL
		{
			cout << p->data;//V
			s.push(p);//访问过的加入栈
			p = p->lchild;//L
		}
		if (!s.empty())//这里执行R
		{
			p = s.top();
			s.pop();
			p = p->rchild;//R
		}
	}


}

template<class T>
void BiTree<T>::InOrderNonRec(BiNode<T>* node)
{
	//@1 在当前节点p非空时候,将p入栈s,p的左子树赋给p,保证左子树都能入栈
	//	p为空时候,也就是左子树最左边访问到了,这时候在栈非空的时候
	//@2 取栈顶给p,输入p,出栈,这时候最底层的最左边节点访问了,将p的右子树赋给p,重复@1
	stack<BiNode<T>*> s;
	BiNode<T>* p = node;
	while (p|| !s.empty())
	{
		while (p)//这里执行L
		{
			s.push(p);
			p = p->lchild;
		}
		if (!s.empty())//这里执行VR
		{
			p = s.top();
			cout << p->data;
			s.pop();
			p = p->rchild;
		}
	}
}

template<class T>
void BiTree<T>::PostOrderNonRec(BiNode<T>* node)
{
	//访问子节点的条件有两种
	//1.当前节点的左右节点都为空,可以直接访问
	//2.前一个被访问的节点是当前节点的子节点
	//这样就需要两个指针,一个指向当前一个指向前一个被访问的节点
	//然后保证入栈顺序是先右再左,(这里先压右再压左,这样左在上面,就先访问左)
	if (!node)
		return;
	stack<BiNode<T>*> s;
	s.push(node);
	BiNode<T>* pre = NULL;
	BiNode<T>* cur;
	while (!s.empty())
	{
		cur = s.top();
		if (!cur->lchild&& !cur->rchild ||(pre != NULL) && (pre == cur->lchild || pre == cur->rchild))//上一次访问的是当前节点的左子树
		{
			cout << cur->data;
			s.pop();
			pre = cur;//pre是前一个被访问的节点
		}
		else
		{
			if (cur->rchild)
				s.push(cur->rchild);
			if (cur->lchild)
				s.push(cur->lchild);

		}
	}

}

template<class T>
int BiTree<T>::LeafNum(BiNode<T>* node)
{
	//递归思路:找到叶子节点返回值加一,返回值计数
	//2种情况
	//1.节点为空,返回 0,传递回去
	//2.每当到达叶子节点,返回 1,传递给上一层函数
	if (!node)
		return 0;
	if (!node->lchild&&!node->rchild)
		return 1;
	return LeafNum(node->lchild) + LeafNum(node->rchild);
}

template<class T>
int BiTree<T>::TreeDepth(BiNode<T>* node)
{
	/*
	递归思路:
	每个节点都有自己的左右子树,
	每次返回当前节点左右子树长度大的那个

	1.如果根节点为空,则深度为0,返回0,递归的出口
	2.否则深度至少为1,然后累加他们左右子树的深度,
	*/
	int LChildDep = 1, RChildDep = 1;
	if (!node)
		return 0;
	LChildDep += TreeDepth(node->lchild);//每次返回之前子树的长度
	RChildDep += TreeDepth(node->rchild);
	return (LChildDep>RChildDep) ? (LChildDep) : (RChildDep);

}

template<class T>
int BiTree<T>::NodesNum(BiNode<T>* node)
{
	//思路,递归遍历所有节点,如果不是空节点的话,递归返回值加1
	if (!node)
		return 0;
	return NodesNum(node->lchild) + NodesNum(node->rchild) + 1;

}

template<class T>
void BiTree<T>::SwapChild(BiNode<T>* node)
{
	//思路,交换所有节点的节点,每个节点走一遍
	if (node)
	{
		swap(node->lchild, node->rchild);
		SwapChild(node->lchild);
		SwapChild(node->rchild);
	}
}


/*

样例输入:
ABC  DE G  F    ↙

样例输出:
先序建立一棵二叉树,请输入节点的值:ABC  DE G  F   
建立完毕.
先序:ABCDEGF
中序:CBEGDFA
后序:CGEFDBA
层序:ABCDEFG
选做题1:采用非递归算法实现二叉树遍历
先序:ABCDEGF
中序:CBEGDFA
后序:CGEFDBA
选做题2:求二叉树的深度/结点数目/叶结点数目
TreeDepth is 5
NodesNum is 7
LeafNum is 3
选做题3:将二叉树每个结点的左右子树交换位置。
交换完毕.
先序:ABDFEGC
中序:AFDGEBC
后序:FGEDCBA
层序:ABDCFEG
*/

int main()
{
	cout << "先序建立一棵二叉树,请输入节点的值:";
	BiTree<char> bitree;
	cout << "建立完毕." << endl;
	cout << "先序:";
	bitree.PreOrder(bitree.GetRoot());
	cout << endl;
	cout << "中序:";
	bitree.InOrder(bitree.GetRoot());
	cout << endl;
	cout << "后序:";
	bitree.PostOrder(bitree.GetRoot());
	cout << endl;
	cout << "层序:";
	bitree.LevelOrder(bitree.GetRoot());
	cout << endl;
	cout << "选做题1:采用非递归算法实现二叉树遍历" << endl;
	cout << "先序:";
	bitree.PreOrderNonRec(bitree.GetRoot());
	cout << endl;
	cout << "中序:";
	bitree.InOrderNonRec(bitree.GetRoot());
	cout << endl;
	cout << "后序:";
	bitree.PostOrderNonRec(bitree.GetRoot());
	cout << endl;
	cout << "选做题2:求二叉树的深度/结点数目/叶结点数目" << endl;
	cout << "深度为    : " << bitree.TreeDepth(bitree.GetRoot()) << endl;
	cout << "结点数目  : " << bitree.NodesNum(bitree.GetRoot()) << endl;
	cout << "叶结点数目: " << bitree.LeafNum(bitree.GetRoot()) << endl;
	cout << "选做题3:将二叉树每个结点的左右子树交换位置。" << endl;
	bitree.SwapChild(bitree.GetRoot());
	cout << "交换完毕." << endl;
	cout << "先序:";
	bitree.PreOrder(bitree.GetRoot());
	cout << endl;
	cout << "中序:";
	bitree.InOrder(bitree.GetRoot());
	cout << endl;
	cout << "后序:";
	bitree.PostOrder(bitree.GetRoot());
	cout << endl;
	cout << "层序:";
	bitree.LevelOrder(bitree.GetRoot());
	cout << endl;
	system("pause");
}

  • 15
    点赞
  • 112
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
好的,我可以回答你关于数据结构实验6的问题。C++实现二叉树类的具体实现如下: ```cpp #include <iostream> using namespace std; // 节点结构体 struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} }; // 二叉树类 class BinaryTree { public: BinaryTree() : root(nullptr) {} // 插入节点 void insert(int val) { if (root == nullptr) { root = new TreeNode(val); return; } TreeNode* cur = root; while (cur != nullptr) { if (val < cur->val) { if (cur->left == nullptr) { cur->left = new TreeNode(val); return; } cur = cur->left; } else { if (cur->right == nullptr) { cur->right = new TreeNode(val); return; } cur = cur->right; } } } // 查找节点 bool find(int val) { TreeNode* cur = root; while (cur != nullptr) { if (cur->val == val) { return true; } else if (cur->val > val) { cur = cur->left; } else { cur = cur->right; } } return false; } // 删除节点 void remove(int val) { root = removeNode(root, val); } // 中序遍历 void inorder() { inorderTraversal(root); } private: // 根节点 TreeNode* root; // 删除节点 TreeNode* removeNode(TreeNode* root, int val) { if (root == nullptr) return root; if (val < root->val) { root->left = removeNode(root->left, val); } else if (val > root->val) { root->right = removeNode(root->right, val); } else { if (root->left == nullptr) { TreeNode* rightChild = root->right; delete root; return rightChild; } else if (root->right == nullptr) { TreeNode* leftChild = root->left; delete root; return leftChild; } else { TreeNode* minNode = findMin(root->right); root->val = minNode->val; root->right = removeNode(root->right, minNode->val); } } return root; } // 查找最小节点 TreeNode* findMin(TreeNode* root) { while (root->left != nullptr) { root = root->left; } return root; } // 中序遍历 void inorderTraversal(TreeNode* root) { if (root == nullptr) return; inorderTraversal(root->left); cout << root->val << " "; inorderTraversal(root->right); } }; ``` 以上是基本的二叉树实现,包括了插入节点、查找节点、删除节点和中序遍历等操作。你可以根据需要进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值