【C++数据结构实验】图论相关内容,链式实现图的存储及基本操作,深度优先和广度优先图的遍历及拓扑排序!

数据结构图存储相关程序

前面部分为实验说明部分,最终代码查看文末即可!

**任务一:**基于邻接表存储结构实现有向图的典型操作(构造、析构、增加顶点、删除顶点、增加弧、删除弧,查找一个顶点、判空、判满、图中顶点个数、邻接表中指定顶点的第一个邻接顶点、深度优先遍历、广度优先遍历),测试和调试程序。
邻接表示意图如下所示:
图示
根据以上的示意图,声明本实验所用到的图类Graph,请仔细阅读下面所给的graph.h 文件,按照注释分析各个方法的作用。
自己编写graph.cpp 文件,实现Graph 类中各个方法(构造、析构、增加顶点、删除顶点、增加弧、删除弧,查找一个顶点、判空、判满、图中顶点个数、邻接表中指定顶点的第一个邻接顶点、深度优先遍历、广度优先遍历)。

---------------------
graph.h 文件
--------------------
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
/* This header file contains the declarations and prototype functions for the graph ADT
class. It also contains a debugging function to print a vertex.
*/
#define DEBUG 1 //On includes printVertex
template <class TYPE> struct Vertex;//存储每个顶点的信息
template <class TYPE> struct Arc;//先简单声明,存储弧的信息
template <class TYPE> struct Vertex //存图中各顶点
{
Vertex<TYPE> *pNextVertex;//指向下一个头顶点
TYPE data;//顶点有效信息
int inDegree;//入度
int outDegree;//出度
short processed;//标识该顶点被处理的程度或状态
Arc<TYPE> *pArc; //指向第一条弧,这里用到了Arc,所以在前面要先简单声明下
}; // Vertex
template <class TYPE> struct Arc //存图中各弧
{
Vertex<TYPE> *destination;//注意这里是指针,指向弧头顶点
Arc<TYPE> *pNextArc;//指向下一条弧
}; // Arc
template <class TYPE, class KTYPE> //KTYPE 表示各顶点中关键字的类型(关键字用于查询)
class Graph
{
private:
int count;
Vertex<TYPE> *first;
public:
Graph(void);
~Graph(void);
int insertVertex(TYPE dataIn);//插入顶点,数据域为dataIn
int deleteVertex(KTYPE dltKey);//删除顶点,其数据域中关键字为dltKey
int insertArc(KTYPE fromKey, KTYPE toKey);//插入弧,该弧从fromKey 指向toKey
int deleteArc(KTYPE fromKey, KTYPE toKey);//删除弧,该弧从fromKey 指向toKey
int retrieveVertex (KTYPE key, TYPE& DataOut);//查关键字为key 的顶点,数据存入DataOut
int firstArc(KTYPE key, TYPE& DataOut);//查关键字为key 的顶点所指的首弧,数据存DataOut
bool emptyGraph(void);//叛图是否为空
bool graphFull(void);//叛图是否为满
int graphCount(void); //返回图顶点个数
void depthFirst (void (*process)(TYPE dataProc));//深度优先遍历
void breadthFirst (void (*process)(TYPE dataProc));/广度优先遍历
#ifdef DEBUG
// The following function is used only for debugging
void printVertex (KTYPE key);//该方法仅在调试时使用,输出该顶点关键字
#endif
}; // Graph
#endif // GRAPH_H_INCLUDED

完成上述程序后,可以执行下面的测试程序,检验自己的图类Graph 是否运行正常。

