调了一个晚上终于把这段程序给调通了,原来对孩子兄弟链表的理解有点偏差,还有就是对递归有了跟深刻的理解,当然最大的收获就是发现程序中错误的能力进一步提高,借助于Visual Stdio这个强大的编程环境,可以让我迅速地积累编程经验,快速的发现程序中隐含的漏洞,而且他强大的自定义功能也让编程变得得心应手。推荐使用。。。
"head.h"
#include<iostream>
#define MAX_VEX_NUM 20
using namespace std;
class NODE//记录孩子结点的序号等信息
{
public:
NODE();
int child;
NODE * next;
};
NODE::NODE()
{
child=0;
next=NULL;
}
class VexNode//记录顶点信息
{
public:
VexNode();
bool visited;
char vexname;
NODE * firstchild;
};
VexNode::VexNode()
{
visited=false;
firstchild=NULL;
}
class VexBox//储存图的邻接表
{
public:
VexBox();
VexNode vexbox[MAX_VEX_NUM];
int vexnum;
};
VexBox::VexBox()
{
vexnum=0;
}
class CSTreeNode//生成树节点
{
public:
CSTreeNode();
char name;
CSTreeNode *lchild,*rsibling;
};
CSTreeNode::CSTreeNode()
{
lchild=rsibling=NULL;
}
class Graph
{
public:
Graph();
void ShowGraph();//接口函数
private:
void GetVexList();//得到顶点信息
void GetChild();//得到各个顶点的孩子信息
void DFSForest();
void DFSTree(int ,CSTreeNode *);
void Print();//输出图的顶点孩子信息
void PrintTree();
void InOrderPrintTree(CSTreeNode *);//中序输出生成树
VexBox l;//定义一个邻接表
CSTreeNode *root;//生成树根
};
Graph::Graph()
{
root=NULL;
}
void Graph::ShowGraph()//接口函数
{
cout<<"ShowGraph Called !"<<endl<<endl;
GetVexList(); //得到顶点信息
GetChild();//得到各个顶点的孩子信息
Print();//输出邻接表信息
DFSForest();//深度优先遍历该图并建立连通分量的生成森林
PrintTree();//输出各连通分量
}
void Graph::GetVexList()//得到顶点信息
{
cout<<"GetVexList Called !"<<endl<<endl;
cout<<"Please Enter The Vertexes :"<<endl<<endl;
char name;
while(cin>>name)
{
l.vexbox[l.vexnum++].vexname=name;
}
cin.clear();
}
void Graph::GetChild()//得到各个顶点的孩子信息
{
cout<<"GetChild Called !"<<endl<<endl;
int num;
NODE *p,*newnode;
for(int i=0;i<l.vexnum;i++)
{
cout<<"Input The Children Of VerTex "<<l.vexbox[i].vexname<<" : "<<endl<<endl;
while(cin>>num)
{
newnode=new NODE;
newnode->child=num;
if((p=l.vexbox[i].firstchild)==NULL)
{
l.vexbox[i].firstchild=newnode;
}
else
{
while(p->next!=NULL)
{
p=p->next;
}
p->next=newnode;
}
}
cin.clear();
}
}
void Graph::Print()//输出邻接表信息
{
cout<<"Print Called !"<<endl<<endl;
NODE * p;
for(int i=0;i<l.vexnum;i++)
{
p=l.vexbox[i].firstchild;
cout<<l.vexbox[i].vexname<<" : "<<endl;
while(p!=NULL)
{
cout<<"\t"<<l.vexbox[p->child].vexname<<endl;
p=p->next;
}
}
}
void Graph::DFSForest()//深度优先遍历该图并建立连通分量的生成森林
{
cout<<"DFSForest Called !"<<endl<<endl;
CSTreeNode *p,*newnode;
for(int i=0;i<l.vexnum;i++)//对列表内的所有节点进行遍历
{
if(l.vexbox[i].visited==false)//如果未被访问
{
newnode=new CSTreeNode;//新开辟一个节点
newnode->name=l.vexbox[i].vexname;//当前节点名字赋给新的节点
if(root==NULL)//如果root未指向任何节点
{
p=root=newnode;
}
else
{
p->rsibling=newnode;//否则就把新开辟的节点挂在右兄弟上
p=p->rsibling;//p指向新开辟的节点
}
DFSTree(i,p);//以p为根节点建立新树
}
}
}
void Graph::DFSTree(int i,CSTreeNode *t)//左孩子右兄弟,左孩子右兄弟!!!在这纠结了半天
{
bool first=true;
l.vexbox[i].visited=true;//标记为已访问
NODE*q=l.vexbox[i].firstchild;
CSTreeNode * newnode,*p;
while(q!=NULL)
{
if(l.vexbox[q->child].visited==false)//如果未被访问
{
l.vexbox[q->child].visited=true;
newnode=new CSTreeNode;
newnode->name=l.vexbox[q->child].vexname;
if(first)//孩子
{
t->lchild=newnode;
p=newnode;
first=false;
}
else//兄弟
{
p->rsibling=newnode;
p=p->rsibling;
}
DFSTree(q->child,newnode);
}
q=q->next;
}
}
void Graph::PrintTree()//调用InOrderPrintTree()输出生成森林的相关信息
{
cout<<"PrintTree Called !"<<endl<<endl;
CSTreeNode *p=root;
while(p!=NULL)
{
cout<<p->name;
InOrderPrintTree(p->lchild);
cout<<endl<<endl;
p=p->rsibling;
}
}
void Graph::InOrderPrintTree(CSTreeNode *t)//递归遍历每一棵树
{
if(t==NULL)
return;
cout<<t->name;
InOrderPrintTree(t->lchild);
InOrderPrintTree(t->rsibling);
}
"main.cpp"
#include"head.h"
int main()
{
Graph g;
g.ShowGraph();
system("pause");
}