二叉树家谱

/*============================================================
  功能描述:

  *   前序扩展建立二叉树家谱(左子树为子女,右子树为兄弟)

  *   使用栈查找指定节点(非递归)

  *   可写入和读取文件

  *   可查找双亲、子女、兄弟

  *   图层显示二叉树家谱

  *   已注释读取文件,正确运行一次后可取消注释

  *   前序扩展建立输入二叉树输入格式:AB**C**

  编写代码环境:vs2008

  使用vc6.0 运行时,注释掉第一行,且将主函数改为:int main(){}即可

 (非递归查找指定节点方法较为繁琐,推荐使用递归方法。自己写的作业,仅供参考)

  有问题可发邮件:weizhenzhenvae@sina.com

=============================================================*/

// 二叉树家谱.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"                               //使用vc6.0运行时注释掉此行
#include<iostream>
#include<vector>
#include<fstream>
using namespace std;
 

class BinaryTreeNode{                             //二叉树节点类
public:
	char name;                                //记录节点名称
	char j;                                   //用来记录走的左子女还是右子女
	BinaryTreeNode *left,*right;
	BinaryTreeNode(char elem){                //初始化
		name=elem;
		left=NULL;
		right=NULL;
		j='l';
	}
};


template<typename T>
class StackNode                                   //栈节点类
{
public:
	T Element;
	StackNode *next;         
	StackNode(T value)                         //初始化
	{
		Element=value;
		next=NULL;
	}
};


template<typename T>                               //不支持类模板定义与实现分享
class ListStack                                    //链表栈
{

	T element;
	StackNode<T> *top;
	StackNode<T> *p,*q,*m;
public:	

	ListStack()
	{
		p=new StackNode<T>(0);
		top=p;
		
	}
	void push(T ele)                           //入栈
	{
		p=new StackNode<T>(ele);
		p->next=top->next;
		top->next=p;
		
	}
	T pop()                                    //出栈
	{
		if(top->next!=NULL)
		{
			p=top->next;
			element=p->Element;
			top->next=p->next;
			delete p;
			return element;
		}
		else
		{
			cout<<"The stack is empty!"<<endl;
			return 0;
		}
	}
	T GetTop()                                //取栈顶元素
	{
		if(top->next!=NULL)
		{
			return top->next->Element;
		}
		else
		{
			cout<<"The stack is empty!"<<endl;
			return 0;
		}
	}
	bool IsEmpty(){                           //判断栈是否为空
		if(top->next==NULL){
			return 0;
		}
		return 1;
	}
};


class BinaryTree{                                  //二叉树类
public:	BinaryTreeNode *root,*himself,*child;
		vector<char> all;                  //存储二叉树前序扩展遍历的结果,方便写入文件
		ListStack<BinaryTreeNode*> store;  //查找二叉树链表中的节点时,用栈暂存前序遍历的节点指针
		ListStack<char> brother;           //存储节点向上的兄弟
		char g;


