圖的深度優先遍歷[非堆疊、堆疊實現]

gudesheng發表於2008-01-03
/*
    標題:<<系統設計師>>應試程式設計例項-[圖程式設計]
    作者:成曉旭
    時間:2002年09月06日(16:30:00-17:16:00)
          完成圖的建立函式、順序遍歷函式
    時間:2002年09月08日(21:30:00-22:35:00)
          完成圖的深度優先遍歷函式[非堆疊、堆疊實現]
*/

#include    
"stdio.h"
#include    
"stdlib.h"

//如:FROMHEAD = 1,則用頭插法;否則:則用尾插法
#define     FROMHEAD 1
/*
    如:HASHEAD 被定義,則各頂點的鄰接點鏈中<帶起始頂點>;
    否則:各頂點的鄰接點鏈中<不帶起始頂點>;
*/

#define        NODE_NUM        5
#ifdef HASHEAD
    
//<帶起始頂點>
    int GraphNode[NODE_NUM][3= {{1,'A',4},{2,'B',4},{3,'C',5},{4,'D',5},{5,'E',3}};
    
int ConnectTable[] = {0,1,2,3,1,0,2,3,2,0,1,3,4,3,0,1,2,4,4,2,3};
#else
    
//<不帶起始頂點>
    int GraphNode[NODE_NUM][3= {{1,'A',3},{2,'B',3},{3,'C',4},{4,'D',4},{5,'E',2}};
    
int ConnectTable[] = {1,2,3,0,2,3,0,1,3,4,0,1,2,4,2,3};
#endif

//鄰接表中圖各頂點結構型別定義
#define    gVertexNode    struct    gVertexNode
gVertexNode
{
    
int    order;                //頂點在圖中的序號
    int    data;                //頂點的資料域
    gVertexNode *link;        //指向頂點的下一個鄰接頂點節點的指標
}
;
//鄰接表中圖各頂點的遍歷頭節點結構型別定義
#define    gHeadNode    struct    gHeadNode
gHeadNode
{
    
int    vcount;                //鄰接連結串列的節點數目[即當前頂點的鄰接頂點個數]
    
//int    order;                //頂點在圖中的序號
    int    data;            //頂點的資料域
    gVertexNode *firstnode;    //指向鄰接表的首頂點節點的指標
}
;
/*
    建立以鄰接表方式儲存的圖
    引數描述:
    gHeadNode    HeadNode    圖的鄰接儲存的頭節點陣列
    int            max:圖的頂點個數
    int            fromhead:插入鄰接佔點的方式
                    fromhead=1    頭插入方式
                    fromhead=0    尾插入方式
*/

void    CreateGraph(gHeadNode HeadNode[],int max,int fromhead)
{
    gVertexNode 
*p,*tail;    //當前頂點節點及鄰接表當前節點的鄰接連結串列的尾節點
    int    i,j,k;    //i,j為迴圈計數器,k為當前頂點的鄰接頂點數目
    for(i=0;i<max;i++)
    
{
        HeadNode[i].vcount 
= GraphNode[i][2];
        HeadNode[i].data 
= GraphNode[i][1];
        HeadNode[i].firstnode 
= NULL;
        
//printf(" 頂點[%c]有[%d]個鄰接點! ",HeadNode[i].data,HeadNode[i].vcount);
    }

    
for(i=0,k=0;i<max;i++)
    
{
        
for(j=0;j<HeadNode[i].vcount;j++)
        
{
            
//建立圖的頂點節點
            p = (gVertexNode *)malloc(sizeof(gVertexNode));
            
if(p==NULL)
            
{
                exit(
1);
            }

            
else
            
{
                
//圖的新頂點賦值
                p->order = GraphNode[ConnectTable[k+j]][0];
                p
->data  = GraphNode[ConnectTable[k+j]][1];
                p
->link  = NULL;
                
if(fromhead)
                
{//新節點放在最前面<緊接頭節點的後面>頭插法
                    p->link = HeadNode[i].firstnode;
                    HeadNode[i].firstnode 
= p;
                }

                
else
                
{//新節點放在最後面<緊接最後一個表節點的後面>尾插法
                    if(HeadNode[i].firstnode == NULL)
                    
{//插入第一個節點
                        HeadNode[i].firstnode = p;
                        tail 
= p;
                    }

                    
else
                    
{//插入非第一個節點[直接接到最後一個節點之後]
                        tail->link = p;
                        tail 
= p;
                    }

                }


            }

        }

        
//移動關聯表計數位置“指標”
        k = k + HeadNode[i].vcount;
    }

}

/*
    順序訪問圖中的各個節點[以建立的鄰接表的頭節點陣列前後順序]
    引數描述:
    gHeadNode    HeadNode    圖的鄰接儲存的頭節點陣列
    int            max:圖的頂點個數
*/

void    Sequence_Journey(gHeadNode HeadNode[],int max)
{
    gVertexNode 
*p;
    
int i;
    printf(
"以建立的鄰接表的頭節點陣列前後順序訪問的圖: ");
    
for(i=0;i<max;i++)
    
{
        p 
= HeadNode[i].firstnode;
        
//printf(" 頂點[%c]的[%d]個鄰接點: ",HeadNode[i].data,HeadNode[i].vcount);
        while(p != NULL)
        
{
            printf(
"頂點[%d][%c] ",p->order,p->data);
            p 
= p->link;
        }

        printf(
" ");
    }

}

//圖的[深度優先遍歷]演算法<非堆疊實現演算法>
void    nsDeepthFirst_Journey(gHeadNode HeadNode[],int max)
{
    gVertexNode 
*p;        //頂點
    int    visited[NODE_NUM];    //0:未訪問        1:已訪問
    int    i;
    printf(
"圖的[深度優先遍歷]結果<非堆疊實現>: ");
    
for(i=0;i<max;i++)        //設定所有的頂點未訪問標誌
        visited[i] = 0;
    
for(i=0;i<max;i++)
    
{
        p 
= HeadNode[i].firstnode;    //指向當前訪問頂點
        
//printf("頂點[%d][%c] ",p->order,p->data);
        while(p != NULL)    //如果頂點有鄰接頂點
        {
            
if(visited[p->order] == 0)
            
{//當前頂點的鄰接頂點還未訪問
                printf("頂點[%d][%c] ",p->order,p->data);
                visited[p
->order] = 1;
            }

            p 
= p->link;        //移向下一個頂點
        }

    }

}

//圖的[深度優先遍歷]演算法<堆疊實現演算法>
void    DeepthFirst_Journey(gHeadNode HeadNode[],int max)
{
    gVertexNode 
*p;        //頂點
    gVertexNode *vstack[NODE_NUM+1];    //頂點堆疊
    int    visited[NODE_NUM+1];    //0:未訪問        1:已訪問
    int    i,top;        //迴圈計數器和堆疊指標
    printf("圖的[深度優先遍歷]結果<堆疊實現>: ");
    
for(i=0;i<=max;i++)        //設定所有的頂點未訪問標誌
        visited[i] = 0;
    
for(i=0;i<max;i++)
    
{
        top 
= 1;
        vstack[top] 
= HeadNode[i].firstnode;//將本次訪問的起始節點進棧,以便將來正確返回
        while(top != 0)    //堆疊不為空
        {
            p 
= vstack[top];    //取堆疊中的棧頂元素
            while((p != NULL) && (visited[p->order] == 1))    //還有鄰接頂點,且已被訪問
                p = p->link;
            
if(p == NULL)    //當前頂點沒有鄰接頂點,或有,但都已經被訪問過
                top--;    //完成退棧
            else
            
{//否則,則訪問之
                printf("頂點[%d][%c] ",p->order,p->data);
                visited[p
->order] = 1;
                vstack[
++top] = p;    //訪問頂點進棧
            }

        }

    }

}

int main(int argc, char* argv[])
{
    gHeadNode HeadNodeArray[NODE_NUM];
    
int    InsertMode = -1;
    
while(InsertMode != 0 && InsertMode != 1)
    
{
        printf(
"請輸入頂點的插入方式[0尾插入法:/1:頭插入法]");
        scanf(
"%d",&InsertMode);
    }

    CreateGraph(HeadNodeArray,NODE_NUM,InsertMode);
    Sequence_Journey(HeadNodeArray,NODE_NUM);
    
//nsDeepthFirst_Journey(HeadNodeArray,NODE_NUM);
    DeepthFirst_Journey(HeadNodeArray,NODE_NUM);
    printf(
" 應用程式執行結束! ");
    
return 0;
}




Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=935905


相關文章