数据结构学习_图(1)深度优先搜索、广度优先搜索和最小生成树

       图算是一种较复杂的数据结构了。图由 边的集合与顶点的集合 组成。
关于图有许多种存储方式。在这一篇中,在深度优先搜索(DFS)和广度优先搜索(BFS)算法中,树用邻接表的方式存储。在最小生成树的Prim算法中,树用的时邻接矩阵的方式表示。

下面对Prim算法做一个简单的介绍。

        Prim算法以点集合逐步扩展的方式选择连接它们的最小的边。

先指定一个点加入空集中,然后把连接它的最小边的另一个顶点加入集合中,在重复前一个步骤,逐步扩大直到所有的点都加入到了集合中。

#include  < iostream >
#include 
< queue >
#include 
< string >
using   namespace  std;

////error class
// class BadOccur
// {
// public:    
//     BadOccur(const string szErrorDescription)
//     {
//         m_szErrorDescription = szErrorDescription;
//     }
//     void BadOccurPrint()
//     {
//         cout << m_szErrorDescription << endl;
//     }
// private:
//     string m_szErrorDescription;
// };

// structure of the adjacent vertex nodes
typedef  struct  TAdjVertexNode
{
    
int nAdjVertexNum; //sequence number of the adjacent vertex node
    struct TAdjVertexNode* pNextAdjVertex; //pointer of the next adjacent vertex node
}
TAdjVertexNode;

// structure of the vertex nodes
typedef  struct  TVertexNode
{
    
int nVertexNum; //sequence number of the vertex node
    struct TAdjVertexNode* pFirstAdjVertex; //pointer of the vertex's first adjacent node 
}
TVertexNode;

TVertexNode
*  CreatGraph( int  NodesNum)
{
    TVertexNode
* pVertexArray = new TVertexNode [NodesNum + 1];
    
for (int i = 1; i <= NodesNum; i++)
    
{
        pVertexArray[i].nVertexNum 
= i;
        
int nAmount = 0;
        cout 
<< "Please give the number of adjacent nodes of the " << i << " th node" << endl;
        cin 
>> nAmount;
        
if (0 == nAmount)
        
{
            pVertexArray[i].pFirstAdjVertex 
= NULL;
        }

        
else
        
{
            TAdjVertexNode
* pPreNode = NULL;
            
for (int j = 1; j <= nAmount; j++)
            
{
                TAdjVertexNode
* pNewNode = new TAdjVertexNode;
                cout 
<< "Please enter the sequence number of the node." << endl;
                
int nSequenceNum = 0;
                cin 
>> nSequenceNum;
                pNewNode
->nAdjVertexNum = nSequenceNum;
                
if (1 == j)
                
{
                    pVertexArray[i].pFirstAdjVertex 
= pNewNode;
                }

                
else
                
{
                    pPreNode
->pNextAdjVertex = pNewNode;
                }

                pPreNode 
= pNewNode;
                pNewNode
->pNextAdjVertex = NULL;
            }

        }

    }

    
return pVertexArray;
}

typedef 
void  ( * TraverseMethod) (TVertexNode * int int * );

/*
*    Function Name             :BFS
*    function                           :broad traverse the graph from one vertex
*    detail                               :none
*    author                             :weixiong
*    time                                 :2007-2-1
*    return type                      :void
*   return description  : 
*    function parameters    :TVertexNode* pVertexesArray    the storage array of the graph 
*                                                 int nVertexSequenceNum         sequence number of current vertex
*                                                 int* pVertexesFlagArray        the flag array of all the vertexes
*/

