1:首先是头文件和全局变量的写入和定义:
#include
#include
#include
#define MAXSIZE 20
char vex[MAXSIZE] ; //存储读入的节点信息
int outDegree[MAXSIZE],
inDegree[MAXSIZE] ; //存储结点出入度
int visited[MAXSIZE] ; //进行DFS搜索遍历时用的访问数组
int LTnum = 0 ; //记录连通分量个数
2:然后定义数据结构:
//**********************************************数据结构定义
typedef struct ArcNode {
int adjvex ; //存储与当前结点连接的结点下标(在vex数组里的下标)
int weight ; //权值
struct ArcNode *next ;
}ArcNode ;
typedef struct VertexNode {
char vexdata ; //存储结点信息
ArcNode *head ; //存储链表的头指针,此链表存的是一个结点所有邻接信息
}VertexNode ;
typedef struct {
VertexNode vertex[MAXSIZE] ;
int vexnum ; //结点总个数
int arcnum ; //结点关系的总个数
}AdjList ;
//**********************************************队列结点定义(DFS遍历时需要用到)
typedef struct Node
{
int data; //存储类型
struct Node *next;
}qNode;
typedef struct
{
qNode *front;
qNode *rear;
}Queue;
3:接下来是邻接表的创建
int index(char ch,int vexnum){
/*求出ch的下标*/
int num = 1 ;
for(int i = 0; i < vexnum; i++){
if( ch == vex[i] ){
return num ;
}
num++ ;
}
}
void Create(AdjList *L){
/*创建有向邻接表*/
char a, b ;
int i, j, k;
ArcNode *p;
scanf("%d%d", &(*L).vexnum, &(*L).arcnum) ;
scanf("%s ", vex) ; //输入结点 加空格防止读取
了回车:这个特别坑!!!
for(i = 1; i <= (*L).vexnum; i++){
(*L).vertex[i].head = NULL ; //初始化指针数组
(*L).vertex[i].vexdata = vex[i-1] ; //存储vexdata的内容
}
for (i=0; i<(*L).arcnum; i++){
scanf(" %c%c", &a,&b); //空格作用同上
j = index(a, (*L).vexnum) ;
k = index(b, (*L).vexnum) ;
p = (ArcNode *)malloc(sizeof(ArcNode)) ;
p->adjvex = k ; //存入关系
p->next = (*L).vertex[j].head ; //采用头插法(不带头结点)
(*L).vertex[j].head = p ;
}
}
4:由于我们创建的邻接表是逆邻接表(尾插法太麻烦),所以函数我们再写一个函数将它逆置过来:
void Reverse(AdjList L, AdjList *B){
/*逆邻接表:新建立一个邻接表,将刚才的邻接表信息照搬过来,链表的信息重新头插一遍*/
int i,k;
ArcNode *p1,*p2;
(*B).vexnum = L.vexnum;
(*B).arcnum = L.arcnum;
for(i=1; i<=L.vexnum; i++){
(*B).vertex[i].vexdata = L.vertex[i].vexdata ; //
(*B).vertex[i].head = NULL ; //头指针赋空
}
for(i=1; i<=L.vexnum; i++){
p1 = L.vertex[i].head;
while(p1){
k = p1->adjvex ;
p2 = (ArcNode *)malloc(sizeof(ArcNode));
p2->adjvex = k ;
p2->next = (*B).vertex[i].head; //再头插一遍邻接表就会复原
(*B).vertex[i].head = p2;
p1 = p1->next;
}
}
}
5:打印出入度(可有可无,很简单):
void printDegree(AdjList L){
/*打印出入度:遍历一遍邻接表*/
int i ;
ArcNode *p = NULL ;
for( i = 1; i <= L.vexnum; i++ ){
p = L.vertex[i].head ;
while (p){
inDegree[p->adjvex]++ ;
outDegree[i]++ ;
p = p->next ;
}
}
for(i=1; i<=L.vexnum; i++){
printf("%c %d %d %d\n", L.vertex[i].vexdata, outDegree[i], inDegree[i], outDegree[i]+inDegree[i]);
}
}
6:DFS(深度优先遍历):
void DepthFirstSearch(AdjList L, int v){
/*采用递归深度遍历图的连通子图*/
int i ;
ArcNode *p ;
printf("%c", L.vertex[v].vexdata) ;
visited[v] = 1 ; //访问后访问数组置1
p = L.vertex[v].head ;
while (p){
if(visited[p->adjvex]==0)
DepthFirstSearch(L, p->adjvex) ;
p = p->next ;
}
}
void DFS(AdjList L){
/*遍历整个图*/
int i ;
for(i=1; i<=L.vexnum; i++){ //访问数组置0
visited[i] = 0 ;
}
for(i=1; i<=L.vexnum; i++){
if(!visited[i]){
LTnum++ ; //可以计算连通子图个数
DepthFirstSearch(L, i);
}
}
}
7:BFS(广度优先遍历)(采用队列):
(1):队列的操作:
Queue *Init_Queue()
/*初始化队列*/
{
Queue *q;
qNode *p;
q = (Queue *)malloc(sizeof(Queue));
p = (qNode *)malloc(sizeof(qNode));
p->next = NULL;
q->front = q->rear = p;
return q;
}
void In_Queue(Queue *q,int x)
/*入队*/
{
qNode *p;
p = (qNode *)malloc(sizeof(qNode));
p->data = x;
p->next = NULL;
q->rear->next = p;
q->rear = p;
}
int isEmpty(Queue *q)
/*判空*/
{
if(q->front==q->rear)
return 1;
else
return 0;
}
void Out_Queue(Queue *q,int *x)
/*出队*/
{
qNode *p;
if(isEmpty(q)){
printf("ERROR\n");
return;
}
else {
p = q->front->next;
q->front->next = p->next;
*x = p->data;
free(p);
if(q->front->next==NULL){
q->rear = q->front;
}
}
}
(2):BFS函数:
void BreadthFirstSearch(AdjList L, int v){
/*广度优先搜索连通子图:入队第一个结点并访问,将访问数组置1,当队列不为空时,出队结点,依次入队并访问未访问的结点*/
printf("%c", L.vertex[v].vexdata) ;
visited[v] = 1 ;
Queue *P = Init_Queue() ;
In_Queue(P, v) ;
ArcNode *p ;
while (!isEmpty(P)){
Out_Queue(P, &v) ;
p = L.vertex[v].head ;
while (p){
if(visited[p->adjvex]==0){
printf("%c", L.vertex[p->adjvex].vexdata) ;
visited[p->adjvex] = 1 ;
In_Queue(P, p->adjvex) ;
}
p = p->next ;
}
}
}
void BFS(AdjList L){ //广度优先遍历
int i ;
for(i=1; i<=L.vexnum; i++){
visited[i] = 0 ;
}
for(i=1; i<=L.vexnum; i++){
if(!visited[i]){
BreadthFirstSearch(L, i) ;
}
}
}
9:打印邻接表(用作调试):
void Print(AdjList L){
int i ;
ArcNode *p = NULL ;
for( i = 1; i <= L.vexnum; i++ ){
p = L.vertex[i].head ;
while (p){
printf("%d ", p->adjvex) ;
p = p->next ;
}
printf("\n") ;
}
}