* 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