图的遍历:从图的某个顶点出发,依次访问图中所有的顶点,每个顶点被访问一次且仅访问一次。
防止多次访问某一个顶点的思路:设置辅助数组visited[n],用来标记每个被访问的顶点,
初始化状态为visited[n]=0;如果顶点被访问到,则修改辅助数组的值 :visited[i]=1
图的遍历:
照搬代码
#include#include #define QUEUE_SIZE 10 int* visitedPtr; typedef struct GraphNodeQueue{ int* nodes; int front; int rear; }GraphNodeQueue, *QueuePtr; QueuePtr initQueue(){ QueuePtr resultQueuePtr = (QueuePtr)malloc(sizeof(struct GraphNodeQueue)); resultQueuePtr->nodes = (int*)malloc(QUEUE_SIZE * sizeof(int)); resultQueuePtr->front = 0; resultQueuePtr->rear = 1; return resultQueuePtr; }//Of initQueue bool isQueueEmpty(QueuePtr paraQueuePtr){ if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) { return true; }//Of if return false; }//Of isQueueEmpty void enqueue(QueuePtr paraQueuePtr, int paraNode){ //printf("front = %d, rear = %d.rn", paraQueuePtr->front, paraQueuePtr->rear); if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) { printf("Error, trying to enqueue %d. queue full.rn", paraNode); return; }//Of if paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode; paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE; //printf("enqueue %d ends.rn", paraNode); }//Of enqueue int dequeue(QueuePtr paraQueuePtr){ if (isQueueEmpty(paraQueuePtr)) { printf("Error, empty queuern"); return NULL; }//Of if paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE; //printf("dequeue %d ends.rn", paraQueuePtr->nodes[paraQueuePtr->front]); return paraQueuePtr->nodes[paraQueuePtr->front]; }//Of dequeue typedef struct Graph{ int** connections; int numNodes; } *GraphPtr; //void deepFirst(GraphPtr paraGraphPtr, int paraNode); GraphPtr initGraph(int paraSize, int** paraData) { int i, j; GraphPtr resultPtr = (GraphPtr)malloc(sizeof(Graph)); resultPtr -> numNodes = paraSize; //resultPtr -> connections = (int**)malloc(paraSize * paraSize * sizeof(int)); resultPtr -> connections = (int**)malloc(paraSize * sizeof(int*)); for (i = 0; i < paraSize; i ++) { resultPtr -> connections[i] = (int*)malloc(paraSize * sizeof(int)); for (j = 0; j < paraSize; j ++) { resultPtr -> connections[i][j] = paraData[i][j]; }//Of for j }//Of for i return resultPtr; }//Of initGraph void initTranverse(GraphPtr paraGraphPtr) { int i; //Initialize data visitedPtr = (int*) malloc(paraGraphPtr -> numNodes * sizeof(int)); for (i = 0; i < paraGraphPtr -> numNodes; i ++) { visitedPtr[i] = 0; }//Of for i }//Of initTranverse void depthFirstTranverse(GraphPtr paraGraphPtr, int paraNode) { int i; visitedPtr[paraNode] = 1; printf("%dt", paraNode); for (i = 0; i < paraGraphPtr -> numNodes; i ++) { if (!visitedPtr[i]){ if (paraGraphPtr -> connections[paraNode][i]) { depthFirstTranverse(paraGraphPtr, i); }//Of if }//Of if }//Of for i }//Of depthFirstTranverse void widthFirstTranverse(GraphPtr paraGraphPtr, int paraStart){ //Use a queue to manage the pointers int i, j, tempNode; i = 0; QueuePtr tempQueuePtr = initQueue(); printf("%dt", paraStart); visitedPtr[paraStart] = 1; enqueue(tempQueuePtr, paraStart); while (!isQueueEmpty(tempQueuePtr)) { tempNode = dequeue(tempQueuePtr); visitedPtr[tempNode] = 1; //For output. i ++; for (j = 0; j < paraGraphPtr->numNodes; j ++) { if (visitedPtr[j]) continue; if (paraGraphPtr->connections[tempNode][j] == 0) continue; printf("%dt", j); visitedPtr[j] = 1; enqueue(tempQueuePtr, j); }//Of for j }//Of while }//Of widthFirstTranverse void testGraphTranverse() { int i, j; int myGraph[5][5] = { {0, 1, 0, 1, 0}, {1, 0, 1, 0, 1}, {0, 1, 0, 1, 1}, {1, 0, 1, 0, 0}, {0, 1, 1, 0, 0}}; int** tempPtr; printf("Preparing datarn"); tempPtr = (int**)malloc(5 * sizeof(int*)); for (i = 0; i < 5; i ++) { tempPtr[i] = (int*)malloc(5 * sizeof(int)); }//Of for i for (i = 0; i < 5; i ++) { for (j = 0; j < 5; j ++) { //printf("i = %d, j = %d, ", i, j); //printf("%drn", tempPtr[i][j]); tempPtr[i][j] = myGraph[i][j]; //printf("i = %d, j = %d, %drn", i, j, tempPtr[i][j]); }//Of for j }//Of for i printf("Data readyrn"); GraphPtr tempGraphPtr = initGraph(5, tempPtr); printf("num nodes = %d rn", tempGraphPtr -> numNodes); printf("Graph initializedrn"); printf("Depth first visit:rn"); initTranverse(tempGraphPtr); depthFirstTranverse(tempGraphPtr, 4); printf("rnWidth first visit:rn"); initTranverse(tempGraphPtr); widthFirstTranverse(tempGraphPtr, 4); }//Of testGraphTranverse int main(){ testGraphTranverse(); return 1; }//Of main
运行截图
邻接矩阵是对存储空间的极大浪费。我们可以考虑对边或弧使用链式存储的方式来避免空间浪费的问题。回忆树结构的孩子表示法,将结点存入数组,并对结点的孩子进行链式存储,不管有多少孩子,也不会存在空间浪费问题。
应用这种思路,我们把这种数组与链表相结合的存储方法称为邻接表
#include#include #define QUEUE_SIZE 10 int* visitedPtr; typedef struct Graph{ int** connections; int numNodes; } *GraphPtr; GraphPtr initGraph(int paraSize, int** paraData) { int i, j; GraphPtr resultPtr = (GraphPtr)malloc(sizeof(struct Graph)); resultPtr -> numNodes = paraSize; //resultPtr -> connections = (int**)malloc(paraSize * paraSize * sizeof(int)); resultPtr -> connections = (int**)malloc(paraSize * sizeof(int*)); for (i = 0; i < paraSize; i ++) { resultPtr -> connections[i] = (int*)malloc(paraSize * sizeof(int)); for (j = 0; j < paraSize; j ++) { resultPtr -> connections[i][j] = paraData[i][j]; }//Of for j }//Of for i return resultPtr; }//Of initGraph typedef struct GraphNodeQueue{ int* nodes; int front; int rear; }GraphNodeQueue, *QueuePtr; QueuePtr initQueue(){ QueuePtr resultQueuePtr = (QueuePtr)malloc(sizeof(struct GraphNodeQueue)); resultQueuePtr->nodes = (int*)malloc(QUEUE_SIZE * sizeof(int)); resultQueuePtr->front = 0; resultQueuePtr->rear = 1; return resultQueuePtr; }//Of initQueue bool isQueueEmpty(QueuePtr paraQueuePtr){ if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) { return true; }//Of if return false; }//Of isQueueEmpty void enqueue(QueuePtr paraQueuePtr, int paraNode){ if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) { printf("Error, trying to enqueue %d. queue full.rn", paraNode); return; }//Of if paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode; paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE; }//Of enqueue int dequeue(QueuePtr paraQueuePtr){ if (isQueueEmpty(paraQueuePtr)) { printf("Error, empty queuern"); return NULL; }//Of if paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE; //printf("dequeue %d ends.rn", paraQueuePtr->nodes[paraQueuePtr->front]); return paraQueuePtr->nodes[paraQueuePtr->front]; }//Of dequeue typedef struct AdjacencyNode { int column; AdjacencyNode* next; }AdjacencyNode, *AdjacentNodePtr; typedef struct AdjacencyList { int numNodes; AdjacencyNode* headers; }AdjacencyList, *AdjacencyListPtr; AdjacencyListPtr graphToAdjacentList(GraphPtr paraPtr) { //Allocate space. int i, j, tempNum; AdjacentNodePtr p, q; tempNum = paraPtr->numNodes; AdjacencyListPtr resultPtr = (AdjacencyListPtr)malloc(sizeof(struct AdjacencyList)); resultPtr->numNodes = tempNum; resultPtr->headers = (AdjacencyNode*)malloc(tempNum * sizeof(struct AdjacencyNode)); //Fill the data. for (i = 0; i < tempNum; i ++) { //Initialize headers. p = &(resultPtr->headers[i]); p->column = -1; p->next = NULL; for (j = 0; j < tempNum; j ++) { if (paraPtr->connections[i][j] > 0) { //Create a new node. q = (AdjacentNodePtr)malloc(sizeof(struct AdjacencyNode)); q->column = j; q->next = NULL; //Link. p->next = q; p = q; }//Of if }//Of for j }//Of for i return resultPtr; }//Of graphToAdjacentList void printAdjacentList(AdjacencyListPtr paraPtr) { int i; AdjacentNodePtr p; int tempNum = paraPtr->numNodes; printf("This is the graph:rn"); for (i = 0; i < tempNum; i ++) { p = paraPtr->headers[i].next; while (p != NULL) { printf("%d, ", p->column); p = p->next; }//Of while printf("rn"); }//Of for i }//Of printAdjacentList void widthFirstTranverse(AdjacencyListPtr paraListPtr, int paraStart){ printf("width first rn"); //Use a queue to manage the pointers int i, j, tempNode; AdjacentNodePtr p; i = 0; //Initialize data visitedPtr = (int*) malloc(paraListPtr->numNodes * sizeof(int)); for (i = 0; i < paraListPtr->numNodes; i ++) { visitedPtr[i] = 0; }//Of for i QueuePtr tempQueuePtr = initQueue(); printf("%dt", paraStart); visitedPtr[paraStart] = 1; enqueue(tempQueuePtr, paraStart); // printf("After enqueuern"); while (!isQueueEmpty(tempQueuePtr)) { // printf("First whilern"); tempNode = dequeue(tempQueuePtr); for (p = &(paraListPtr->headers[tempNode]); p != NULL; p = p->next) { j = p->column; // printf("j = %d rn", j); if (visitedPtr[j]) continue; printf("%dt", j); visitedPtr[j] = 1; enqueue(tempQueuePtr, j); }//Of for }//Of while printf("rn"); }//Of widthFirstTranverse void testGraphTranverse() { int i, j; int myGraph[5][5] = { {0, 1, 0, 1, 0}, {1, 0, 1, 0, 1}, {0, 1, 0, 1, 1}, {1, 0, 1, 0, 0}, {0, 1, 1, 0, 0}}; int** tempPtr; printf("Preparing datarn"); tempPtr = (int**)malloc(5 * sizeof(int*)); for (i = 0; i < 5; i ++) { tempPtr[i] = (int*)malloc(5 * sizeof(int)); }//Of for i for (i = 0; i < 5; i ++) { for (j = 0; j < 5; j ++) { //printf("i = %d, j = %d, ", i, j); //printf("%drn", tempPtr[i][j]); tempPtr[i][j] = myGraph[i][j]; //printf("i = %d, j = %d, %drn", i, j, tempPtr[i][j]); }//Of for j }//Of for i printf("Data readyrn"); GraphPtr tempGraphPtr = initGraph(5, tempPtr); AdjacencyListPtr tempListPtr = graphToAdjacentList(tempGraphPtr); printAdjacentList(tempListPtr); widthFirstTranverse(tempListPtr, 4); }//Of testGraphTranverse int main(){ testGraphTranverse(); return 1; }//Of main
运行截图



