数据结构_图_邻接表做存储结构实现求无向图的连通分量_C++实现
调了一个晚上终于把这段程序给调通了,原来对孩子兄弟链表的理解有点偏差,还有就是对递归有了跟深刻的理解,当然最大的收获就是发现程序中错误的能力进一步提高,借助于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");
}