/* This program tests the graph ADT */
#include <iostream.h>
#include <iomanip.h>
#include <ctype.h>
#include <stdlib.h>
#include <limits.h>
struct DATA
{
int key;
} ;
#include "graph.h"
//Prototype Functions
void doInsertVertex(Graph<DATA, int>& graph);
void doInsertArc(Graph<DATA, int>& graph);
void doDeleteVertex(Graph<DATA, int>& graph);
void doDeleteArc(Graph<DATA, int>& graph);
void search(Graph<DATA, int>& graph);
void doRetrieveVertex(Graph<DATA, int>& graph);
void doFirstArc(Graph<DATA, int>& graph);
void testUtilties(Graph<DATA, int>& graph);
void buildAGraph(Graph<DATA, int>& graph);
char doMenu(void);
void process(DATA data);
int main (void)
{ // Local Declarations
char option;
int key;
DATA datum;
Graph<DATA, int> graph;
// Statements
cout << "Start Explore Graphs\n";
while ((option = doMenu ()) != 'q')
{
switch (option)
{
case 'i' : doInsertVertex(graph); break;
case 'd' : doDeleteVertex(graph); break;
case 'a' : doInsertArc(graph); break;
case 'b' : doDeleteArc(graph); break;
case 'p' : cout << "Enter vertex key: ";
cin >> key;
graph.printVertex(key);
break;
case 'r' : doRetrieveVertex(graph); break;
case 's' : doFirstArc(graph); break;
case 't' : datum.key = INT_MIN;
process (datum);//Set count
cout << "\nBegin depth first traversal\n";
graph.depthFirst (process);
cout << "\nEnd depth first traversal\n";
cout << "\nBegin breadth first traversal\n";
process (datum); //Set count
graph.breadthFirst (process);
cout << "\nEnd breadth first traversal\n";
break;
case 'x' : testUtilties (graph); break;
case '!' : buildAGraph (graph); break;
default : cout << "\a\a\nInvalid option. Please try again.\n";
} // switch
} // while
return 0;
cout << "End Explore Graphs\n";
} // main
/* ============================= doMenu =============================
This function prints a menu and reads the user selection.
Pre Nothing.
Post option returned.
*/
char doMenu(void)
{ // Local Declarations
charoption;
// Statements
cout << "\n============ Menu =============\n" ;
cout << " i : Insert new item \n";
cout << " d : Delete a vertex \n";
cout << " a : Insert an arc \n";
cout << " b : Delete an arc \n";
cout << " p : Print Vertex Adjacency \n";
cout << " r : Retrieve Vertex \n";
cout << " s : Retrieve First Arc \n";
cout << " t : Traverse graph \n";
cout << " x : Test ADT utilities \n";
cout << " q : Quit \n\n";
cout << "=============================== \n";
cout << "Please enter your choice: ";
cin >> option;
option = tolower (option);
return option;
} // doMenu
/* =================== doRetrieveVertex ===================
This function locates a vertex in the graph.
Pre graph exists.
Post vertex retrieved and printed.
*/
void doRetrieveVertex (Graph<DATA, int>& graph)
{ // Local Declarations
int key;
int success;
DATA dataOut;
// Statements
cout << "Please enter key to be found: ";
cin >> key;
success = graph.retrieveVertex (key, dataOut);
if (success == 1)
cout << "\nKey found. Contains " << dataOut.key << endl;
else
cout << "\n\aKey " << key << " not found\n";
return;
} // doRetrieveVertex
/* =================== doFirstArc ===================
This function locates the first arc of a vertex.
Pre graph exists.
Post vertex first arc retrieved and printed.
*/
void doFirstArc(Graph<DATA, int>& graph)
{ // Local Declarations
int key;
int success;
DATA dataOut;
// Statements
cout << "Please enter key of first arc: ";
cin >> key;
success = graph.firstArc ( key, dataOut);
if (success == 1)
cout << "\nFirst arc of " << key << " contains " << dataOut.key;
else if (success == -2)
cout << "\n\aVertex Key " << key << " not found\n";
else
cout << key << " has no arcs\n";
return;
} // doFirstArc
/* ===================== doInsertVertex =====================
This function gets input from the user and passes it to
vertex insert vertex function.
Pre graph exists.
Post vertex has been inserted.
*/
void doInsertVertex (Graph<DATA, int>& graph)
{ // Prototype Statements
// Local Declarations
DATA newData;
int success;
// Statements
cout << "\nPlease enter interger to be inserted: ";
cin >> newData.key;
success = graph.insertVertex (newData);
if (success)
cout << newData.key << " inserted\n";
else
cout << newData.key << " NOT inserted\a\n";
return;
} // doInsertVertex
/* ======================= doInsertArc =======================
This function gets input from the user and passes it to
arc insert vertex function.
Pre graph exists.
Post arc has been inserted.
*/
void doInsertArc (Graph<DATA, int>& graph)
{
// Prototype Statements
// Local Declarations
int fromKey;
int toKey;
int success;
// Statements
cout << "\nPlease enter from key: ";
cin >> fromKey;
cout << "\nPlease enter to key: ";
cin >> toKey;
success = graph.insertArc (fromKey, toKey);
switch (success)
{
case 1 : cout << "arc " << fromKey << "-to-" << toKey << " inserted\n";
break;
case -1: cout << "Overflow: arc NOT inserted\a\n";
break;
case -2: cout << "From Key " << fromKey << " Error\a\n";
break;
case -3: cout << "To Key " << toKey << " Error\a\n";
break;
default: cout << "Unknown error " << success << " in doInsertArc\n";
cout << "ABORTING 100\a\a\n";
exit (100);
} // switch
return;
} // doInsertArc
/* ======================= doDeleteArc =======================
This function gets input from the user and passes it to
the delete arc function.
Pre graph exists.
Post arc has been deleted.
*/
void doDeleteArc (Graph<DATA, int>& graph)
{ // Local Declarations
int fromKey;
int toKey;
int success;
// Statements
cout << "\nPlease enter from key: ";
cin >> fromKey;
cout << "\nPlease enter to key: ";
cin >> toKey;
success = graph.deleteArc (fromKey, toKey);
switch (success)
{
case 1 : cout << "arc " << fromKey << "-to-" << toKey << " deleted\n";
break;
case -2: cout << "From Key " << fromKey << " Error\a\n";
break;
case -3: cout << "To Key " << toKey << " Error\a\n";
break;
default: cout << "Unknown error " << success << "in doDeleteArc\n";
cout << "ABORTING 101\a\a\n";
exit (101);
} // switch
return;
} // doDeleteArc
/* ========================== doDeleteVertex ==========================
This function deletes a node from the graph. It asks the user for the
key of the node to be deleted and then removes it from the graph.
Pre graph must be initialized. Null graph is OK.
Post The node is deleted and its space recylced
-or- An error message is printed.
*/
void doDeleteVertex (Graph<DATA, int>& graph)
{ // Prototype Statements
// Local Declarations
int dltKey;
int success;
DATA dltData;
// Statements
cout << "\nPlease enter integer to be deleted: ";
cin >> dltKey;
graph.retrieveVertex( dltKey, dltData);//即将被删的元素读出来到dltDat 中
success = graph.deleteVertex ( dltKey);//真正删除被删的元素
switch (success)
{
case 1 : cout << dltKey << " deleted\n";
break;
case -1 : cout << dltKey << "'s degree not zero\a\n";
break;
case -2 : cout << dltKey << "'s key not found\a\n";
break;
default : cout << "UNKNOWN ERROR 101 in delete\a\n";
cout << "ABORTING\a";
exit (101);
} // switch
return;
} // doDeleteVertex
/* =================== process ==================
This function "processes" a graph by printing a
sequential number and the vertex data.
Pre dataPtr is pointer to user data structure
Post Data (integer) printed.
*/
void process (DATA data)
{ // Local Declarations
static int count = 1;
// Statements
if (data.key == INT_MIN)
count = 1;
else
cout << "Vertex #" << setw(3) << count++
<< " contains: " << setw(3) << data.key << endl;
return;
} // process
/* =================== testUtilties ==================
This function tests the ADT utilities by calling
each in turn and printing their results.
Pre graph has been created.
Post Results printed.
*/
void testUtilties (Graph<DATA, int>& graph)
{
cout << "Graph contains " << graph.graphCount() << " nodes\n";
if (graph.emptyGraph())
cout << "The graph IS empty\n";
else
cout << "The graph IS NOT empty\n";
if (graph.graphFull())
cout << "The graph IS full\a\n";
else
cout << "The graph IS NOT full\n";
return;
} // testUtilities
/* =================== buildAGraph ==================
This function builds the graph in Figure 12-1(a)
using 1 for A, 2 for B, etc.
Pre graph has been created.
Post graph built.
*/
void buildAGraph (Graph<DATA, int>& graph)
{
// Local Declarations
DATA data;
int i;
int success;
int fromKey;
int toKey;
// Statements
for (i = 1; i <= 6; i++)
{
data.key = i ;
success = graph.insertVertex (data);
if (!success)
cout << "Insert error in buildAGraph\a\a\n", exit(100);
} // for
// Vertices built. Now build arcs
fromKey = 1;
toKey = 2;
success = graph.insertArc (fromKey, toKey);
fromKey = 2;
toKey = 3;
success = graph.insertArc (fromKey, toKey);
fromKey = 3;
toKey = 4;
success = graph.insertArc (fromKey, toKey);
fromKey = 3;
toKey = 5;
success = graph.insertArc (fromKey, toKey);
fromKey = 5;
toKey = 4;
success = graph.insertArc (fromKey, toKey);
fromKey = 5;
toKey = 6;
success = graph.insertArc (fromKey, toKey);
fromKey = 2;
toKey = 5;
success = graph.insertArc (fromKey, toKey);
if (!success)
cout << "Error adding arcs in buildAGraph\a\a\n", exit(100);
return;
} // buildAGraph
// ====================== End of Program ======================

