(第19讲)图

* DFS:深度优先搜索,利用栈 、栈中每个时刻的内容是:从起始点到当前顶点经过的所有顶点。

可以模拟的问题有:迷宫问题。游戏仿真中(三连棋游戏,tic-tac-toe)、决策树

public class DFSApp {

         publicstatic void main(String[] args) {

                   Graphdfsgraph = new Graphdfs();

                   graph.addVer('a');

                   graph.addVer('b');

                   graph.addVer('c');

                   graph.addVer('d');

                   graph.addVer('e');

                   graph.addEdge(0,1);

                   graph.addEdge(1,2);

                   graph.addEdge(0,3);

                   graph.addEdge(3,4);

                   graph.dfs();

                   System.out.println();

         }

}

//深度优先选择需要的栈类

class Stack{

         privateint[] arr;

         inttop = -1;

         privatefinal int NUM = 20;

         publicStack(){

                   arr= new int[NUM];

         }

         //入栈

         publicvoid push(int key){

                   arr[++top]= key;

         }

         //出栈

         publicint pop(){

                   returnarr[top--];

         }

         //访问栈顶

         publicint peek(){

                   returnarr[top];

         }

         //判断栈是否为空

         publicboolean isEmpty(){

                   returntop==-1;

         }

         //遍历栈内元素

         publicvoid display(){

                   for(inti=0;i<NUM;i++){

                            System.out.print(arr[i]+"");

                   }

                   System.out.println();

         }

}

class Vertexdfs{

         publicchar label;

         publicboolean wasvisited;

         publicVertexdfs(char lab){

                   label= lab;

                   wasvisited= false;

         }

}

class Graphdfs{

         privatefinal int NUMS = 20;

         privateVertexdfs[] verarr;

         privateint curnum;

         privateint[][] adjmat;

         privateStack stack;

         publicGraphdfs(){

                   verarr= new Vertexdfs[NUMS];

                   curnum= 0;

                   stack= new Stack();

                 adjmat= new int[NUMS][NUMS];

                   for(inti=0;i<NUMS;i++){

                            for(intj=0;j<NUMS;j++){

                                     adjmat[i][j]= 0;

                            }

                   }

         }

         //添加顶点

         publicvoid addVer(char lab){

                   verarr[curnum++]= new Vertexdfs(lab);

         }

         //添加边

         publicvoid addEdge(int i,int j){

                   adjmat[i][j]= 1;

                   adjmat[j][i]= 1;

         }

         //遍历指定顶点

         publicvoid display(int i){

                   System.out.print(verarr[i].label);

         }

         //深度优先搜索

         publicvoid dfs(){

                   //访问顶点列表中的第一个,即访问第一个顶点,并入栈,将其标志位赋为true

                   verarr[0].wasvisited= true;

                   display(0);

                   stack.push(0);

                   //栈中非空时,取出栈顶,找其邻接点,若无,再从栈中弹出一个;

                   //若有,访问其邻接点,标志位赋为true,并将其入栈

                   while(!stack.isEmpty()){

                            intindex = stack.peek();

                            intadj = getAdjVer(index);

                            if(adj==-1)

                                     stack.pop();

                            else{

                                     display(adj);

                                     verarr[adj].wasvisited= true;

                                     stack.push(adj);

                            }

                   }

                   //重置所有标志位

                   for(inti=0;i<curnum;i++){

                            verarr[i].wasvisited= false;

                   }                

         }

         //找到某顶点邻接的未访问的顶点

         publicint getAdjVer(int v){

                   for(inti=0;i<curnum;i++){

                            if(adjmat[v][i]==1&& verarr[i].wasvisited==false)

                                     returni;

                   }

                   return-1;

         }

}

答案:abcde

 * 广度优先搜索:利用队列。时刻的队列中所包含的顶点都是那些,本身已经被访问过,但他的邻居还没有被访问过的顶点。

可以模拟的:水波纹扩展过程、流感病菌传播的过程、用来查找起始顶点与指定顶点的最短距离

public class BFSApp {

         publicstatic void main(String[] args){

                   Graph2graph = new Graph2();

                   graph.addVer('a');

                   graph.addVer('b');

                   graph.addVer('c');

                   graph.addVer('d');

                   graph.addVer('e');

                   graph.addEdge(0,1);

                   graph.addEdge(1,2);

                   graph.addEdge(0,3);

                   graph.addEdge(3,4);

                   graph.bfs();

                   System.out.println();

         }

}

class Vertexbfs{

         publicchar label;

         publicboolean wasvisited;

         publicVertexbfs(char lab){

                   label= lab;

                   wasvisited= false;

         }

}

class Queue3{

         privatefinal int SIZE = 20;

         privateint[] arr;

         privateint head;

         privateint rear;

         publicQueue3(){

                   arr= new int[SIZE];

                   head= 0;

                   rear= 0;

         }

         //入队

         publicvoid insert(int key)

