1. 程式人生 > >資料結構之——用C++實現鄰接表的DFS與BFS

資料結構之——用C++實現鄰接表的DFS與BFS

首先我們要知道鄰接表的基本思想:

鄰接表儲存的基本思想:對於圖的每個頂點vi將所有鄰接於vi的頂點鏈成一個單鏈表,稱為頂點vertex邊表(對於有向圖則稱為出邊表),所有邊表的頭指標和儲存頂點資訊的一維陣列構成了頂點表

在這裡我打算將一個無向圖的鄰接表的建立,以及相應的深度優先搜尋和廣度優先搜尋

首先我們要明白一個鄰接表是什麼樣的,看下面這個圖:


這是一個無向圖,與之對應的鄰接表如下:


可以看到最左邊縱向的一排結點和右邊的結點有所區別

在鄰接表中,我們將其分為兩個部分:

頂點結點與邊結點

其中頂點結點的寫法如下:

class vertex				//頂點類 
    {
        public:
        char data;			//頂點資訊 
        edge *firstedge;		//頂點指向邊的指標
        vertex() {firstedge = NULL;}
    };
頂點結點中包含了頂點的名稱與頂點所指向的邊

邊結點的寫法如下:

class edge				//邊類 
    {
        public:
        int adjvex;			//該邊所指向的點的資訊 
        edge *nextedge;			//指向下一條邊
        edge() {nextedge = NULL;}
        //int weight;<span style="white-space:pre">			</span>//權值
    };
邊結點則分為 邊所指向的頂點的資訊 與 該邊指向的下一條邊

從圖解中可以看出,左邊縱向的一列是頂點資訊,頂點採用順序表的方式儲存,每個頂點對應的一個橫行是從該頂點出發所能到達的所有點對應的邊

整個圖結構大致如下(不包含函式):

class graph						//圖類 
{
    public:
    class edge					//邊類 
    {
        public:
        int adjvex;				//該邊所指向的點的資訊 
        edge *nextedge;			//指向下一條邊
        edge() {nextedge = NULL;}
        int weight;
    };
    class vertex				//頂點類 
    {
        public:
        char data;				//頂點資訊 
        edge *firstedge;		//頂點指向邊的指標
        vertex() {firstedge = NULL;}
    };


接下來給個原始碼:

/*************************************************************************
	> File Name: graph.cpp
	> Author: James
	> Mail: [email protected]
	> Created Time: Wed 09 Dec 2015 11:23:55 AM GMT
 ************************************************************************/

#define MAX 20
#define TRUE 1
#define FALSE 0
#include<iostream>

using namespace std;
class graph						//圖類 
{
    public:
    class edge					//邊類 
    {
        public:
        int adjvex;				//該邊所指向的點的資訊 
        edge *nextedge;			//指向下一條邊
        edge() {nextedge = NULL;}
        int weight;
    };
    class vertex				//頂點類 
    {
        public:
        char data;				//頂點資訊 
        edge *firstedge;		//頂點指向邊的指標
        vertex() {firstedge = NULL;}
    };