任务二: 用递归方法实现有向图的拓扑排序算法,测试和调试程序。
使用递归机制,实现有向图的拓扑排序算法,以深度优先遍历策略实现有向图的拓扑排序算法。运行测试程序检验功能是否正确。
任务三: 用栈实现有向图的拓扑排序算法,测试和调试程序。
使用栈(可以基于实验一的双端队列)作为存储空间,以深度优先遍历策略实现有向图的拓扑排序算法。运行测试程序检验功能是否正确。
任务四: 用队列实现有向图的拓扑排序算法,测试和调试程序。
使用队列(可以基于实验一的双端队列)作为存储空间,以广度优先遍历策略实现有向图的拓扑排序算法。运行测试程序检验功能是否正确。

Graph.h文件

#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
#define DEBUG 1 //On includes printVertex
#include<iostream>
#include<iomanip>
#include<string>
#include<queue>
#include<stack>
using namespace std;
template <class TYPE> struct Vertex;//存储每个顶点的信息
template <class TYPE> struct Arc;//先简单声明,存储弧的信息
template <class TYPE>
struct Vertex //存图中各顶点
{
	Vertex<TYPE> *pNextVertex;//指向下一个头顶点
	TYPE data;//顶点有效信息
	int inDegree;//入度
	int outDegree;//出度
	short processed;//标识该顶点被处理的程度或状态
	Arc<TYPE> *pArc; //指向第一条弧,这里用到了Arc,所以在前面要先简单声明下
}; // 顶点
template <class TYPE>
struct Arc //存图中各弧
{
	Vertex<TYPE> *destination;//注意这里是指针,指向弧头顶点
	Arc<TYPE> *pNextArc;//指向下一条弧
}; // 弧
template <class TYPE, class KTYPE> //KTYPE 表示各顶点中关键字的类型(关键字用于查询)
class Graph
{
protected:
	int count;
	Vertex<TYPE> *first;
public:
	Graph(void);
	~Graph(void);
	int insertVertex(TYPE dataIn);//插入顶点,数据域为dataIn
	int deleteVertex(KTYPE dltKey);//删除顶点,其数据域中关键字为dltKey
	int insertArc(KTYPE fromKey, KTYPE toKey);//插入弧,该弧从fromKey 指向toKey
	int deleteArc(KTYPE fromKey, KTYPE toKey);//删除弧,该弧从fromKey 指向toKey
	int retrieveVertex(KTYPE key, TYPE& DataOut);//查关键字为key 的顶点,数据存入DataOut
	int firstArc(KTYPE key, TYPE& DataOut);//查关键字为key 的顶点所指的首弧,数据存DataOut
	Vertex<TYPE> * search(KTYPE &key);//查找函数,返回节点指针
	bool emptyGraph(void);//叛图是否为空
	bool graphFull(void);//叛图是否为满
	int graphCount(void); //返回图顶点个数
	void depthFirst(void(*process)(TYPE dataProc));//深度优先遍历
	void breadthFirst(void(*process)(TYPE dataProc)); //广度优先遍历
#ifdef DEBUG
		// The following function is used only for debugging
	void printVertex(KTYPE key);//该方法仅在调试时使用,输出该顶点关键字
};