void  BFS(TVertexNode *  pVertexesArray,  int  nVertexSequenceNum,  int *  pVertexesFlagArray)
{
    queue
<int> qAdjacentNodes;
    TAdjVertexNode
* pCurrentNode = NULL;
    
int nCurrentNodeNum = nVertexSequenceNum;
    cout 
<< nCurrentNodeNum << " ";
    pVertexesFlagArray[nCurrentNodeNum] 
= 1;
    
for (pCurrentNode = pVertexesArray[nCurrentNodeNum].pFirstAdjVertex; NULL != pCurrentNode; pCurrentNode = pCurrentNode->pNextAdjVertex)
    
{
        nCurrentNodeNum 
= pCurrentNode->nAdjVertexNum;
        cout 
<< nCurrentNodeNum << " ";
        pVertexesFlagArray[nCurrentNodeNum] 
= 1;
        qAdjacentNodes.push(nCurrentNodeNum);
    }

    
while (!qAdjacentNodes.empty())
    
{
        pCurrentNode 
= pVertexesArray[nCurrentNodeNum].pFirstAdjVertex;
        
if (pCurrentNode)
        
{
            nCurrentNodeNum 
= pCurrentNode->nAdjVertexNum;
        }

        
for (; NULL != pCurrentNode; pCurrentNode = pCurrentNode->pNextAdjVertex)
        
{
            nCurrentNodeNum 
= pCurrentNode->nAdjVertexNum;
            
if (0 == pVertexesFlagArray[nCurrentNodeNum])
            
{
                cout 
<< nCurrentNodeNum << " ";
                pVertexesFlagArray[nCurrentNodeNum] 
= 1;
                qAdjacentNodes.push(nCurrentNodeNum);
            }

        }

        nCurrentNodeNum 
= qAdjacentNodes.front();
        qAdjacentNodes.pop();
    }

}


/*
*    Function Name        :DFS
*    function            :depth traverse the graph from one vertex
*    detail                :none
*    author                :weixiong
*    time                :2007-2-1
*    return type            :void
*   return description  : 
*    function parameters    :TVertexNode* pVertexesArray    the storage array of the graph 
*                         int nVertexSequenceNum         sequence number of current vertex
*                          int* pVertexesFlagArray        the flag array of all the vertexes
*/

void  DFS(TVertexNode *  pVertexesArray,  int  nVertexSequenceNum,  int *  pVertexesFlagArray)
{
    cout 
<< pVertexesArray[nVertexSequenceNum].nVertexNum << " ";
    pVertexesFlagArray[nVertexSequenceNum] 
= 1;
    TAdjVertexNode
* pCurrentVertex = pVertexesArray[nVertexSequenceNum].pFirstAdjVertex;
    
int nCurrentVertexNum = 0;
    
if (NULL != pCurrentVertex)
    
{
        nCurrentVertexNum 
= pCurrentVertex->nAdjVertexNum;
    }

    
for (; NULL != pCurrentVertex; pCurrentVertex = pCurrentVertex->pNextAdjVertex)
    
{
        
if (0 == pVertexesFlagArray[nCurrentVertexNum])
        
{
            DFS(pVertexesArray, nCurrentVertexNum, pVertexesFlagArray);
        }

    }

}


/*
*    Function Name        :DepthFirstTraveralGraph
*    function            :traverse graph using the depth first order
*    detail                :none
*    author                :weixiong
*    time                :2007-2-1
*    return type            :bool
*   return description  : true                                      two matrices has multiplied
*                         false                                     two matrices can't be multiplied
*    function parameters    :int nNodesNum                             number of all the vertexes
*                         int* pVertexesFlagArray                   the flag array of all the vertexes
*                          TVertexNode* pVertexesArray               the storage array of the vertex
*/

void  DepthFirstTraveralGraph( int  nNodesNum,  int *  pVertexesFlagArray, TVertexNode *  pVertexesArray)
{
    
int nVertex = 1;
    TraverseMethod p 
= NULL;
    cout 
<< "Please choose your traversal method: 1. BFS   2. DFS" << endl;
    
int nChoice = 0;
    cin 
>> nChoice;
    
while(nVertex != nNodesNum)
    
{
        
int nCurrentVertex = pVertexesArray[nVertex].nVertexNum;
        
if (0 == pVertexesFlagArray[nVertex])
        
{
            
switch (nChoice)
            
{
            
case 1:
                    BFS(pVertexesArray, nVertex, pVertexesFlagArray);
                    
break;
            
case 2:
                    DFS(pVertexesArray, nVertex, pVertexesFlagArray);
                    
break;
            
default:
                    cout 
<< "Bad choice!" << endl;
            }

        }

        nVertex
++;
    }

}