    graph();					//建立圖的建構函式 
    ~graph(){};					//解構函式 
    void print();				//列印圖的資訊 
    int getPosition(char ch);	//確定輸入的邊的頂點 
    void linkList(edge *before, edge *after);	//連線一個頂點的多條邊 
    char readChar();			//讀入資料 
    void DFS(graph *G,int vertexnum);
    void BFS(graph *G,int vertexnum);
    private:
    int vexnum;					//頂點總數 
    int edgnum;					//邊總數 
    vertex vexs[MAX];			//陣列形式的頂點 
};
int DFSvisited[MAX] = {FALSE};
int BFSvisited[MAX] = {FALSE};

typedef struct QNode			//隊中結點結構 
{
    int data;
    struct QNode *next;
}QNode, *QueuePtr;

typedef struct					  //隊的結構 
{
    QueuePtr front;   		   	 //隊頭指標
    QueuePtr rear;  			 //隊尾指標
}LinkQueue;		


int InitQueue(LinkQueue *Q)		 //初始化隊 
{
    Q->front = Q->rear = new QNode;
    if (!Q->front)				 
    {
        return -1;
    }
    Q->front->next = NULL;
    return 0;
}
int EnQueue(LinkQueue *Q, int e)//入隊 
{
    QueuePtr p = new QNode;
    if (!p)
    {
        return -1;
    }
    p->data = e;
    p->next = NULL;
    Q->rear->next = p;			//最後一個結點指向新加入的結點p 
    Q->rear = p;				//隊尾指標指向新加入的結點p 
    return 0;
}

int DeQueue(LinkQueue *Q)	//出隊 
{	
    QueuePtr p;
    if (Q->front == Q->rear)
    {
        return -1;
    }
    p = Q->front->next;				//p指向隊頭結點的下一個結點 
    int a = p->data;
    Q->front->next = p->next;		//隊頭結點直接指向下下個結點 
    if (Q->rear == p)
    {
        Q->rear = Q->front;
    }
    delete p;
    return a;
}
int QueueEmpty(LinkQueue Q)
{
    if (Q.front->next == NULL)
    {
        return TRUE;
    }
    else
    {
        return FALSE;
    }
}


int graph::getPosition(char ch)
{
        int i;
        for(i = 0; i < vexnum; i++)
            if(vexs[i].data == ch)
                return i;
        return -1;

}

char graph::readChar()
{
        char ch = 'a';
		while(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));		//頂點為字母 
		{
			cin>>ch;
		}
        return ch;

}
void graph::linkList(edge *before, edge *after)
{
    //edge *p = before;

    while(before->nextedge)
        before = before->nextedge;
    before->nextedge = after;
}

graph::graph()
{
    char c1;char c2;
    int v;int e;
    int i;int p1;int p2;
    int weight;
    edge *edge1 = NULL, *edge2 = NULL;
    cout<<"input vertex number: ";
    cin>>vexnum;
    cout<<"input edge number: ";
    cin>>edgnum;

    for(i = 0;i<vexnum;i++)				//初始化各頂點 
    {
        cout<<"vertex("<<i<<"):";
        vexs[i].data = readChar();
        vexs[i].firstedge = NULL;
    }
    for(i = 0; i<edgnum; i++)				// 讀取邊的起始頂點和結束頂點
    {
        cout << "edge(" << i << "): ";
        c1 = readChar();
        c2 = readChar();

        p1 = getPosition(c1);
        p2 = getPosition(c2);							// 初始化edge1
        cout<<"weight:";
        cin>>weight;
        edge1 = new edge();
        edge1->weight = weight;
        edge1->adjvex = p2;								//將edge1連線到p1所在連結串列的末尾
        if(vexs[p1].firstedge == NULL)
          vexs[p1].firstedge = edge1;
        else
            linkList(vexs[p1].firstedge,edge1);			// 初始化edge2
        edge2  =  new edge();
        edge2->weight = weight;
        edge2->adjvex  =  p1;								//無向圖,交換P1/P2位置重複上方操作 
        if(vexs[p2].firstedge == NULL)
          vexs[p2].firstedge = edge2;
        else
            linkList(vexs[p2].firstedge, edge2);
    }

}

void graph::print()
{
    int i,j;
    edge *node;

    cout << "List Graph:" << endl;
    for (i = 0; i < vexnum; i++)
    {
        cout << i << "(" << vexs[i].data << "): ";
        node  =  vexs[i].firstedge;
        while (node != NULL)
        {
            cout<<node->adjvex<<"-("<<node->weight<<")"<<"(" << vexs[node->adjvex].data<<")\t";
            node = node->nextedge;
        }
        cout << endl;
    }
}
void graph::DFS(graph *G,int vertexnum)			//DFS 
{
								
    edge *p;
    cout<<"visited vertex:"<<G->vexs[vertexnum].data<<endl;
    DFSvisited[vertexnum] = TRUE; 					//標記vexs[i]已訪問
    p  =  G->vexs[vertexnum].firstedge; 			//取vexs[i]邊表的頭指標
    while(p)
	{							//橫向搜尋vexs[i]的鄰接點
      if (!DFSvisited[p->adjvex])			//若vi尚未被訪問
        DFS(G,p->adjvex);				//則以p.adjvex為出發點向縱深搜尋
      p = p->nextedge; 					//找vexs[i]的下一鄰接點
	}
}

