圖的dfs遞迴(非遞迴)遍歷和bfs遍歷(鄰接表)
1.深度優先遍歷是連通圖的一種遍歷策略.其基本思想如下:
設x是當前被訪問的頂點,在對x做過訪問的標記之後,選擇一條從x出發的未檢測過的邊(x,y),若發現頂點y已經訪問過了,則重新選擇另一條從x出發的未檢測過的邊,否則沿邊(x,y)到達未曾訪問過的y,對y訪問並將其標記為已訪問過,然後從y開始搜尋,直到搜尋完從y出發的所有路徑,即訪問完所有從y出發可達的頂點之後,才回溯到頂點x,並且再選擇一條從x出發的未檢測的邊,直到從x出發的所有的邊都已經檢測過為止;
2.廣度優先搜尋:廣度優先搜尋是一種遍歷策略;從一個頂點出發,輻射狀地優先遍歷其周圍較廣的區域,例如,從圖的某個頂點vo出發,並訪問此節點.然後依次訪問v0的各個未曾訪問的鄰接點w1,w2,w3...,然後依次從w1,w2..出發訪問各自未被訪問的鄰接點.重複此步驟,直到所有的頂點都被訪問.
上面是兩種遍歷圖的基本思想,用我寫的程式碼來看具體的過程中:如圖:
如上圖:節點ABCDEFG,我們就給每個頂點依次編號1,2,3,4,5,6;(在這裡,我們就以無向圖來說)
首先,我們輸入節點個數和關係的個數,然後依次ABCDEFG,並用相應的的結構儲存它,然後輸入每個節點之間的關係:AB,AC,AD,DF,DG,BE,EG,FG,CF,BD;用鄰接表儲存它;儲存後的示意圖:
1 A:2,3,4 ; 2 B:1,4,5 ; 3 C:1,6 ; 4 E:2,7; 5 F:3,4,7; 6 G:4,5,6
下面是我實現的圖的建立,dfs遞迴和非遞迴,以及bfs遍歷:
************************************************************************* > File Name: linjiebiao.c > Author:yang > Mail:[email protected] > Created Time: 2015年11月26日 星期四 22時38分28秒 ************************************************************************/ #include<stdio.h> #include<stdlib.h> #define MAXVEX 20 typedef struct Stack { int data; struct Stack *next; }LinkStack; typedef struct Queue { int data; struct Queue *next; }LNode; typedef struct { LNode *front; LNode *rear; }LinkQueue; typedef struct ArcNode { int adjvex; struct ArcNode *next; }ArcNode; typedef struct VertexNode { char vexdata; ArcNode *head; }VertexNode; typedef struct { VertexNode vertex[MAXVEX]; int vexnum; //頂點數 int arcnum; //邊數 }AdjList; /********************************棧的操作******************************************/ LinkStack *Init_LinkStack(LinkStack *T) { T=(LinkStack *)malloc(sizeof(LinkStack)); T->next=NULL; return T; } int IsEmpty_LinkStack(LinkStack *T) { if(T->next!=NULL){ return 0; } return 1; } LinkStack* Push_LinkStack(LinkStack *T,int t) { LinkStack *s=(LinkStack *)malloc(sizeof(LinkStack)); if(s==NULL){ return NULL; } s->data=t; s->next=T->next; T->next=s; } LinkStack *Pop_LinkStack(LinkStack *T,int *t) { LinkStack *p=T->next; if(T->next==NULL){ return NULL; } *t=p->data; T->next=p->next; free(p); } /*************************佇列的操作****************************/ LinkQueue *Init_LinkQueue() { LinkQueue *q=(LinkQueue *)malloc(sizeof(LinkQueue)); LNode *p=(LNode *)malloc(sizeof(LNode)); p->next=NULL; q->front=q->rear=p; return q; } int IsEmpty_LinkQueue(LinkQueue *q) { if(q->front == q->rear){ return 1; } return 0; } void EnterQueue(LinkQueue *q,int t) { LNode *s=(LNode *)malloc(sizeof(LNode)); s->data=t; s->next=NULL; q->rear->next=s; q->rear=s; } int OutQueue(LinkQueue *q,int *t) { LNode *p; if(IsEmpty_LinkQueue(q)){ printf("the Queue is Empty!\n"); return 0; }else{ p=q->front->next; *t=p->data; q->front->next=p->next; free(p); if(q->front->next==NULL){ q->rear=q->front; } return 1; } } VertexNode *Insert(VertexNode *h,ArcNode *p) //此函式的意義是把每個連結串列根據adjvex的按從小到大的順序排列; { ArcNode *pre,*cur,*q; cur=h->head; if(cur == NULL){ p->next=cur; cur->next=p; }else{ pre =h->head; q=h->head->next; while(q){ if(p->adjvex < q->adjvex ){ p->next=q; pre->next=p; break; } pre = q; q=q->next; } if(q == NULL){ //當新的節點比當前連結串列中的所有的adjvex都大時,直接插在連結串列的最後面. p->next==NULL; pre->next = p; } } return h; } AdjList *Created_Graph(AdjList *G) { int i,j,k,n1,n2; ArcNode *s; char vex1,vex2; G=(AdjList *)malloc(sizeof(AdjList)); printf("請輸入頂點的個數和邊數:"); scanf("%d%d",&G->vexnum,&G->arcnum); printf("請輸入頂點:\n"); for(i=1;i<=G->vexnum;i++) { printf("No.%d號頂點的值:",i); scanf(" %c",&G->vertex[i].vexdata); G->vertex[i].head=(ArcNode *)malloc(sizeof(ArcNode)); //為每個頭節點開闢空間;有頭節點的連結串列; G->vertex[i].head->next=NULL; //頭節點指向為空; } printf("請輸入由兩個頂點構成的邊:"); for(k=1;k<=G->arcnum;k++){ scanf(" %c%c",&vex1,&vex2); for(i=1;i<=G->vexnum;i++){ if(G->vertex[i].vexdata == vex1){ n1=i; } if(G->vertex[i].vexdata == vex2){ n2=i; } } s=(ArcNode *)malloc(sizeof(ArcNode)); s->adjvex = n2; Insert(&G->vertex[n1],s); /*如果是有向圖,則下面的語句去掉就行*/ s=(ArcNode *)malloc(sizeof(ArcNode)); s->adjvex = n1; Insert(&G->vertex[n2],s); } return G; } int visited[MAXVEX]={0}; void dfs(AdjList *G,int i) { ArcNode *p; printf("%c ",G->vertex[i].vexdata); visited[i]=1; p=G->vertex[i].head->next; while(p){ if(visited[p->adjvex]==0){ dfs(G,p->adjvex); } p=p->next; } } void trans_dfs(AdjList *G) { int v; for(v=1;v<=G->vexnum;v++){ visited[v]=0; } for(v=1;v<=G->vexnum;v++){ if(visited[v]==0){ dfs(G,v); //當圖只有一個連通分量時,此句只會執行一次; } } } void undfs(AdjList *G,int vo) { LinkStack *T; ArcNode *p; T=Init_LinkStack(T); int visited[MAXVEX]={0},i, t; Push_LinkStack(T,vo); while(!IsEmpty_LinkStack(T)){ Pop_LinkStack(T,&t); if(visited[t]==0){ printf("%c ",G->vertex[t].vexdata); visited[t]=1; } p=G->vertex[t].head->next; while(p){ if(visited[p->adjvex] == 0){ printf("%c ",G->vertex[p->adjvex].vexdata); visited[p->adjvex]=1; Push_LinkStack(T,p->adjvex); p=G->vertex[p->adjvex].head->next; }else{ p=p->next; } } } //for(i=1;i<=G->vexnum;i++){} } void bfs(AdjList *G,int v) { int i,t; ArcNode *p; LinkQueue *S=Init_LinkQueue(); for(i=1;i<=G->vexnum;i++) { visited[i]=0; } visited[v]=1; printf("%c ",G->vertex[v].vexdata); EnterQueue(S,v); while(!IsEmpty_LinkQueue(S)){ OutQueue(S,&t); p=G->vertex[t].head->next; while(p){ if(visited[p->adjvex]==0){ printf("%c ",G->vertex[p->adjvex].vexdata); visited[p->adjvex]=1; EnterQueue(S,p->adjvex); } p=p->next; } } } void print(AdjList *G) { ArcNode *p; int i; for(i=1;i<=G->vexnum;i++){ printf(" %c:",G->vertex[i].vexdata); p=G->vertex[i].head->next; while(p) { printf("%d ",p->adjvex); p=p->next; } printf("\n"); } } int main(int argc,char *argv[]) { AdjList *G; G=Created_Graph(G); print(G); printf("**************dfs遞迴遍歷*****************************\n"); dfs(G,1); printf("\n"); printf("*************dfs遞迴遍歷多個連通分量********************\n"); trans_dfs(G); printf("\n"); printf("*******************dfs非遞迴遍歷*************************\n"); undfs(G,1); printf("\n"); printf("*********************bfs遍歷****************************\n"); bfs(G,1); printf("\n"); return 0; }
相關推薦
圖的dfs遞迴(非遞迴)遍歷和bfs遍歷(鄰接表)
1.深度優先遍歷是連通圖的一種遍歷策略.其基本思想如下: 設x是當前被訪問的頂點,在對x做過訪問的標記之後,選擇一條從x出發的未檢測過的邊(x,y),若發現頂點y已經訪問過了,則重新選擇另一條從x出發的未檢測過的邊,否則沿邊(x,y)到達未曾訪問過的y,對y訪問並將其標
用鄰接表儲存有向圖並實現DFS(遞迴+非遞迴)BFS(非遞迴)兩種遍歷
程式碼如下: #include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> using namespace std; #define MA
利用鄰接矩陣儲存無向圖,並實現BFS(非遞迴) DFS(遞迴+非遞迴)兩種遍歷
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> using namespace std; //------------鄰接矩陣----------- #def
實驗四(建圖,無向圖+鄰接矩陣(BFS,DFS(遞迴+非遞迴)),有向圖+鄰接表(BFS,DFS(遞迴+非遞迴)),拓撲排序)
//Sinhaeng Hhjian #include<bits/stdc++.h> using namespace std; const int N=100; const int MAX=1000; int book[N], cnt; struct node{
圖的BFS演算法和DFS的遞迴非遞迴演算法
#include<iostream> #include<fstream> #include<queue> #include<stack> using namespace std; #define MAX 10 typedef
二叉樹前序、中序、後序(遞迴 / 非遞迴)遍歷
前語 二叉樹的遍歷是指按一定次序訪問二叉樹中的每一個結點,且每個節點僅被訪問一次。 前序遍歷 若二叉樹非空,則進行以下次序的遍歷: 根節點—>根節點的左子樹—>根節點的右子樹 若要遍歷左子樹和右子樹,仍然需要按照以上次序進行,所以前序遍歷也是一個遞
二叉樹的非遞迴遍歷和層次遍歷
資料結構 struct node{ int val; node *lchild,*rchild; }; 先序非遞迴遍歷 1) 訪問結點p,並將結點P入棧; 2) 判
二叉樹的前中後序遍歷(遞迴+非遞迴)
/** * 二叉樹節點類 * @author wj * */ class TreeNode{ int value; TreeNode left_Node; TreeNode right_Node; public TreeNode(int value) { this.value
二叉樹DFS和BFS 遞迴/非遞迴
二叉樹DFS和BFS 遞迴/非遞迴方式 1.DFS DFS, 深度優先遍歷 (1)遞迴形式 public class TreeNode { int val; TreeNode left; TreeNode right; TreeNode(int
樹的廣度優先遍歷和深度優先遍歷(遞迴非遞迴、Java實現)
在程式設計生活中,我們總會遇見樹性結構,這幾天剛好需要對樹形結構操作,就記錄下自己的操作方式以及過程。現在假設有一顆這樣樹,(是不是二叉樹都沒關係,原理都是一樣的) 1.廣度優先遍歷 英文縮寫為BFS即Breadth FirstSearch。其過程檢驗來說是對每一層
二叉樹遍歷(前序)(遞迴+非遞迴)
題目 Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes’ values. For example: Given binary
二叉樹遍歷(中序)(遞迴+非遞迴)
Binary Tree Inorder Traversal(二叉樹中序遍歷) Given a binary tree, return the inorder traversal of its nodes’ values. For example: Given binary tree{
二叉樹的遞迴非遞迴遍歷
二叉樹定義結構: struct BtNode{ int data; BtNode * lchild; BtNode * rchild; }; 二叉樹有三種遍歷,前序遍歷,中序遍歷,後序遍歷 前序遍歷的順序是對每一棵樹(子樹),先訪問根節點,然後訪問左子樹,然後訪問右子樹 中序遍
二叉樹遍歷 遞迴/非遞迴 模板(??)
遞迴版 void First_order_traversal(int i) //先序 { printf("%d\n", key[i]); First_order_traversal(lc[i]);
JAVA 先序、中序、後序、層序,遞迴非遞迴遍歷二叉樹
定義一個二叉樹 package com.niuke.binaryTree; public class binaryTree { int data; binaryTree left; binaryTree right; public binaryTree(int
二叉樹的前中後序遍歷(遞迴&非遞迴)
中序遞迴: class Solution { public: vector<int> res; vector<int> inorderTraversal(Tre
二叉樹的三種非遞迴遍歷和層次遍歷
1 .三種非遞迴遍歷(棧) 所要遍歷的樹是: 先序 + 中序 思路:就拿先序遍歷為例來說吧。 1.訪問根節點,根節點入棧,進入左子樹。 2.訪問左子樹的根節點,根節點入棧,進入下一層左子樹。 3.重複直到當前節點為
二叉樹遞迴非遞迴遍歷,層次遍歷,反轉,輸出路徑等常見操作詳細總結
1.序言 在實際工作中,很多業務場景其實也需要一些比較巧妙的演算法來支撐,並不是業務邏輯就全是複製貼上或者說重複的程式碼寫一百遍。越是隨著演算法研究的深入,越是發現數據結構的重要性。或者說,資料結構中就蘊藏著無數精妙演算法的思想,很多演算法的思想在資料結構中體現得非常突出。而作為一種
二叉樹遍歷演算法(遞迴實現先序中序和後續遍歷)(非遞迴實現中序和先續)
二叉樹遍歷 這兩天抓緊把二叉樹遍歷複習了一遍,遞迴實現還是一如既往地簡潔,迭代版本寫了好久還是隻實現了先序和中序,後續一直沒搞明白,有空了再更新。 遞迴實現 void RecursionBackTree(TreeNode * root) {
遞迴、棧、非遞迴非棧實現二叉樹的遍歷
先序遍歷的三種演算法: //遞迴實現先序遍歷 void preorderTree(binNode<Elem>* root){ if(root==NULL){ return; } else{ cout<<root->getE