const   int  MAX  =   100 ; // If it hasn't directly path from Vi to Vj, we denote value(Vi, Vj) = 100 
const   int  VERNUM  =   6 ;
/*    Function Name        :MiniSpanTree_Prim
*    function            :creat the minimal span tree
*    detail                :none
*    author                :weixiong
*    time                :2007-2-1
*    return type            :void
*   return description  : 
*    function parameters    :int ppGraphMatrix[][VERNUM]      the storage of the orginal tree
    *                                                int nVertexNum                               the vertexes number it has
    */
void  MiniSpanTree_Prim( int  ppGraphMatrix[][VERNUM],  int  nVertexNum)
{
    ppGraphMatrix[
0][0= 1;
    
int nRow = 0;//record row of the minimal edge
    int nCol = 0;
    
for (int k = 0; k < nVertexNum - 1; k++)
    
{
        
int nMinEdge = MAX;//record the minimal value
        for (int i = 0; i < nVertexNum; i++)
        
{
            
if (1 == ppGraphMatrix[i][i])
            
{
                
for (int j = 0; j < nVertexNum; j++)
                
{
                    
if ((0 == ppGraphMatrix[j][j]) && (ppGraphMatrix[i][j] < nMinEdge))
                    
{
                        nMinEdge 
= ppGraphMatrix[i][j];
                        nRow 
= i;
                        nCol 
= j;
                    }

                }

            }

        }

        ppGraphMatrix[nCol][nCol] 
= 1;
        
if (nRow > nCol)
            ppGraphMatrix[nRow][nCol] 
= -ppGraphMatrix[nRow][nCol];
        
else
            ppGraphMatrix[nCol][nRow] 
= -ppGraphMatrix[nCol][nRow];
    }

}

void  PrintGraph( int  ppGraphMatrix[][VERNUM])
{     
    
for (int i = 0; i < VERNUM; i++)
        
{
            
for (int j = 0; j < VERNUM; j++)
            
{
                cout 
<< ppGraphMatrix[i][j] << ' ';
            }

            cout 
<< endl;
        }

}
typedef struct TEdge
{
 int nVertexBegin;
 int nVertexEnd;
 int nVertexValue;
 int nFlag;
}TEdge;
/*    Function Name        :MiniSpanTree_Prim
*    function            :creat the minimal span tree
*    detail                :none
*    author                :weixiong
*    time                :2007-2-1
*    return type            :void
*   return description  : 
*    function parameters    :TEdge GraphEdgeArray[],      the storage of the edges of the tree
    *                                                TAdjVertexNode GraphVertexArray[] the storage of the vertexes array
    */
void MiniSpanTree_Kruskal(TEdge GraphEdgeArray[], TAdjVertexNode GraphVertexArray[])
{
 int nChosenEdges = 1;
 while (nChosenEdges < VERNUM)
 {
  int nMin = MAX;
  int nEdge = 0;
  int nEdgeBegin = 0;
  int nEdgeEnd = 0;
  for (int i = 1; i <= EDGENUM; i++) //search the minimal edge from the edges which were not chosen
  {
   if ((0 == GraphEdgeArray[i].nFlag) && (GraphEdgeArray[i].nVertexValue < nMin))
   {
    nMin = GraphEdgeArray[i].nVertexValue;
    nEdge = i;
    nEdgeBegin = GraphEdgeArray[i].nVertexBegin;
    nEdgeEnd = GraphEdgeArray[i].nVertexEnd;
   }
  }
  //add the chosen edge's initial vertex to its terminal vertex's list
  TAdjVertexNode* pCurrentVertex = &GraphVertexArray[nEdgeBegin];
  for (; (pCurrentVertex->pNextAdjVertex != NULL) && (pCurrentVertex->nAdjVertexNum != nEdgeEnd); pCurrentVertex = pCurrentVertex->pNextAdjVertex)
  {}
  if (NULL == pCurrentVertex->pNextAdjVertex)
  {
   TAdjVertexNode* pNewVertex = new TAdjVertexNode;
   pNewVertex->nAdjVertexNum = nEdgeEnd;
   pNewVertex->pNextAdjVertex = NULL;
   pCurrentVertex->pNextAdjVertex = pNewVertex;
  }
  //add the chosen edge's terminal vertex to its initial vertex's list
  pCurrentVertex = &GraphVertexArray[nEdgeEnd];
  for (; (pCurrentVertex->pNextAdjVertex != NULL) && (pCurrentVertex->nAdjVertexNum != nEdgeBegin); pCurrentVertex = pCurrentVertex->pNextAdjVertex)
  {}
  if (NULL == pCurrentVertex->pNextAdjVertex)
  {
   TAdjVertexNode* pNewVertex = new TAdjVertexNode;
   pNewVertex->nAdjVertexNum = nEdgeBegin;
   pNewVertex->pNextAdjVertex = NULL;
   pCurrentVertex->pNextAdjVertex = pNewVertex;
   GraphEdgeArray[nEdge].nFlag = 1;
   nChosenEdges++;
  }
 }
}

int  main()
{
    
//MiniSpanTree
    static int ppGraphMatrix[][VERNUM] =
    
{
        
{0  ,6  ,1,5  ,MAX,MAX},
        
{6  ,0  ,5,MAX,3  ,MAX},
        
{1  ,5  ,0,5  ,6  ,4},
        
{5  ,MAX,5,0  ,MAX,2},
        
{MAX,3  ,6,MAX,0  ,6},
        
{MAX,MAX,4,2  ,6  ,0}
    }
;
    MiniSpanTree_Prim(ppGraphMatrix, VERNUM);
    PrintGraph(ppGraphMatrix);
    
//DestroyGraphMatrix(ppGraphMatrix, nVertexNum);//destory the storage matrix
    
//ppGraphMatrix = NULL;
//graph's edges
static TEdge GraphEdgeArray[EDGENUM + 1] =
{
{0, 0, 0, 0},//no use, convenient for count
{1, 2, 6, 0},
{1, 3, 1, 0},
{1, 4, 5, 0},
{2, 3, 5, 0},
{3, 4, 5, 0},
{2, 5, 3, 0},
{3, 5, 6, 0},
{3, 6, 4, 0},
{4, 6, 2, 0},
{5, 6, 6, 0}
};
//graph's vertexes
static TAdjVertexNode GraphVertexArray[VERNUM + 1] =
{
{0, NULL},//no use
{1, NULL},
{2, NULL},
{3, NULL},
{4, NULL},
{5, NULL},
{6, NULL}
};
MiniSpanTree_Kruskal(GraphEdgeArray, GraphVertexArray);
for (int i = 0; i < EDGENUM + 1; i++)
{
if (1 == GraphEdgeArray[i].nFlag)
{
cout << GraphEdgeArray[i].nVertexValue << endl;
}
}
getchar();

    getchar();

    
//BFS and DFS 
    cout << "Please enter the sequence number for all the vertexes in the graph." << endl;
    
int nNodesNum = 0;
    cin 
>> nNodesNum;
    
int *pVertexesFlagArray = new int [nNodesNum + 1];
    
for (int i = 1; i <= nNodesNum; i++)
    
{
        pVertexesFlagArray[i] 
= 0;
    }
    
    TVertexNode
* pGraphStorageArray = CreatGraph(nNodesNum);
    DepthFirstTraveralGraph(nNodesNum, pVertexesFlagArray, pGraphStorageArray);
    getchar();
}

/*
int** CreatGraphMatrix(int nVertexNum)
{
int** ppGraphMatrix = new int* [nVertexNum];
for (int i = 0; i < nVertexNum; i++)
{
ppGraphMatrix[i] = new int [nVertexNum];
for (int j = 0; j < nVertexNum; j++)
{
cin >> ppGraphMatrix[i][j];
}
}
return ppGraphMatrix;
}
void DestroyGraphMatrix(int** ppGraphMatrix, int nVertexNum)
{
for (int i = 0; i < nVertexNum; i++)
{
delete [] ppGraphMatrix[i];
}
ppGraphMatrix = NULL;
}
*/

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值