	BinaryTree(){root=0;}
	void CreateBinaryTree(BinaryTreeNode *&t){ //前序扩展建立二叉树
		char na;
        cin>>na;
    	if(na=='*'){
    		t=NULL;
		}
    	else{
    		t=new BinaryTreeNode(na);
    		CreateBinaryTree(t->left);
    		CreateBinaryTree(t->right);
		}
	}
	void Visit(BinaryTreeNode *&t){              //访问节点
		if(t){
			cout<<t->name<<" ";
			all.push_back(t->name);
		}
		else{
			all.push_back('*');          //将前序遍历存入数组中,方便文件的写入
		}
	}
	void PreOrder(BinaryTreeNode *&r){           //前序遍历二叉树
		Visit(r);
		if(r){
			PreOrder(r->left);
			PreOrder(r->right);
		}
	}
	void WriteBinaryTree(){                       //将二叉树的前序遍历结果存入文本文件中
		ofstream outstuf;
		outstuf.open("F:\\jiapu.txt",ios::out);//写入之前先删除原有的内容
		if(!outstuf){
			cerr<<"file could not be open."<<endl;
	        abort();
        }
		
		all.clear();
		PreOrder(root);
		for(vector<char>::iterator i=all.begin();i!=all.end();i++){
	    	outstuf<<*i<<endl;
		}
		outstuf.close();

	}
	void ReadBinaryTree(BinaryTreeNode *&t,ifstream &out){//将文本文件中的内容读取到二叉树中
		
		char na;
        out>>na;
    	if(na=='*'){
    		t=NULL;
		}
    	else{
    		t=new BinaryTreeNode(na);
    		ReadBinaryTree(t->left,out);
    		ReadBinaryTree(t->right,out);
		}

	}
	void Show(BinaryTreeNode *t,int i){               //将二叉树以图层的关系显示
		
		if(t){
			for(int j=0;j<i;j++)              //用循环控制空格输出

				cout<<' ';
			}
			Visit(t);
			cout<<endl;		
			Show(t->left,i+1);
			i--;
			Show(t->right,i+1);                           
		}
		
	}
	void Research(char na,BinaryTreeNode *t){          //利用栈查找指定节点的双亲
		if(!t||t->name!=na){
			if(!t){                           //若指针为空,判断指针是左子树还是右子树
				t=store.GetTop();
				if(t->j=='l'){                          
					t->j='r';
					Research(na,t->right);              
				}
				else if(t->j=='r'){         //空指针为右子树退栈
					t=store.pop();
			    	t=store.GetTop();
					if(t->j=='r'){t=store.pop();}
					t->j='r';
			    	Research(na,t->right);
				}
				
			}
			else{
				store.push(t);
				Research(na,t->left);
			}
		}
		else{
			himself=t;                            //记录找到的节点,方便查找其兄弟和子女
			
	     	        if(store.IsEmpty()){                    
				while(1){
					if(!store.IsEmpty()){  //若节点为根节点的兄弟,则没有双亲
						cout<<"没有双亲"<<endl;
						break;
					}
					t=store.GetTop();        //取栈顶元素
		    		if(t->j=='l'){                   //若查找的节点是栈顶元素的左子女,则栈顶元素即为其双亲
		    		cout<<"双亲是"<<t->name<<endl;
		    		break;
					}
		    		else{                            //若查找的节点为右子女,则继续向上查找其兄弟的双亲
			    		t=store.pop();
						brother.push(t->name);  //用栈保留节点上方的兄弟
					}
				}
			}
			else{
				cout<<"没有双亲"<<endl;
			}
		}
	}
	void ReChild(BinaryTreeNode *t){                         //查找指定节点的子女,包括左子女及左子女的兄弟
		if(t->left==NULL){ 
			cout<<"没有子女"<<endl;
		}
		else{	
			cout<<"子女是";
			Visit(t->left);
			t=t->left;
			while(t->right){
				Visit(t->right);
				t=t->right;
			}
		}
       cout<<endl;
	}
	void ReBrother(BinaryTreeNode *t){                       //查找指定节点的兄弟
		if(t->right==NULL&&!brother.IsEmpty()){
			cout<<"没有兄弟"<<endl;
		}
		else{
			cout<<"兄弟是";
			while(brother.GetTop()!=0){               //向上的兄弟已用栈保存
				cout<<brother.pop()<<" ";
			}
			while(t->right){                         //向下查找其兄弟
		  	Visit(t->right);
			t=t->right;
			}
		}  
		cout<<endl;
	}
	void Enter(char name,BinaryTreeNode *t){                 //插入子女
		if(t->left==NULL){	                         //若节点没有子女,则直接插入
			child=new BinaryTreeNode(name);
			t->left=child;
		}
		else{                                            //若已有子女,则插入其子女的兄弟
			t=t->left;
			while(t->right){
				t=t->right;
			}
			child=new BinaryTreeNode(name);
			t->right=child;
		}
	}
	bool Judge(char nam){
		for (vector<char>::iterator i=all.begin();i!=all.end();i++)
		{
			if (*i==nam)
			{
				return true;
			}
		}
		return false;

	}
};

int _tmain(int argc, _TCHAR* argv[]){
	BinaryTree tree;
//	ifstream out("F:\\jiapu.txt");                            //读取文件
//	tree.ReadBinaryTree(tree.root,out);                        //正确运行一次后可取消注释
	tree.Show(tree.root,0);
	cout<<endl<<"是否重建家谱?1.yes 2.no"<<endl;
	int chose;
	cin>>chose;
	if(chose==1){                                              //重建二叉树家谱
		system("cls");  
		cout<<"请按照前序输入二叉树"<<endl;
		tree.CreateBinaryTree(tree.root);
		tree.Show(tree.root,0);         
	}
	int con;
	do{
		cout<<endl<<"要查找谁的双亲、子女、兄弟?"<<endl;
		char name;
	    cin>>name;
		if(tree.Judge(name)){
			tree.Research(name,tree.root);
	    	cout<<endl;
        	tree.ReChild(tree.himself);
    		cout<<endl;
        	tree.ReBrother(tree.himself);
		}
		else{
			cout<<"家谱中没有此人"<<endl;
		}
    	cout<<"要给谁插入子女?"<<endl;
    	char na;
    	cin>>na;
		if (tree.Judge(na)){
			tree.Research(na,tree.root);	
	    	system("cls");
        	cout<<"请输入该子女的名称"<<endl;
        	char childname;
        	cin>>childname;
        	tree.Enter(childname,tree.himself);
     		system("cls");
     		tree.Show(tree.root,0);   
	    	cout<<endl<<"是否继续操作?1.yes 2.no"<<endl;
			cin>>con;
		}
		else{cout<<"家谱中没有此人"<<endl;}
    }while(con==1);
    tree.WriteBinaryTree();
    return 0;
}

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值