整形圖的深度遍歷和廣度遍歷
阿新 • • 發佈:2018-11-12
比較簡單的實現,圖採用鄰接矩陣的儲存方式,且沒有加上覆制建構函式和過載運算子。
#include <iostream>
#include<stdexcept>
#include<stdio.h>
using namespace std;
struct Node
{
int data;
Node *next;
Node(){next=NULL;}
Node(int item,Node *link=NULL)
{
data=item;
next=link;
}
};
class LinkQueue
{
protected:
Node *front,*rear;
int count;
public:
LinkQueue(){rear=front=new Node();count=0;}
virtual ~LinkQueue();
int length()const{return count;}
bool Empty()const{return count==0;}
void Clear();
void Traverse()const;
bool OutQueue(int &e);
bool GetHead(int &e)const;
bool InQueue(const int &e);
LinkQueue(const LinkQueue ©);
LinkQueue&operator=(const LinkQueue ©);
};
LinkQueue::~LinkQueue()
{
Clear();
}
void LinkQueue::Clear()
{
int tmp;
while(!Empty())
OutQueue(tmp);
}
void LinkQueue::Traverse()const
{
for(Node *tmp=front->next;tmp!=NULL;tmp=tmp->next)
cout<<tmp->data<<' ';
}
bool LinkQueue::OutQueue(int &e)
{
if(!Empty())
{
Node *tmp=front->next;
e=tmp->data;
front->next=tmp->next;
if(rear==tmp)
rear=front;
delete tmp;
count--;
return true;
}
else
return false;
}
bool LinkQueue::GetHead(int &e)const
{
if(!Empty())
{
Node *tmp=front->next;
e=tmp->data;
return true;
}
else
return false;
}
bool LinkQueue::InQueue(const int &e)
{
Node *tmp=new Node(e);
rear->next=tmp;
rear=tmp;
count++;
return true;
}
LinkQueue::LinkQueue(const LinkQueue©)
{
rear=front=new Node();
count=0;
for(Node *tmp=copy.front->next;tmp!=NULL;tmp=tmp->next)
InQueue(tmp->data);
}
LinkQueue&LinkQueue::operator=(const LinkQueue©)
{
if(©!=this)
{
Clear();
for(Node *tmp=copy.front->next;tmp!=NULL;tmp=tmp->next)
InQueue(tmp->data);
}
return *this;
}
class AdjMatrixDirGraph
{
protected:
int vexNum,edgeNum; //頂點數和邊數
int **Matrix; //領接矩陣
int *elems; //頂點元素
mutable bool *tag; //指向標誌陣列的指標
void DestroyHelp(); //銷燬有向圖
void DFS(int v)const; //從頂點v開始深度優先遍歷
void BFS(int v)const; //從頂點v開始廣度優先遍歷
public:
AdjMatrixDirGraph(int es[],int vertexNum=10); //構造資料元素為es,頂點個數為vertexNum,邊數為0的有向圖
AdjMatrixDirGraph(int vertexNum=10); //構造頂點個數為vertexNum變數為0的有向圖
~AdjMatrixDirGraph(); //解構函式
void DFSTraverse()const; //對圖進行深度優先遍歷
void BFSTraverse()const; //對圖進行廣度優先遍歷
bool GetElem(int v,int &e)const; //求頂點的元素
bool SetElem(int v,const int &e); //設定頂點的元素
int GetVexNum()const{return vexNum;} //返回頂點個數
int GetEdgeNum()const{return edgeNum;} //返回邊的條數
int FirstAdjVex(int v)const; //返回頂點v的第一個鄰接頂點
int NextAdjVex(int v1,int v2)const; //返回頂點v1的相對於v2的下一個鄰接點
void InsertEdge(int v1,int v2); //插入頂點為v1和v2的邊
void DeleteEdge(int v1,int v2); //刪除頂點為v1和v2的邊
bool GetTag(int v)const; //返回頂點v的標誌
void SetTag(int v,bool val)const; //設定v1的標誌為val
void Display()const; //顯示關係矩陣
};
void AdjMatrixDirGraph::DestroyHelp()
{
delete[] elems;
delete[] tag;
for(int i=0;i<vexNum;i++)
delete []Matrix[i];
delete []Matrix;
}
void AdjMatrixDirGraph::DFS(int v)const
{
SetTag(v,true);
int e;
GetElem(v,e);
cout<<e<<' ';
for(int w=FirstAdjVex(v);w>=0;w=NextAdjVex(v,w))
if(!GetTag(w))
DFS(w);
}
void AdjMatrixDirGraph::DFSTraverse()const
{
int v;
for(v=0;v<GetVexNum();v++)
SetTag(v,false);
cout<<"深度遍歷:";
for(v=0;v<GetVexNum();v++)
if(!GetTag(v))
DFS(v);
}
void AdjMatrixDirGraph::BFS(int v)const
{
SetTag(v,true);
int e;
GetElem(v,e);
cout<<e<<' ';
LinkQueue q;
q.InQueue(v);
while(!q.Empty())
{
int u,w;
q.OutQueue(u);
for(w=FirstAdjVex(u);w>=0;w=NextAdjVex(u,w))
{
if(!GetTag(w))
{
SetTag(w,true);
GetElem(w,e);
cout<<e<<' ';
q.InQueue(w);
}
}
}
}
void AdjMatrixDirGraph::BFSTraverse()const
{
int v;
for(v=0;v<vexNum;v++)
SetTag(v,false);
cout<<"廣度遍歷:";
for(v=0;v<vexNum;v++)
if(!GetTag(v))
BFS(v);
}
AdjMatrixDirGraph::AdjMatrixDirGraph(int es[],int vetexNum)
{
if(vetexNum<=0)
throw runtime_error("頂點數不能小於等於0");
vexNum=vetexNum,edgeNum=0;
Matrix=new int*[vexNum];
elems=new int[vexNum];
tag=new bool[vexNum];
for(int i=0;i<vexNum;i++)
Matrix[i]=new int[vexNum];
for (int u = 0; u < vexNum; u++)
for (int v = 0; v < vexNum; v++)
Matrix[u][v] = 0;
for(int i=0;i<vexNum;i++)
elems[i]=es[i];
for(int i=0;i<vexNum;i++)
tag[i]=false;
}
AdjMatrixDirGraph::AdjMatrixDirGraph(int vetexNum)
{
if(vetexNum<0)
throw runtime_error("頂點數不能小於等於0");
vexNum=vetexNum,edgeNum=0;
Matrix=new int*[vexNum];
elems=new int[vexNum];
tag=new bool[vexNum];
for(int i=0;i<vexNum;i++)
Matrix[i]=new int[vexNum];
for (int u = 0; u < vexNum; u++)
for (int v = 0; v < vexNum; v++)
Matrix[u][v] = 0;
for(int i=0;i<vexNum;i++)
tag[i]=false;
}
AdjMatrixDirGraph::~AdjMatrixDirGraph()
{
DestroyHelp();
}
bool AdjMatrixDirGraph::GetElem(int v,int &e)const
{
if(v<0||v>=vexNum)
return false;
else
{
e=elems[v];
return true;
}
}
bool AdjMatrixDirGraph::SetElem(int v,const int &e)
{
if(v<0||v>=vexNum)
return false;
else
{
elems[v]=e;
return true;
}
}
int AdjMatrixDirGraph::FirstAdjVex(int v)const
{
int i=0;
while(Matrix[v][i]==0&&i<vexNum)
i++;
if(Matrix[v][i]==1)
return i;
return -1;
}
int AdjMatrixDirGraph::NextAdjVex(int v1,int v2)const
{
while(Matrix[v1][++v2]==0&&v2<vexNum)
if(Matrix[v1][v2]==1)
return v2;
return -1;
}
void AdjMatrixDirGraph::InsertEdge(int v1,int v2)
{
if(v1<0||v1>=vexNum) throw runtime_error("v1不合法");
if(v2<0||v2>=vexNum) throw runtime_error("v2不合法!");
if(v1==v2) throw runtime_error("v1不能等於v2!");
if(Matrix[v1][v2]==0&&Matrix[v2][v1]==0)
edgeNum++;
Matrix[v1][v2]=1;
Matrix[v2][v1]=1;
}
void AdjMatrixDirGraph::DeleteEdge(int v1,int v2)
{
if(v1<0||v1>=vexNum) throw runtime_error("v1不合法!");
if(v2<0||v2>=vexNum) throw runtime_error("v2不合法!");
if(v1==v2) throw runtime_error("v1不能等於v2!");
if(Matrix[v1][v2]==1&&Matrix[v2][v1]==1)
edgeNum--;
Matrix[v1][v2]=0;
Matrix[v2][v1]=0;
}
bool AdjMatrixDirGraph::GetTag(int v)const
{
if(v<0||v>=vexNum)
throw runtime_error("v不合法");
else
return tag[v];
}
void AdjMatrixDirGraph::SetTag(int v,bool val)const
{
if(v<0||v>=vexNum)
throw runtime_error("v不合法");
else
tag[v]=val;
}
void AdjMatrixDirGraph::Display()const
{
for(int i=0;i<vexNum;i++)
{
for(int j=0;j<vexNum;j++)
cout<<Matrix[i][j]<<' ';
cout<<endl;
}
}
int main()
{
int vetexNum,edgeNum,v1,v2;
cout<<"請輸入頂點個數:";
cin>>vetexNum;
int es[vetexNum];
for(int i=0;i<vetexNum;i++)
{
cout<<"請輸入頂點編號為"<<i<<"的頂點的值:";
cin>>es[i];
}
AdjMatrixDirGraph g(es,vetexNum);
cout<<"請輸入邊的條數:";
cin>>edgeNum;
for(int i=0;i<edgeNum;i++)
{
cout<<"請輸入所要插入的第"<<i+1<<"條邊的兩個端點(以空格隔開):";
scanf("%d %d",&v1,&v2);
g.InsertEdge(v1,v2);
}
g.Display();
g.DFSTraverse();
g.BFSTraverse();
return 0;
}