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

来源:互联网 发布:淘宝店铺客服模块代码 编辑:程序博客网 时间:2024/04/29 00:12

       图算是一种较复杂的数据结构了。图由 边的集合与顶点的集合 组成。
关于图有许多种存储方式。在这一篇中,在深度优先搜索(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*intint*);

/*
*    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;
}
*/

原创粉丝点击