void graph::BFS(graph *G,int vertexnum)			// 以vk為起始點 
  {

    int i;								 
    LinkQueue Q;						//建立佇列 
    edge *p;
    InitQueue(&Q);						//佇列初始化
    cout<<"visited vertex:"<<G->vexs[vertexnum].data<<endl;
    BFSvisited[vertexnum]  =  TRUE;
    EnQueue(&Q,vertexnum);						//vexs[k]已訪問,將其序號入隊
    while(!QueueEmpty(Q)){				//隊非空則執行
        i = DeQueue(&Q);					//相當於vexs[i]出隊
        p = G->vexs[i].firstedge; 		//取vi的邊表頭指標
        while(p){						//橫向搜尋vexs[i]的鄰接點
            if(!BFSvisited[p->adjvex])
		     {							//橫向探測 
              cout<<"visited vertex:"<<vexs[p->adjvex].data<<endl; //向右訪問 
              BFSvisited[p->adjvex] = TRUE;
              EnQueue(&Q,p->adjvex);							//訪問過的邊序號入隊
             }//if
            p = p->nextedge;										//下一條邊 
         }//while
      }//while
   }
   
int main(void)
{
    graph *pG = NULL;
    pG = new graph();
    pG->print();
   	cout<<"DFS:"<<endl;	
    pG->DFS(pG,0);
   	cout<<"BFS:"<<endl;
    pG->BFS(pG,0);
    delete pG;
    return 0;
}

咳 本來還想寫個PRIM演算法的

寫了寫發現還有點瑕疵

先發了吧 以後有空來填坑

歡迎指正

相關推薦

資料結構——C++實現鄰接DFSBFS

首先我們要知道鄰接表的基本思想: 鄰接表儲存的基本思想:對於圖的每個頂點vi,將所有鄰接於vi的頂點鏈成一個單鏈表,稱為頂點vertex的邊表(對於有向圖則稱為出邊表),所有邊表的頭指標和儲存頂點資訊的一維陣列構成了頂點表。 在這裡我打算將一個無向圖的鄰接表的建立,以及相

