C++ 二叉树 家谱

1.实验说明

要求完成的功能如下,测试输出如图 所示:
(1) 输入一棵二叉树的括号表示法,完成树的构建
(2) 使用后序遍历递归算法遍历二叉树并输出
(3) 使用先序遍历非递归算法遍历二叉树并输出
(4) 指定家谱中的某一成员,输出其所有长辈
测试例:
输入:A(B(C(E,F),D(G(M,N),H)),)
输出:
M 的长辈为:FCNGHDBA
N 的长辈为:HDBA
实验结果


2.流程图

以下为该实验的流程图

yes
yes
no
no
输入括号表达式
表达式正确
生成二叉树
输出
输入成员
是否存在
输出其祖先
结束

3. BTree.h

3.1 树的结点

//树的结点
typedef struct node//家谱中个人信息的载体
{
	char data;
	bool isLchild;
	int level;
	struct node* lchild;
	struct node* rchild;
}Node,*BTNode;//struct node -> Node/*BTNode

3.2 树的类

class BTree
{
private:
	BTNode root;    //根结点
public:
	BTree(const char* str);  //构造方法
	~BTree();  //析构方法
	bool isEmpty();
	BTNode getRoot();
	void PostOrderRe(BTNode b); //后序递归遍历
	void PreOrderRe(BTNode b); //先序递归遍历,由后序遍历简单变化而来 
	void PreOrderNotRe();    //先序非递归遍历
	bool isAncestor(BTNode b, char me);
	BTNode FindMe(char me);
	BTNode FindFather(BTNode me);
	void FindAllAncestor(char Object);
	void ShowAncestor(BTNode ancestor);
	void DestroyBTree(BTNode b);
	bool banish(char b);  //逐出家门,我闲着无聊搞得,不属于课程要求
};

4. 源.cpp

4.1 菜单

int main(void)
{
	int choose; 
	char housemenu[100];
	char me;
	cout << "请以括号表示法输入二义树结构:";
	cin >> housemenu;
	BTree tree(housemenu); //构造BTree类的对象
	BTNode r = tree.getRoot();
	cout << "后序遍历递归算法输出:";
	tree.PostOrderRe(r);
	cout << endl<<"前序遍历递归算法输出:";
	tree.PreOrderNotRe();
	cout <<endl<< "请输入指定人物代号,以查询其所有长辈:";
	cin >> me;
	cout << me << "的所有长辈为:";
	tree.FindAllAncestor(me);
	cout << endl << "请输入指定人物代号,以查询其所有同辈:";
	cin >> me;
	BTNode me_BTnode = tree.FindMe(me);
	if (me_BTnode == NULL) {
		cout << "没有此人" << endl;
	}
	else {
		cout << me << "的所有同辈为:";
		tree.ShowAncestor(me_BTnode);
	}
	cout <<endl<< "是否需要进行逐出操作(1-是/0-否):";
	cin >> choose;
	if (choose == 0) {
		return 0;
	}
	cout<< "请输入将被逐出家族的支系的族长:";
	cin >> me;
	me_BTnode = tree.FindMe(me);
	if (me_BTnode == NULL) {
		cout << "没有此支系" << endl;
	}
	else {
		cout << "该支系家谱为:";
		tree.PreOrderRe(me_BTnode);
		cout <<endl<< "是否要逐出此支系(1-是/0-否):";
		cin >> choose;
		if (choose == 1) {
			cout << "是否真的要逐出此支系(1-是/0-否):";
			cin >> choose;
			if (choose == 1) {
				if (tree.banish(me)) {
					cout << "逐出后新家谱为:";
					tree.PostOrderRe(r);
				}
				else {
					cout << "逐出失败";
				}
			}
		}
	}


	return 0;
}

5. BTree.cpp

5.1 树的初始化

BTree::BTree(const char* str)
{
	stack<BTNode> st;
	BTNode p;
	bool flag = true;  //flag默认为true,左结点
	int i = 0;
	while (str[i] != '\0') {
		switch (str[i]) {
		case'(':       // '( ' => p的孩子,
			st.push(p);   
			flag = true;   //例子:B为左结点,A(B,C)
			break;
		case')':    
			st.pop();
			break;
		case',':
			flag = false; //C为右结点
			break;
		default:;
			p = new Node;  //新的结点
			p->data = str[i];
			p->lchild = NULL;  //一定要记得加上,我掉在这坑里好久
			p->rchild = NULL;
			if (root == NULL) {   //空树
				p->isLchild = true;
				p->level = 1;       //树的高度,根结点在第一层
				root = p;
			}
			else {
				if (!st.empty()) {
					p->level += st.top()->level;  //高度+1
					if (flag) {
						st.top()->lchild = p;
						p->isLchild = true;
					}
					else if (!st.empty()) {
						st.top()->rchild = p;
						p->isLchild = false;
					}
				}
			}
		}
		i++;
	}
}

5.2后序遍历输出

void BTree::PostOrderRe(BTNode b)
{
	if (b->lchild != NULL || b->rchild != NULL) {
		cout << "(";
		if (b->lchild != NULL) {
			PostOrderRe(b->lchild);
		}
		if (b->rchild != NULL) {
			cout << ",";
			PostOrderRe(b->rchild);
		}
		cout << ")";
	}
	cout << b->data;  //将这句换一下位置即为先序遍历
	return;
}

5.3 先序非遍历输出

void BTree::PreOrderNotRe()
{
	stack<BTNode> st;
	BTNode p;
	p = root;
	while (!st.empty() || p != NULL) {
		if (p != NULL) {
			cout << p->data;
			st.push(p);
			p = p->lchild;
		}
		else {
			p=st.top();
			st.pop();
			p = p->rchild;
		}
	}
	return;
}

5.4 找祖先

void BTree::ShowAncestor(BTNode ancestor) 
{
	stack<BTNode> st;
	BTNode p;
	p = root;
	while (!st.empty() || p != NULL) {
		if (p != NULL) {
			if (p->level == ancestor->level&&p!=ancestor) {
				cout << p->data;
			}
			st.push(p);
			p = p->lchild;
		}
		else {
			p = st.top();  //取栈顶的结点,没出栈
			st.pop();    //出栈
			p = p->rchild;
		}
	}
	return;
}

6. 收尾

源码

我的github仓库
我的gitee仓库 https://gitee.com/aa2255/smalltask

其余的方法基本都是根据已有的变化一下就行了,全部贴出来太长了,影响观感(主要是我懒 -_- )。
就到这了,青山不改水长流,后会有期。😉

  • 20
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

杀小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值