         {

                   if(!isFull())

                   {

                            arr[rear]= key;

                            rear= (rear+1)%arr.length;

                   }

         }

         //出队

         publicint delete(){

                   intdeletekey = 0;

                   if(!isEmpty()){

                             deletekey = arr[head];

                            head= (head+1)%arr.length;

                   }

                   returndeletekey;

         } 

         //队列是否为空

         publicboolean isEmpty(){

                   returnhead==rear;

         }

         //队列是否为满

         publicboolean isFull(){

                   returnhead==(rear+1)%arr.length;

         }

         //遍历

         publicvoid display(){

                   for(inti=head;i!=rear;i=(i+1)%arr.length){

                            System.out.print(arr[i]+"");

                   }

                   System.out.println();

         }

}

class Graph2{

         privatefinal int SIZE =20;

         privateVertexbfs[] verarr;

         privateint[][] adjmat;

         privateQueue3 queue;

         privateint curnum;

         publicGraph2(){

                   verarr= new Vertexbfs[SIZE];

                   queue= new Queue3();

                  curnum = 0;

                   adjmat= new int[SIZE][SIZE];

                   for(inti=0;i<SIZE;i++){

                            for(intj=0;j<SIZE;j++){

                                     adjmat[i][j]= 0;

                            }

                   }

         }

         //增加顶点

         publicvoid addVer(char key){

                   verarr[curnum++]= new Vertexbfs(key);

         }

         //增加边

         publicvoid addEdge(int i,int j){

                   adjmat[i][j]= 1;

                   adjmat[j][i]= 1;

         }

         //遍历某顶点

         publicvoid display(int i)

         {

                   System.out.print(verarr[i].label+"");

         }

         //BFS

         publicvoid bfs(){

                   verarr[0].wasvisited= true;

                   display(0);

                   queue.insert(0);

                   while(!queue.isEmpty())

                   {

                            intqueuepeek = queue.delete();

                            intadj = 0;                          

                            while((adj=getAdj(queuepeek))!=-1){//当前队首元素有邻接点

                                     verarr[adj].wasvisited= true;

                                     display(adj);

                                     queue.insert(adj);

                            }

                   }

                   for(inti=0;i<curnum;i++){

                            verarr[i].wasvisited= false;

                   }

         }

         //找邻接点

         publicint getAdj(int v){

                   for(inti=0;i<curnum;i++){

                            if(adjmat[v][i]==1&& verarr[i].wasvisited==false)

                                     returni;

                   }

                   return-1;

         }

}

答案:a b d c e

 * 最小生成树:跟深度优先搜索很像,最小生成树的边的数量总是比定点的数量少1

package com.thirteen;

public class MSTApp {

         publicstatic void main(String[] args){

                   Graph3graph = new Graph3();

                   graph.addVer('a');

                   graph.addVer('b');

                   graph.addVer('c');

                   graph.addVer('d');

                   graph.addVer('e');

                   graph.addEdge(0,1);

                   graph.addEdge(0,2);

                   graph.addEdge(0,3);

                   graph.addEdge(0,4);

                   graph.addEdge(1,2);

                   graph.addEdge(1,3);

                   graph.addEdge(1,4);

                   graph.addEdge(2,3);

                   graph.addEdge(2,4);

                   graph.addEdge(3,4);

                   graph.mst();

                   System.out.println();

         }

}

class Vertex3{

         publicchar label;

         publicboolean wasvisited;

         publicVertex3(char lab){

                   label= lab;

                   wasvisited= false;

         }

}

class Stack3{

         privateint[] arr;

         privatefinal int SIZE = 20;

         privateint top;

         publicStack3(){

                   arr= new int[SIZE];

                   top= -1;

         }

         publicvoid push(int key){

                   arr[++top]= key;

         }

         publicint pop(){

                   returnarr[top--];

         }

         publicint peek(){

                   returnarr[top];

         }

         publicboolean isEmpty(){

                   returntop==-1;

         }

}

class Graph3{

         privatefinal int SIZE = 20;

         privateVertex3[] verarr;

         privateint curnum;

         privateStack3 stack;

         privateint[][] adjmat;

         publicGraph3(){

                   verarr= new Vertex3[SIZE];

                   curnum= 0;

                   stack= new Stack3();

                   adjmat= new int[SIZE][SIZE];

                   for(inti=0;i<SIZE;i++){

                            for(intj=0;j<SIZE;j++){

                                     adjmat[i][j]= 0;

                            }

                   }

         }

         //加顶点

         publicvoid addVer(char key){

                   verarr[curnum++]= new Vertex3(key);

         }

         //加边

         publicvoid addEdge(int i,int j){

                   adjmat[i][j]= 1;

                   adjmat[j][i]= 1;

         }

         //遍历节点

         publicvoid display(int v){

                   System.out.print(verarr[v].label);

         }

         //mst

