/// 10_16 利用圖的深度優先搜索和廣度優先搜索各寫一個算法,
/// 判別以鄰接表方式表示的有向圖中是否存在由頂點
/// vi到頂點vj的路徑(i!=j)
#include "stdafx.h"
#include <stdlib.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include "Chapter10.h"
void initializeGraph(vexNode* head, const int numOfVex)
//初始化一個以head爲頭節點,長度爲numOfVex的鄰接表
{
for(int i = 0; i < numOfVex; i++)
{
(head + i)->vertex = ' ';
(head + i)->pLink = NULL;
}
}
void initializeEdgeNode(edgeNode* head)
//初始化一個edgeNode節點
{
head->adjvex = -1;
head->pNext = NULL;
}
edgeNode* newEdgeNode()
//用來分配空間
{
edgeNode* head = NULL;
head = (edgeNode*)malloc(sizeof(edgeNode));
if(head == NULL)
{
printf("分配空間出錯!/n");
exit(1);
}
initializeEdgeNode(head);
return head;
}
vexNode* constructGraph(const int size)
//生成鄰接表的函數
{
char ch = 'A';
int tempVex = 0;
srand((unsigned)time(NULL));
vexNode* vexes = (vexNode*)malloc(sizeof(vexNode) * size);
initializeGraph(vexes, size);
edgeNode* r = NULL;
edgeNode* s = NULL;
int totalEdges = 0;
for(int i = 0; i < size; i++, ch++)
{
r = NULL;
(vexes + i)->vertex = (char)('a' + i);
for (int j = 0; j < size; j++)
{
if (j == i)
{
continue;
}
//避免生成與自己相連的邊
if ((tempVex = (rand() % 4) )== 1)
//隨機地生成與這個頂點相連的邊
{
s = newEdgeNode();
totalEdges++;
s->adjvex = j;
if (r == NULL)
{
(vexes + i)->pLink = s;
}
else
{
r->pNext = s;
}
r = s;
}
}
}
printf("已生成鄰接表,頂點數爲%d,邊數爲%d。/n", NUM_OF_VEX, totalEdges);
printEdges(vexes, size);
return vexes;
}
void printEdges(vexNode* vexes, const int size)
//顯示所有的頂點和邊
{
printf("鄰接表的信息爲:/n");
printf("頂點/t相鄰的頂點/n");
edgeNode* tempNode = NULL;
for (int i = 0; i < size; i++)
{
printf("%c/t", (vexes + i)->vertex);
tempNode = (vexes + i)->pLink;
while (tempNode != NULL)
{
printf("%c/t", tempNode->adjvex + 'a');
tempNode = tempNode->pNext;
}
printf("/n");
}
}
vexNode* searchNode(vexNode* vexes, const int size, const char data)
//在以vexes爲首,大小爲size的鄰接表中查找vertex爲data的節點的函數
{
vexNode* t = vexes;
vexNode* s = NULL;
for (int i = 0; (i < size) && (t->vertex != data); i++)
{
t++;
}
if (t->vertex == data)
{
s = t;
}
else
{
return NULL;
}
return s;
}
void findPathDepth(vexNode* graph, const int size, const char source, const char target)
//在先序遍歷的基礎上作的查找從source到target的路徑的程序,深度優先
{
int stack[NUM_OF_VEX * NUM_OF_VEX] = {NULL};
int top = -1;
int i = 0; //循環計數器
vexNode* s = NULL;
vexNode* t = graph;
vexNode* r = NULL;
s = searchNode(graph, size, source);
r = searchNode(graph, size, target);
//以上將s和r調整到source和target對應的位置
printf("進行深度優先查找……/n");
if (s == NULL || r == NULL)
{
printf("空的起始/終結節點,不進行路徑查找!/n");
return;
}
t = s;
edgeNode* tempedgeNode = s->pLink;
do
{
while (tempedgeNode != NULL)
{
if ((graph + tempedgeNode->adjvex)->vertex == target)
{
printf("有從節點%c到節點%c的路徑!/n", source, target);
return;
}
top++;
stack[top] = tempedgeNode->adjvex; //s的臨接頂點的位置入棧
tempedgeNode = tempedgeNode->pNext;
}
while(tempedgeNode == NULL && top >= 0)
{
t = graph + stack[top];
top--;
tempedgeNode = t->pLink;
}
}
while(top >= 0 && top < 64);
printf("沒有從節點%c到節點%c的路徑!/n", source, target);
}
void findPathWidth(vexNode* graph, const int size, const char source, const char target)
//在先序遍歷的基礎上作的查找從source到target的路徑的程序,廣度優先
{
int stack[NUM_OF_VEX * NUM_OF_VEX] = {NULL};
int front = 0;
int rear = -1;
int i = 0; //循環計數器
vexNode* s = NULL;
vexNode* t = graph;
vexNode* r = NULL;
s = searchNode(graph, size, source);
r = searchNode(graph, size, target);
//以上將s和r調整到source和target對應的位置
printf("進行廣度優先查找……/n");
if (s == NULL || r == NULL)
{
printf("空的起始/終結節點,不進行路徑查找!/n");
return;
}
t = s;
edgeNode* tempedgeNode = s->pLink;
do
{
while (tempedgeNode != NULL)
{
if ((graph + tempedgeNode->adjvex)->vertex == target)
{
printf("有從節點%c到節點%c的路徑!/n", source, target);
return;
}
rear++;
stack[rear] = tempedgeNode->adjvex; //s的臨接頂點的位置入隊
tempedgeNode = tempedgeNode->pNext;
}
while(tempedgeNode == NULL && front <= rear)
{
front++;
t = graph + stack[front];
tempedgeNode = t->pLink;
}
}
while(front <= rear);
printf("沒有從節點%c到節點%c的路徑!/n", source, target);
}
void visit(vexNode* vex)
{
printf("%c", vex->vertex);
}
int _tmain(int argc, _TCHAR* argv[])
{
vexNode* head = NULL;
char ch = 'y';
char source = '/0';
char target = '/0';
head = constructGraph(NUM_OF_VEX);
while(ch == 'y')
{
printf("請輸入一個從%c到%c的字母作爲起始節點:", 'a', 'a' + NUM_OF_VEX - 1);
source = getche();
printf("/n請輸入一個從%c到%c的字母作爲結束節點:", 'a', 'a' + NUM_OF_VEX - 1);
target = getche();
printf("/n");
findPathDepth(head, NUM_OF_VEX, source, target);
findPathWidth(head, NUM_OF_VEX, source, target);
printf("/n還繼續嗎(請輸入y以繼續)?");
ch = getche();
printf("/n");
}
return 0;
}