template <class TYPE, class KTYPE>
inline Graph<typename TYPE, typename KTYPE>::Graph(void) {
	first = NULL;
	count = 0;
}
template <class TYPE, class KTYPE>
inline Graph<TYPE, KTYPE>::~Graph(void) {
	Vertex<TYPE> *temVertex, *deleteVertex = NULL;
	Arc<TYPE> *temArc, *deleteArc = NULL;
	if (first) {
		temVertex = first;
		while (temVertex) {
			temArc = temVertex->pArc;
			while (temArc) {
				deleteArc = temArc;
				temArc = temArc->pNextArc;
				deleteArc->pNextArc = NULL;
				delete deleteArc;
			}
			deleteVertex = temVertex;
			temVertex = temVertex->pNextVertex;
			deleteVertex->pArc = NULL;
			delete deleteVertex;
		}

		count = 0;
	}
}
template <class TYPE, class KTYPE>
//the return value:  1----successful    -4----duplicate
inline int Graph< TYPE, KTYPE>::insertVertex(TYPE dataIn) {
	Vertex<TYPE> *new_one = new Vertex<TYPE>;
	if (new_one == NULL)
		return -1;//表示操作失败
	new_one->data = dataIn;
	new_one->inDegree = 0;
	new_one->outDegree = 0;
	new_one->processed = 0;
	new_one->pNextVertex = NULL;
	new_one->pArc = NULL;
	if (first == NULL) {
		first = new_one;
	}
	else {
		Vertex<TYPE> *copy = first;
		Vertex<TYPE> *pre_copy = first;
		while (copy && copy->data.key < dataIn.key) {
			pre_copy = copy;
			copy = copy->pNextVertex;
		}
		if (copy) {
			if (copy->data.key == dataIn.key) {
				return -4;
			}
			else {
				pre_copy->pNextVertex = new_one;
				new_one->pNextVertex = copy;
			}
		}
		else {
			pre_copy->pNextVertex = new_one;
			new_one->pNextVertex = NULL;
		}
	}
	count++;
	return 1;//表示操作成功
}
template <class TYPE, class KTYPE>
//the return value:  1----successful  -1----degree is not zero   -2----dltkey not found
inline int Graph< TYPE, KTYPE>::deleteVertex(KTYPE dltKey) {
	if (!first)
		return -2;
	Vertex<TYPE> *des = first;
	Vertex<TYPE> *pre_des = NULL;
	Vertex<TYPE> *temple;
	while (des && des->data.key < dltKey) {
		pre_des = des;
		des = des->pNextVertex;
	}
	if (des && des->data.key == dltKey) {
		if (!pre_des && des->inDegree == 0 && des->outDegree == 0) {
			first = first->pNextVertex;
			delete des;
		}
		else if (des->inDegree == 0 && des->outDegree == 0) {
			temple = des->pNextVertex;
			pre_des->pNextVertex = temple;
			des->pNextVertex = NULL;
			delete des;
		}
		else
			return -1;
	}
	else
		return -2;
	return 1;
}
template <class TYPE, class KTYPE>
//the return value:1----successful  -1----overflow    -2----fromKey not exist  -3----toKey not exist
inline int Graph< TYPE, KTYPE>::insertArc(KTYPE fromKey, KTYPE toKey) {
	if (!first)
		return -1;
	Vertex<TYPE> *foundFrom = search(fromKey);
	Vertex<TYPE> *foundTo = search(toKey);
	if (foundFrom && foundTo) {
		Arc<TYPE> *new_arc = new Arc<TYPE>;
		new_arc->destination = foundTo;
		new_arc->pNextArc = NULL;
		if (foundFrom->pArc == NULL) {
			foundFrom->pArc = new_arc;
		}
		else {
			Arc<TYPE> *temple = foundFrom->pArc;
			while (temple->pNextArc != NULL) {
				temple = temple->pNextArc;
			}
			temple->pNextArc = new_arc;
		}
		foundFrom->outDegree++;
		foundTo->inDegree++;
		return 1;
	}
	else {
		if (!foundFrom)
			return -2;
		if (!foundTo)
			return -3;
	}
	return 1;
}
template <class TYPE, class KTYPE>
//the return value:1----successful -2----fromKey not exist  -3----toKey  not exist
inline int Graph< TYPE, KTYPE>::deleteArc(KTYPE fromKey, KTYPE toKey) {
	if (!first)
		return -3;
	Vertex<TYPE> *foundFrom = search(fromKey);
	Vertex<TYPE> *foundTo = search(toKey);
	if (!foundFrom)
		return -2;
	if (!foundTo)
		return -3;
	if (foundFrom && foundTo) {
		Arc<TYPE> *temple = foundFrom->pArc;
		Arc<TYPE> *pre_temple = NULL, *back;
		while (temple && temple->destination->data.key != toKey) {
			pre_temple = temple;
			temple = temple->pNextArc;
		}
		if (temple) {
			if (temple == foundFrom->pArc) {
				foundFrom->pArc = temple->pNextArc;
				temple->pNextArc = NULL;
				delete temple;
			}
			else {
				back = temple->pNextArc;
				pre_temple->pNextArc = back;
				temple->pNextArc = NULL;
				delete temple;
			}
			foundFrom->outDegree--;
			foundTo->inDegree--;
			return 1;
		}
		else {
			return -4;
		}
	}
	return 1;
}
template <class TYPE, class KTYPE>
//the return value:1----successful  -1----emptylist    -2----key not found
inline int Graph< TYPE, KTYPE>::retrieveVertex(KTYPE key, TYPE& DataOut) {
	Vertex<TYPE> *found = search(key);
	if (!first)
		return -1;
	if (found == NULL) {
		return -2;
	}
	else {
		DataOut = found->data;
		return 1;
	}
}
template <class TYPE, class KTYPE>
//the return value:  1----successful  -1----emptylist    -2----key not found   -3----no destination key or arc
inline int Graph< TYPE, KTYPE>::firstArc(KTYPE key, TYPE& DataOut) {
	if (!first)
		return -1;
	Vertex<TYPE> *found = search(key);
	if (!found)
		return -2;
	else {
		if (found->pArc) {
			DataOut = found->pArc->destination->data;
			return 1;
		}
		else {
			return -3;
		}
	}
}
template <class TYPE, class KTYPE>
inline bool Graph< TYPE, KTYPE>::emptyGraph(void) {
	return count == 0;
}
template <class TYPE, class KTYPE>
inline bool Graph< TYPE, KTYPE>::graphFull(void) {
	Vertex<TYPE> *test = new Vertex<TYPE>;
	if (test != NULL) {
		delete test;
		return false;
	}
	return true;
}
template <class TYPE, class KTYPE>
inline int Graph< TYPE, KTYPE>::graphCount(void) {
	return count;
}
template <class TYPE, class KTYPE>
inline void Graph< TYPE, KTYPE>::depthFirst(void(*process)(TYPE dataProc)) {
	stack<Vertex<TYPE>*> stack;
	Vertex<TYPE> *walk;
	Vertex<TYPE> *walkto;
	Vertex<TYPE> *top;
	Arc<TYPE> *arcwalk;
	if (!first)
		return;
	walk = first;
	while (walk) {
		walk->processed = 0;
		walk = walk->pNextVertex;
	}
	walk = first;
	while (walk) {
		if (walk->processed < 2) {
			if (walk->processed < 1) {
				//processed为0,还没有入栈
				int num = stack.size();
				stack.push(walk);
				int num2 = stack.size();
				if (num == num2) {
					cout << "\aStack overflow!" << endl;
					exit(0);
				}
				walk->processed = 1;
			}
		}
		while (!stack.empty()) {
			top = stack.top();
			stack.pop();
			process(top->data);
			top->processed = 2;
			arcwalk = top->pArc;
			while (arcwalk) {
				walkto = arcwalk->destination;
				if (walkto->processed == 0) {
					int num = stack.size(), num1;
					stack.push(walkto);
					num1 = stack.size();
					if (num == num1) {
						cout << "\aStack overflow!" << endl;
						exit(1);
					}
					walkto->processed = 1;
				}
				arcwalk = arcwalk->pNextArc;
			}
		}
		walk = walk->pNextVertex;
	}
	return;
}
template <class TYPE, class KTYPE>
inline void Graph< TYPE, KTYPE>::breadthFirst(void(*process)(TYPE dataProc)) {
	if (!first)
		return;
	queue<Vertex<TYPE>*> q;
	Vertex<TYPE> *current;
	Vertex<TYPE> *currentTo;
	Vertex<TYPE> *front;
	Arc<TYPE> *arcwalk;
	int num, num1;
	current = first;
	while (current) {
		current->processed = 0;
		current = current->pNextVertex;
	}
	current = first;
	while (current) {
		if (current->processed < 2) {
			if (current->processed < 1) {
				num = q.size();
				q.push(current);
				num1 = q.size();
				if (num == num1) {
					cout << "\aQueue overflow!" << endl;
					exit(3);
				}
				current->processed = 1;
			}
		}
		while (!q.empty()) {
			front = q.front();
			q.pop();
			process(front->data);
			front->processed = 2;
			arcwalk = front->pArc;
			while (arcwalk) {
				currentTo = arcwalk->destination;
				if (currentTo->processed == 0) {
					num = q.size();
					q.push(currentTo);
					num1 = q.size();
					if (num == num1) {
						cout << "\aQueue overflow!" << endl;
						exit(4);
					}
					currentTo->processed = 1;
				}
				arcwalk = arcwalk->pNextArc;
			}
		}
		current = current->pNextVertex;
	}
	return;
}
template <class TYPE, class KTYPE>
inline void Graph< TYPE, KTYPE>::printVertex(KTYPE key) {
	if (!first) {
		cout << "\a This graph is empty,and Vertex:" << key << "does not exist!\n";
		return;
	}
	Vertex<TYPE> *found = search(key);
	if (!found) {
		cout << "\a Vertex:" << setw(2) << key << "does not exist!\n";
		return;
	}
	cout << "Adjacency list for " << setw(2) << key;
	cout << "(inDegree: " << setw(2) << found->inDegree << "--outDegree:" << setw(2) << found->outDegree << ")" << endl;
	Arc<TYPE> *temple = found->pArc;
	while (temple) {
		cout << setw(4) << temple->destination->data.key;
		temple = temple->pNextArc;
	}
	return;

}
template <class TYPE, class KTYPE>
inline Vertex<TYPE> * Graph< TYPE, KTYPE>::search(KTYPE &key) {

	if (first == NULL) {
		return NULL;
	}
	Vertex<TYPE> *copy = first;
	while (copy && key > copy->data.key)
		copy = copy->pNextVertex;
	if (copy->data.key == key) {
		return copy;
	}
	return NULL;
}
#endif
#endif

