- 图
- 图的定义
- 图的遍历
- 队列的定义(多个索引)
- 判断队列是否为空
- 入队
- 出队
- 图的结构
- 深度优先遍历
- 广度优先遍历
- 完整代码以及运行结果
- 邻接表以及广度优先遍历
- 定义
- 代码
- 图的初始化
- 队列的初始化
- 判断队列是否为空
- 入队
- 出队
- 邻接表的定义
- 邻接表的创建
- 打印邻接表
- 广度优先遍历
- 完整代码以及运行结果
图是由顶点的有穷非空集合和顶点之间边的集合组成, 通常表示为: G(V,E), 其中,G表示一个图,V是图G中顶点的集合,E是图G中边的集合。
图的遍历 队列的定义(多个索引)注意:线性表可以是空表,树可以是空树,但图不可以是空图。就是说,图中不能一个顶点也没有,图的顶点集V一定非空,但边集E可以为空,此时图中只有顶点而没有边。
// 队列的定义
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;
}
判断队列是否为空
// 判断队列是否为空
bool isQueueEmpty(QueuePtr paraQueuePtr){
if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) {
return true;
}
return false;
}
入队
// 入队
void enqueue(QueuePtr paraQueuePtr, int paraNode){
if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) {
printf("错误,元素%d无法入队. 队列已经满了.rn", paraNode);
return;
}
paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
}
出队
// 出队
int dequeue(QueuePtr paraQueuePtr){
if (isQueueEmpty(paraQueuePtr)) {
printf("错误,队列为空rn");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
return paraQueuePtr->nodes[paraQueuePtr->front];
}
图的结构
// 图的结构
typedef struct Graph{
int** connections;
int numNodes;
} *GraphPtr;
深度优先遍历
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);
}
}
}
}
广度优先遍历
// 广度优先遍历
void widthFirstTranverse(GraphPtr paraGraphPtr, int paraStart){
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;
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);
}
}
}
完整代码以及运行结果
#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; } // 判断队列是否为空 bool isQueueEmpty(QueuePtr paraQueuePtr){ if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) { return true; } return false; } // 入队 void enqueue(QueuePtr paraQueuePtr, int paraNode){ if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) { printf("错误,元素%d无法入队. 队列已经满了.rn", paraNode); return; } paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode; paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE; } // 出队 int dequeue(QueuePtr paraQueuePtr){ if (isQueueEmpty(paraQueuePtr)) { printf("错误,队列为空rn"); return NULL; } paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE; return paraQueuePtr->nodes[paraQueuePtr->front]; } // 图的结构 typedef struct Graph{ int** connections; int numNodes; } *GraphPtr; GraphPtr initGraph(int paraSize, int** paraData) { int i, j; GraphPtr resultPtr = (GraphPtr)malloc(sizeof(Graph)); resultPtr -> numNodes = paraSize; 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]; } } return resultPtr; } void initTranverse(GraphPtr paraGraphPtr) { int i; visitedPtr = (int*) malloc(paraGraphPtr -> numNodes * sizeof(int)); for (i = 0; i < paraGraphPtr -> numNodes; i ++) { visitedPtr[i] = 0; } } 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); } } } } // 广度优先遍历 void widthFirstTranverse(GraphPtr paraGraphPtr, int paraStart){ 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; 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); } } } // 测试函数 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)); } for (i = 0; i < 5; i ++) { for (j = 0; j < 5; j ++) { tempPtr[i][j] = myGraph[i][j]; } } 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); } int main(){ testGraphTranverse(); return 1; }
邻接表,存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。
代码 图的初始化// 图的初始化
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 * 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];
}
}
return resultPtr;
}
队列的初始化
// 队列的初始化
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;
}
判断队列是否为空
// 判断队列是否为空
bool isQueueEmpty(QueuePtr paraQueuePtr){
if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) {
return true;
}
return false;
}
入队
// 入队
void enqueue(QueuePtr paraQueuePtr, int paraNode){
if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) {
printf("错误,元素%d无法入队. 队列已经满了.rn", paraNode);
return;
}
paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode;
paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;
}
出队
// 出队
int dequeue(QueuePtr paraQueuePtr){
if (isQueueEmpty(paraQueuePtr)) {
printf("错误,队列为空rn");
return NULL;
}
paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;
return paraQueuePtr->nodes[paraQueuePtr->front];
}
邻接表的定义
// 邻接表的定义
typedef struct AdjacencyNode {
int column;
AdjacencyNode* next;
}AdjacencyNode, *AdjacentNodePtr;
typedef struct AdjacencyList {
int numNodes;
AdjacencyNode* headers;
}AdjacencyList, *AdjacencyListPtr;
邻接表的创建
// 邻接表的创建
AdjacencyListPtr graphToAdjacentList(GraphPtr paraPtr) {
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));
for (i = 0; i < tempNum; i ++) {
p = &(resultPtr->headers[i]);
p->column = -1;
p->next = NULL;
for (j = 0; j < tempNum; j ++) {
if (paraPtr->connections[i][j] > 0) {
q = (AdjacentNodePtr)malloc(sizeof(struct AdjacencyNode));
q->column = j;
q->next = NULL;
p->next = q;
p = q;
}
}
}
return resultPtr;
}
打印邻接表
// 打印邻接表
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;
}
printf("rn");
}
}
广度优先遍历
// 广度优先遍历
void widthFirstTranverse(AdjacencyListPtr paraListPtr, int paraStart){
printf("width first rn");
int i, j, tempNode;
AdjacentNodePtr p;
i = 0;
visitedPtr = (int*) malloc(paraListPtr->numNodes * sizeof(int));
for (i = 0; i < paraListPtr->numNodes; i ++) {
visitedPtr[i] = 0;
}
QueuePtr tempQueuePtr = initQueue();
printf("%dt", paraStart);
visitedPtr[paraStart] = 1;
enqueue(tempQueuePtr, paraStart);
while (!isQueueEmpty(tempQueuePtr)) {
tempNode = dequeue(tempQueuePtr);
for (p = &(paraListPtr->headers[tempNode]); p != NULL; p = p->next) {
j = p->column;
if (visitedPtr[j])
continue;
printf("%dt", j);
visitedPtr[j] = 1;
enqueue(tempQueuePtr, j);
}
}
printf("rn");
}
完整代码以及运行结果
#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 * 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]; } } return resultPtr; } // 队列的初始化 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; } // 判断队列是否为空 bool isQueueEmpty(QueuePtr paraQueuePtr){ if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear) { return true; } return false; } // 入队 void enqueue(QueuePtr paraQueuePtr, int paraNode){ if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE) { printf("错误,元素%d无法入队. 队列已经满了.rn", paraNode); return; } paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode; paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE; } // 出队 int dequeue(QueuePtr paraQueuePtr){ if (isQueueEmpty(paraQueuePtr)) { printf("错误,队列为空rn"); return NULL; } paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE; return paraQueuePtr->nodes[paraQueuePtr->front]; } // 邻接表的定义 typedef struct AdjacencyNode { int column; AdjacencyNode* next; }AdjacencyNode, *AdjacentNodePtr; typedef struct AdjacencyList { int numNodes; AdjacencyNode* headers; }AdjacencyList, *AdjacencyListPtr; // 邻接表的创建 AdjacencyListPtr graphToAdjacentList(GraphPtr paraPtr) { 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)); for (i = 0; i < tempNum; i ++) { p = &(resultPtr->headers[i]); p->column = -1; p->next = NULL; for (j = 0; j < tempNum; j ++) { if (paraPtr->connections[i][j] > 0) { q = (AdjacentNodePtr)malloc(sizeof(struct AdjacencyNode)); q->column = j; q->next = NULL; p->next = q; p = q; } } } return resultPtr; } // 打印邻接表 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; } printf("rn"); } } // 广度优先遍历 void widthFirstTranverse(AdjacencyListPtr paraListPtr, int paraStart){ printf("width first rn"); int i, j, tempNode; AdjacentNodePtr p; i = 0; visitedPtr = (int*) malloc(paraListPtr->numNodes * sizeof(int)); for (i = 0; i < paraListPtr->numNodes; i ++) { visitedPtr[i] = 0; } QueuePtr tempQueuePtr = initQueue(); printf("%dt", paraStart); visitedPtr[paraStart] = 1; enqueue(tempQueuePtr, paraStart); while (!isQueueEmpty(tempQueuePtr)) { tempNode = dequeue(tempQueuePtr); for (p = &(paraListPtr->headers[tempNode]); p != NULL; p = p->next) { j = p->column; if (visitedPtr[j]) continue; printf("%dt", j); visitedPtr[j] = 1; enqueue(tempQueuePtr, j); } } printf("rn"); } 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)); } for (i = 0; i < 5; i ++) { for (j = 0; j < 5; j ++) { tempPtr[i][j] = myGraph[i][j]; } } printf("Data readyrn"); GraphPtr tempGraphPtr = initGraph(5, tempPtr); AdjacencyListPtr tempListPtr = graphToAdjacentList(tempGraphPtr); printAdjacentList(tempListPtr); widthFirstTranverse(tempListPtr, 4); } int main(){ testGraphTranverse(); return 1; }