         publicvoid mst(){

                   verarr[0].wasvisited=true;

                   stack.push(0);

                   while(!stack.isEmpty())

                   {

                            intcurver = stack.peek();

                            intv = getAdj(curver);

                            if(v==-1)

                                     stack.pop();

                            else{

                                     verarr[v].wasvisited= true;

                                     stack.push(v);

                                     display(curver);

                                     display(v);

                                     System.out.print("");

                            }

                   }

                   for(inti=0;i<curnum;i++){

                            verarr[i].wasvisited= false;

                   }

         }

         //获得邻接点

         publicint getAdj(int v)

         {

                   for(inti=0;i<curnum;i++){

                            if(adjmat[v][i]==1&& verarr[i].wasvisited==false)

                                     returni;

                   }

                   return-1;

         }

}

答案:ab bc cd de

 * 有向无环图的拓扑排序 :必须在有向无环图中,DAG,不含环的图叫做树

public class TOPOApp {

         publicstatic void main(String[] arg){

                   Graph4graph = new Graph4();

                   graph.addVer('a');

                   graph.addVer('b');

                   graph.addVer('c');

                   graph.addVer('d');

                   graph.addVer('e');

                   graph.addVer('f');

                   graph.addVer('g');

                   graph.addVer('h');

                   graph.addEdge(0,3);

                   graph.addEdge(0,4);

                   graph.addEdge(1,4);

                   graph.addEdge(2,5);

                   graph.addEdge(3,6);

                   graph.addEdge(4,6);

                   graph.addEdge(5,7);

                   graph.addEdge(6,7);

                   graph.topo();

                            }

}

class Vertex4{

         publicchar label;

         publicVertex4(char lab){

                   label= lab;

         }

}

class Graph4{

         privatefinal int SIZE = 20;

         privateVertex4[] verarr;

         privateint curlen;

         privateint[][] adjmat;

         privatechar sortedArr[];

         publicGraph4(){

                   verarr= new Vertex4[SIZE];

                   curlen= 0;

                   adjmat= new int[SIZE][SIZE];

                   for(inti=0;i<SIZE;i++){

                            for(intj=0;j<SIZE;j++)

                                     adjmat[i][j]= 0;

                   }

                   sortedArr= new char[SIZE];

         }

         //增加顶点

         publicvoid addVer(char lab){

                   verarr[curlen++]= new Vertex4(lab);

         }

         //增加边:有向图添加边的时候只用加一个

         publicvoid addEdge(int i,int j){

                   adjmat[i][j]= 1;

         }

         //遍历某个顶点

         publicvoid display(int v){

                   System.out.print(verarr[v].label);

         }

         //拓扑排序

         publicvoid topo(){

                   intcur = curlen;

                   while(curlen>0){

                            intcurver = noSuccessor();

                            if(curver==-1){//若图中全是有后继的顶点,那么必含有环

                                     System.out.println("Error:此图中含有环");

                                     return;

                            }

         //找到无后继的顶点,把这个顶点放到排序数组的最后一个,然后图中删除这个顶点

                            sortedArr[curlen-1]= verarr[curver].label;

                            deletever(curver);

                   }

                   System.out.println("拓扑排序为:");

                   for(inti=0;i<cur;i++)

                            System.out.print(sortedArr[i]+"");

                   System.out.println();

         }

         //查找无后续的顶点

         publicint noSuccessor(){

                   booleanisEdge;

                   for(introw=0;row<curlen;row++){//行

                            isEdge= false;

                            for(intcol=0;col<curlen;col++)

                            {

                                     if(adjmat[row][col]>0)//这一行的邻接矩阵中有1,则row这个顶点有后继

                                     {

                                               isEdge= true;

                                               break;

                                     }

                            }

                            if(!isEdge)//这一行没有1,返回row这个顶点下标

                                     returnrow;

                   }

                   return-1;//全是有后继的顶点,即有环

         }

         //删除顶点

         publicvoid deletever(int index){

                   if(index!=curlen-1){//如果不是最后一个顶点

                            for(inti=index;i<curlen-1;i++){//删除这个顶点,就是顶点数组中后边的补上

                                     verarr[i]= verarr[i+1];

                            }

                            //将邻接矩阵中有关这个顶点的也删除

                            for(introw=index;row<curlen-1;row++)

                                     moveRowUp(row,curlen);

                            for(intcol=index;col<curlen-1;col++)

                                     moveColLeft(col,curlen-1);

                    }

                   curlen--;

         }

         //下边的行移上来

         publicvoid moveRowUp(int row,int curlen){

                   for(intcol=0;col<curlen;col++){

                            adjmat[row][col]= adjmat[row+1][col];

                   }

         }

         //右边的列移过来

         publicvoid moveColLeft(int col,int curlen){

                   for(introw=0;row<curlen;row++){

                            adjmat[row][col]= adjmat[row][col+1];

                   }

         }

}答案:

拓扑排序为:

b a e d g c f h

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值