其余三问代码:

部分内容请根据自身需要进行修改(文中已注明)

#include"Graph.h"//请将Graph类中的成员变量权限修饰变成protected
#include<list>
#include<stack>
#include<queue>
#include<stdlib.h>

template<class KTYPE>
struct Data {
	KTYPE key;
};
template<class TYPE,class KTYPE>
class ExtendGraph: public Graph<TYPE,KTYPE>{
public:
	ExtendGraph() {};
	void depth_sort(list<TYPE> &topological_order);
	void breadth_sort(list<TYPE> &topological_order);
	void recursive_depth_order(list<TYPE> &topological_order);
private:
	void recursive_depth_sort(Vertex<TYPE>* v, list<TYPE> &topological_order);
};
template<class TYPE, class KTYPE>
void ExtendGraph<TYPE, KTYPE>::depth_sort(list<TYPE> &topological_order) {
	topological_order.clear();
	stack<Vertex<TYPE>*> process;
	Vertex<TYPE> *current, *top, *des;
	Arc<TYPE> *arccurrent;
	current = this->first;
	while (current) {
		current->processed = current->inDegree;
		if (current->inDegree == 0) {
			process.push(current);
		}
		current = current->pNextVertex;
	}
	while (!process.empty()) {
		top = process.top();
		topological_order.push_back(top->data);
		process.pop();
		arccurrent = top->pArc;
		while (arccurrent) {
			des = arccurrent->destination;
			des->processed--;
			if (des->processed == 0) {
				process.push(des);
			}
			arccurrent = arccurrent->pNextArc;
		}
	}
}
template<class TYPE, class KTYPE>
void ExtendGraph<TYPE, KTYPE>::breadth_sort(list<TYPE> &topological_order) {
	topological_order.clear();
	queue<Vertex<TYPE>*> process;
	Vertex<TYPE> *current,*front,*des;
	Arc<TYPE> *arccurrent;
	current = this->first;
	while (current) {
		if (current->inDegree == 0) {
			process.push(current);
		}
		current->processed = current->inDegree;//将节点的入度存入processed中以便后续操作保证树的结构不便
		current = current->pNextVertex;
	}
	while (!process.empty()) {
		front = process.front();
		topological_order.push_back(front->data);
		arccurrent = front->pArc;
		while (arccurrent) {
			des = arccurrent->destination;
			des->processed--;
			if (des->processed == 0) {
				process.push(des);
			}
			arccurrent = arccurrent->pNextArc;
		}
		process.pop();
	}
}
template<class TYPE, class KTYPE>
void ExtendGraph<TYPE, KTYPE>::recursive_depth_order(list<TYPE> &topological_order) {
	topological_order.clear();
	if (!this->first)
		return;
	Vertex<TYPE> *current;
	current = this->first;
	while (current) {
		current->processed = 0;
		current = current->pNextVertex;
	}
	current = this->first;
	while (current) {
		if (current->processed == 0)
			recursive_depth_sort(current, topological_order);
		current = current->pNextVertex;
	}
}
template<class TYPE, class KTYPE>
void ExtendGraph<TYPE, KTYPE>::recursive_depth_sort(Vertex<TYPE>* v, list<TYPE> &topological_order) {
	v->processed = 1;
	Arc<TYPE> *arcwalk=v->pArc;
	Vertex<TYPE> *currentTo;
	while (arcwalk) {
		currentTo=arcwalk->destination;
		if (currentTo->processed == 0) {
			recursive_depth_sort(currentTo, topological_order);
		}
		arcwalk = arcwalk->pNextArc;
	}
	topological_order.push_front(v->data);
}

