/*============================================================
功能描述:
* 前序扩展建立二叉树家谱(左子树为子女,右子树为兄弟)
* 使用栈查找指定节点(非递归)
* 可写入和读取文件
* 可查找双亲、子女、兄弟
* 图层显示二叉树家谱
* 已注释读取文件,正确运行一次后可取消注释
* 前序扩展建立输入二叉树输入格式: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;
}
二叉树家谱
最新推荐文章于 2022-11-22 20:19:00 发布