資料結構實現迷宮問題(dfs

給一個n*n的方格,讓你求從左上角到所給一點的任意一條路徑並輸出 該題用到dfs,以下是對dfs的簡要解析  :詳解請參見 傳送門 dfs是一種用於遍歷或搜尋樹或圖的演算法。 沿著樹的深度遍歷樹的節點,儘可能深的搜尋樹的分支。當節點v的所在邊都己被探尋過或者在搜尋時結點不

資料結構佇列實現楊輝三角

/************************************************************** > File Name: PascalTriangle.c > Author: chengfeiyan > Mail:

資料結構筆記C++實現順序棧和鏈式棧

這裡介紹兩種實現棧的方式:“順序棧”和“鏈式棧”,各有各的優缺點。 不管是“順序棧”還是“鏈式棧”,我們可以先定義一個棧的ADT(抽象資料型別),如下面的“stack.h” #ifndef STACK_H #define STACK_H const int

資料結構佇列C語言實現

C語言實現迴圈佇列:實現佇列需要理解先進先出的思想,可以先看一下資料機構的書籍,不做過多累述定義為順序表形式。typedef struct{ Elemtype data[MaxSize]; int front,rear; }Queue;MaxSize表示佇列最大值,其中f

資料結構——圖整理程式碼(鄰接儲存圖)

資料結構圖相關程式碼整理記錄——鄰接表儲存圖 環境CodeBlocks17 執行通過 #include <iostream> #include <stdio.h> #include <stdlib.h> #include <queue> usi

資料結構連結串列實現佇列

#include<stdio.h>#include<malloc.h>#include<stdlib.h>#define OK 1#define ERROR 0typedef struct Node{ int data; struct Node *next;}Node,*L

資料結構學習筆記——C++實現雙向迴圈連結串列模板類(超詳解)

定義了兩個標頭檔案分別放置結點類模板(Node.h)和雙鏈表模板(DoubleLinkList.h), 然後在原始檔的main函式中測試。 Node.h #pragma once # include <iostream> template <class

資料結構模版實現大小堆、實現優先順序佇列,以及堆排序

    一、用模版實現大小堆    如果不用模版的話,寫大小堆,就需要分別實現兩次,但是應用模版的話問題就簡單多了,我們只需要實現兩個仿函式,Greater和Less就行了,仿函式就是用類實現一個()的過載就實現了仿函式。這個看下程式碼就能理解了。再設計引數的時候,需要把模版

【Java資料結構實現字尾表示式求值

今天在學資料結構,自己擼一段用棧來實現字尾表示式求值的程式碼,能改進的地方還有很多,在此先mark一下 package StackPractice; import java.util.Scanner; import java.util.Stack; im

一次一小步C++實現Huffman檔案壓縮

首先介紹下Huffman演算法: 哈夫曼編碼(Huffman Coding)是一種編碼方式,哈夫曼編碼是可變字長編碼(VLC)的一種。Huffman於1952年提出一種編碼方法,該方法完全依據字元出現概率來構造異字頭的平均長 度最短的碼字,有時稱之為最佳編碼,一般就叫作Hu

資料結構棧模板實現(3)

注意:1 注意模板的格式,宣告檔案和實現檔案都放在標頭檔案中,無法實現分離編譯; 2 學會過載運算子和友元函式使用 #ifndef MYSTACK_H #define MYS

C++實現單鏈的建立、逆置和輸出

題目描述:在已知單鏈表頭節點的情況下,設計演算法逆置單鏈表並輸出 方法一:採用首先將頭節點指向空,讓其變為尾節點,然後利用中間節點 p、q 將其後的節點一個接一個改為指向前面的節點 /******

資料結構作業五】以鄰接作儲存結構,廣度遍歷圖的優先搜尋序列

#include <iostream> #define MVNum 100 #define MAXQSIZE 100 using namespace std; typedef char ElemType; typedef int QElemType; typed

資料結構環形佇列實現(1)

注意:判空,判佇列滿, MyQueue.h #ifndef MYQUEUE_H #define MYQUEUE_H /* 環形佇列C++實現 */ class MyQueue{ publ

C#實現 迴圈:空心菱形實心菱形,三角形

三元表示式(三目運算): 語法:x>y?z:k 例如:      int int_num1 = 10;          &nb

資料結構基礎(五)圖以及DFSBFS

概念 定義 圖是一種較線性表和樹更為複雜的資料結構 相較於線性表的一對一(每個結點只有一個前驅後驅)和樹的一對多(層級結構,上層結點可以與多個下層結點相關),圖形結構的元素關係是多對多(即結點之間的關係可以是任意的) 圖可分為有向圖和無向圖 術

資料結構,圖的鄰接矩陣建立,鄰接矩陣鄰接的交換,兩種的輸出,過程C++實現

/* 編寫一個程式algo8-1.cpp,實現不帶權圖和帶權圖的鄰接矩陣與鄰接表的互相 轉換演算法、輸出鄰接矩陣與鄰接表的演算法,並在此基礎上設計一個程式exp8-1.cpp 實現如下功能: 1)建立如圖有向圖G的鄰接矩陣,並輸出; 2)由有向圖G的鄰接矩陣產生鄰接表,並輸

資料結構圖(鄰接實現)(C++)

一、圖的鄰接表實現 1.實現了以頂點順序表、邊連結串列為儲存結構的鄰接表; 2.實現了圖的建立(有向/無向/圖/網)、邊的增刪操作、深度優先遞迴/非遞迴遍歷、廣度優先遍歷的演算法; 3.採用頂點物件列表、邊(弧)物件列表的方式,對圖的建立進行初始化;引用 "ObjArr

資料結構順序實現(C語言)

實現程式碼: #ifndef __LINEARLIST_H__ #define __LINEARLIST_H__ #include <malloc.h> #include <stdi