template<class TYPE, class KTYPE>
void buildTree(ExtendGraph<TYPE, KTYPE> &graph) {//测试函数,请根据自己需要修改一下哈
	Data<int> dt[10];
	for (int i = 0; i < 10; i++) {
		dt[i].key = i;
	}
	for (int j = 0; j < 10; j++) {
		graph.insertVertex(dt[j]);
	}
	graph.insertArc(0, 1);
	graph.insertArc(0, 5);
	graph.insertArc(1, 7);
	graph.insertArc(3, 2);
	graph.insertArc(3, 4);
	graph.insertArc(3, 7);
	graph.insertArc(3, 8);
	graph.insertArc(4, 8);
	graph.insertArc(6, 0);
	graph.insertArc(6, 1);
	graph.insertArc(6, 2);
	graph.insertArc(8, 2);
	graph.insertArc(8, 7);
	graph.insertArc(9, 4);

}
void print(list<Data<int>> &order) {//测试函数,请根据自己需要修改一下哈
	while (!order.empty()) {
		cout << order.front().key << "   ";
		order.pop_front();
	}
	cout << endl;
}
int main() {//测试函数,请根据自己需要修改一下哈
	ExtendGraph<Data<int>,int> Eg;
	buildTree(Eg);
	list<Data<int>> order;
	Eg.recursive_depth_order(order);
	cout << "递归实现的深度优先排序输出结果:" << endl;
	print(order);
	Eg.depth_sort(order);
	cout << "栈实现的深度优先排序输出结果:" << endl;
	print(order);
	Eg.breadth_sort(order);
	cout << "队列实现的广度优先排序输出结果:" << endl;
	print(order);
	system("pause");
}

java进阶课程分享

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

輕塵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值