赞
踩
本文接着《【经典算法实现 30】图的创建 — 十字链表法》,
在它的基础上来实现 深度优先算法 与 广度优先算法。
先上图
A
找到B
,将A
放入栈,此时栈内容为:A
B
找到D
,将B
放入栈,此时栈内容为:BA
D
找到E
,将D
放入栈,此时栈内容为:DBA
E
找到G
,将E
放入栈,此时栈内容为:EDBA
G
找不到其他的节点了,G
不用入栈,此时开始弹出数据。E
,E
也找不到其他的节点了,D
,D
找到F
,将D
再次入栈,此时栈内容为:DBA
F
找到C
,将F 放入栈,此时栈内容为:FDBA
C
发现其他几个节点都已经在栈中,说明都找过了,找不到其他结点,此时开始弹栈F
,找不到其他未走过的节点D
,找不到其他未走过的节点B
,找不到其他未走过的节点A
,找不到其他未走过的节点该次遍历的顺序为: A -> B -> D-> E -> G ->F -> C
//图********************************************************************** // 这部分的代码就是《【经典算法实现 30】图的创建 --- 十字链表法》 ,此处省略 。。。。。。 // 栈代码 *********************************************************************** // 实现一个 10 个元素的循环队列 #define Queue_Size 10 typedef struct List{ pNode * node; struct List *next; struct List *pre; }List; // 定义循环队列的头部和尾部 List * list_head = NULL; List * list_tail = NULL; // 往list后添加新的节点,list为队尾节点 List * Insert_pNode(List *list){ List *p; if(list == NULL){ return NULL; } p = (List *)malloc(sizeof(List)); p->node = NULL; p->next = list->next; p->pre = list->next->pre; list->next->pre = p; list->next = p; return p; } List * New_List_Queue(int size){ List * list; int i; if(size == 0) return NULL; printf("\n%s -- size=%d\n",__func__, size); // 创建头节点,单向循环链表头节点指向自已 list = (List *)malloc(sizeof(List)); list->node = NULL; list->next = list; list->pre = list; list_head = list; //队头指向 list list_tail = list; //队尾指向 list //创建剩余的节点 for(i = 0; i<size-1; i++){ list = Insert_pNode(list); } printf("\n列表创建完毕\n"); //创建完毕,返回list 的头结点,即 list->next,因为list即最后一个节点 return list->next; } void Delete_List_Queue(List *list){ List *p; while(list->next != list){ p = list->next; list->next = p->next; list->next->pre = p->pre; printf("\n释放ListQueue:%p", p); free(p); } printf("\n释放ListQueue:%p\n\n", list); free(list); } //向队尾指针添加 Node节点 void Push_Node(pNode *node){ List *p = NULL; // 如果队列满了,则自动扩充队列 if(list_tail == list_head && list_head->node != NULL){ // 找到list_head 的前一个节点 p = list_head; while(p->next != list_head) p = p->next; // 在队尾插入节点,返回队尾指针 list_tail = Insert_pNode(p); printf("\n队列容量已满,增加一个元素, list_tail=%p, list_head=%p\n", list_tail, list_head); } if(list_tail != NULL){ printf("\n插入元素 %c, list_head(%p), list_tail(%p)",node->data, list_head,list_tail ); list_tail->node = node; list_tail = list_tail->next; } } //队列:从队头取出一个 Node节点,队列无数据时,返回NULL,即先进先出 pNode * Pop_Queue(){ pNode *node; if(list_head != NULL && list_head->node != NULL){ node = list_head->node; list_head->node = NULL; list_head = list_head->next; return node; } return NULL; } //栈: 从队尾取出一个 Node节点,队列无数据时,返回NULL,即先进后出 pNode * Pop_Stack(){ pNode *node; if(list_tail->pre != NULL && list_tail->pre->node != NULL){ node = list_tail->pre->node; list_tail->pre->node = NULL; list_tail = list_tail->pre; return node; } return NULL; }
测试程序
int main() { int i; // 创建边 sNode **s = Create_sNode(); // 创建顶点 pNode *node, **p = Create_pNode(s); // 打印节点及其关系 List *p_list, *list = New_List_Queue(Queue_Size); for(i = 0; i<pNode_Num; i++){ Push_Node(p[i]); } printf("\n\n栈后进先出\n"); for(i = 0; i<pNode_Num; i++){ node = Pop_Stack(); printf("%c -- ", node->data); } printf("\n\n"); return 0; }
运行结果:
New_List_Queue -- size=10
列表创建完毕
插入元素 A, list_head(001F04B0), list_tail(001F04B0)
插入元素 B, list_head(001F04B0), list_tail(001F1030)
插入元素 C, list_head(001F04B0), list_tail(001F1048)
插入元素 D, list_head(001F04B0), list_tail(001F1018)
插入元素 E, list_head(001F04B0), list_tail(001F10A8)
插入元素 F, list_head(001F04B0), list_tail(001F1060)
插入元素 G, list_head(001F04B0), list_tail(001F1168)
栈后进先出
G -- F -- E -- D -- C -- B -- A --
// 深度优先遍历算法 , 栈实现 void DFS(pNode **p) { int i, flag=0; pNode *node; sNode *snode; char find_list[pNode_Num], *f=find_list; // 用于保存遍历的顺序 // 将 p[0] 入栈 Push_Node(p[0]); *f++ = p[0]->data; // 只要栈不为空,循环遍历 while(list_head->node != NULL){ // 从栈取出一个节点,获得该节点的下一个节点字符 node = Pop_Stack(); snode = node->firstOut; // 判断下一个节点 while(snode != NULL){ // 判断该节点是否访问过,即是否在 find_list[] 数组中 for(i = 0, flag=0; i<pNode_Num; i++) if(find_list[i] == snode->headvex) flag = 1; printf("\n下一个节点,%c ,flag=%d", snode->headvex, flag); // 判断下一个节点是否在栈中 if( flag == 0){ // 不在数组中,说明找到了一个新节点 Push_Node(node); // 将当前节点重新入栈 // 找到新字符的节点 for(i = 0; i<pNode_Num; i++){ if(p[i]->data == snode->headvex){ Push_Node(p[i]); // 将新节点入栈 *f++ = p[i]->data; snode = NULL; // 将snode 给Null 退出循环 break; } } }else snode = snode->tlink; // 在数组中,说明该节点访问过了 } } printf("\n\n深度遍历完毕,遍历顺序为: \n"); for(i = 0; i<pNode_Num; i++){ printf("%c -> ", find_list[i]); } }
// 十字链表法实现图的保存 #include <stdio.h> //图********************************************************************** // 边结构体 typedef struct sNode{ char tailvex; // 该边的起点, 如 A->B 这条边,此处保存 A char headvex; // 该边的终点, 如 A->B 这条边,此处保存 B struct sNode *tlink; // 出表指针链表,指同起点所有边的链表,比如 A->B 和 A->C,它们的起点相同都是A struct sNode *hlink; // 入表指针链表,指同终点的所有边的链表,比如 B->D 和 C->D,它们的终点相同都是D }sNode; // 顶点结构体 typedef struct pNode{ char data; // 顶点字符,如 A struct sNode *firstIn; // 入边结构体指针链表, 指向第一条入边的结构体指针 struct sNode *firstOut; // 出边结构体指针链表, 指向第一条出边的结构体指针 }pNode; #define pNode_Num 7 // 7个顶点 #define sNode_Num 9 // 9条边 const char c_char[pNode_Num] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; const char s_char[sNode_Num][2]={ {'A','B'}, {'A','C'}, {'B','D'}, {'B','A'}, {'C','D'}, {'D','E'}, {'D','F'}, {'E','G'}, {'F','C'}}; // 创建边 sNode ** Create_sNode(){ int i; sNode **s; s = (sNode **)malloc(sizeof(sNode *) * sNode_Num); for(i = 0; i<sNode_Num; i++){ s[i] = (sNode *)malloc(sizeof(sNode)); s[i]->tailvex = s_char[i][0]; s[i]->headvex = s_char[i][1]; s[i]->tlink = NULL; s[i]->hlink = NULL; printf("sNode[%d]: \'%c\'->\'%c\' - %p - %p\n",i, s[i]->tailvex, s[i]->headvex, s[i]->tlink, s[i]->hlink); } printf("\n\n"); return s; } // 创建顶点 pNode ** Create_pNode(sNode **s){ int i, j; pNode **p; sNode *s_tmp=NULL; p = (pNode **)malloc(sizeof(pNode *) * pNode_Num); for(i = 0; i<pNode_Num; i++){ p[i] = (pNode *)malloc(sizeof(pNode)); p[i]->data = c_char[i]; p[i]->firstIn = NULL; p[i]->firstOut = NULL; // 找出当前节点所有的出边,以当前节点为起始点 for(j = 0; j<sNode_Num; j++){ if(p[i]->data == s[j]->tailvex) { if(p[i]->firstOut == NULL){ p[i]->firstOut = s[j]; s_tmp = p[i]->firstOut; } else{ s_tmp->tlink = s[j]; } } } // 找出当前节点所有的入边,以当前节点为起始点 for(j = 0; j<sNode_Num; j++){ if(p[i]->data == s[j]->headvex) { if(p[i]->firstIn == NULL){ p[i]->firstIn = s[j]; s_tmp = p[i]->firstIn; } else{ s_tmp->hlink = s[j]; } } } // 打印节点关系 printf("pNode[%d]: \'%c\' - %p - %p\nfirstIn : ",i, p[i]->data, p[i]->firstIn, p[i]->firstOut); s_tmp = p[i]->firstIn; while(s_tmp != NULL){ printf(" --> [\'%c\'->\'%c\']", s_tmp->tailvex, s_tmp->headvex); s_tmp = s_tmp->hlink; } printf("\nfirstOut: "); s_tmp = p[i]->firstOut; while(s_tmp != NULL){ printf(" --> [\'%c\'->\'%c\']", s_tmp->tailvex, s_tmp->headvex); s_tmp = s_tmp->tlink; } printf("\n\n\n"); } printf("\n\n"); return p; } // 栈代码 *********************************************************************** // 实现一个 10 个元素的循环队列 #define Queue_Size 10 typedef struct List{ pNode * node; struct List *next; struct List *pre; }List; // 定义循环队列的头部和尾部 List * list_head = NULL; List * list_tail = NULL; // 往list后添加新的节点,list为队尾节点 List * Insert_pNode(List *list){ List *p; if(list == NULL){ return NULL; } p = (List *)malloc(sizeof(List)); p->node = NULL; p->next = list->next; p->pre = list->next->pre; list->next->pre = p; list->next = p; return p; } List * New_List_Queue(int size){ List * list; int i; if(size == 0) return NULL; printf("\n%s -- size=%d\n",__func__, size); // 创建头节点,单向循环链表头节点指向自已 list = (List *)malloc(sizeof(List)); list->node = NULL; list->next = list; list->pre = list; list_head = list; //队头指向 list list_tail = list; //队尾指向 list //创建剩余的节点 for(i = 0; i<size-1; i++){ list = Insert_pNode(list); } printf("\n列表创建完毕\n"); //创建完毕,返回list 的头结点,即 list->next,因为list即最后一个节点 return list->next; } void Delete_List_Queue(List *list){ List *p; while(list->next != list){ p = list->next; list->next = p->next; list->next->pre = p->pre; printf("\n释放ListQueue:%p", p); free(p); } printf("\n释放ListQueue:%p\n\n", list); free(list); } //向队尾指针添加 Node节点 void Push_Node(pNode *node){ List *p = NULL; // 如果队列满了,则自动扩充队列 if(list_tail == list_head && list_head->node != NULL){ // 找到list_head 的前一个节点 p = list_head; while(p->next != list_head) p = p->next; // 在队尾插入节点,返回队尾指针 list_tail = Insert_pNode(p); printf("\n队列容量已满,增加一个元素, list_tail=%p, list_head=%p\n", list_tail, list_head); } if(list_tail != NULL){ printf("\n插入元素 %c, list_head(%p), list_tail(%p)",node->data, list_head,list_tail ); list_tail->node = node; list_tail = list_tail->next; } } //队列:从队头取出一个 Node节点,队列无数据时,返回NULL,即先进先出 pNode * Pop_Queue(){ pNode *node; if(list_head != NULL && list_head->node != NULL){ node = list_head->node; list_head->node = NULL; list_head = list_head->next; printf("\n弹出元素 %c",node->data); return node; } return NULL; } //栈: 从队尾取出一个 Node节点,队列无数据时,返回NULL,即先进后出 pNode * Pop_Stack(){ pNode *node; if(list_tail->pre != NULL && list_tail->pre->node != NULL){ node = list_tail->pre->node; list_tail->pre->node = NULL; list_tail = list_tail->pre; printf("\n弹出元素 %c",node->data); return node; } return NULL; } // 深度优先遍历算法 , 栈实现 void DFS(pNode **p) { int i, flag=0; pNode *node; sNode *snode; char find_list[pNode_Num], *f=find_list; // 用于保存遍历的顺序 // 将 p[0] 入栈 Push_Node(p[0]); *f++ = p[0]->data; // 只要栈不为空,循环遍历 while(list_head->node != NULL){ // 从栈取出一个节点,获得该节点的下一个节点字符 node = Pop_Stack(); snode = node->firstOut; // 判断下一个节点 while(snode != NULL){ // 判断该节点是否访问过,即是否在 find_list[] 数组中 for(i = 0, flag=0; i<pNode_Num; i++) if(find_list[i] == snode->headvex) flag = 1; printf("\n下一个节点,%c ,flag=%d", snode->headvex, flag); // 判断下一个节点是否在栈中 if( flag == 0){ // 不在数组中,说明找到了一个新节点 Push_Node(node); // 将当前节点重新入栈 // 找到新字符的节点 for(i = 0; i<pNode_Num; i++){ if(p[i]->data == snode->headvex){ Push_Node(p[i]); // 将新节点入栈 *f++ = p[i]->data; snode = NULL; // 将snode 给Null 退出循环 break; } } }else snode = snode->tlink; // 在数组中,说明该节点访问过了 } } printf("\n\n深度遍历完毕,遍历顺序为: \n"); for(i = 0; i<pNode_Num; i++){ printf("%c -> ", find_list[i]); } } int main() { int i; // 创建边 sNode **s = Create_sNode(); // 创建顶点 pNode *node, **p = Create_pNode(s); // 打印节点及其关系 List *p_list, *list = New_List_Queue(Queue_Size); DFS(p); printf("\n\n"); return 0; }
sNode[0]: 'A'->'B' - 00000000 - 00000000 sNode[1]: 'A'->'C' - 00000000 - 00000000 sNode[2]: 'B'->'D' - 00000000 - 00000000 sNode[3]: 'B'->'A' - 00000000 - 00000000 sNode[4]: 'C'->'D' - 00000000 - 00000000 sNode[5]: 'D'->'E' - 00000000 - 00000000 sNode[6]: 'D'->'F' - 00000000 - 00000000 sNode[7]: 'E'->'G' - 00000000 - 00000000 sNode[8]: 'F'->'C' - 00000000 - 00000000 pNode[0]: 'A' - 00660E30 - 00660DE8 firstIn : --> ['B'->'A'] firstOut: --> ['A'->'B'] --> ['A'->'C'] pNode[1]: 'B' - 00660DE8 - 00660E18 firstIn : --> ['A'->'B'] firstOut: --> ['B'->'D'] --> ['B'->'A'] pNode[2]: 'C' - 00660E00 - 00660E48 firstIn : --> ['A'->'C'] --> ['F'->'C'] firstOut: --> ['C'->'D'] pNode[3]: 'D' - 00660E18 - 00660E60 firstIn : --> ['B'->'D'] --> ['C'->'D'] firstOut: --> ['D'->'E'] --> ['D'->'F'] pNode[4]: 'E' - 00660E60 - 00660E90 firstIn : --> ['D'->'E'] firstOut: --> ['E'->'G'] pNode[5]: 'F' - 00660E78 - 00660EA8 firstIn : --> ['D'->'F'] firstOut: --> ['F'->'C'] pNode[6]: 'G' - 00660E90 - 00000000 firstIn : --> ['E'->'G'] firstOut: New_List_Queue -- size=10 New_List_Queue -- size=10 列表创建完毕 插入元素 A, list_head(00B204B0), list_tail(00B204B0) 弹出元素 A 插入元素 A, list_head(00B204B0), list_tail(00B204B0) 插入元素 B, list_head(00B204B0), list_tail(00B20FD0) 弹出元素 B 插入元素 B, list_head(00B204B0), list_tail(00B20FD0) 插入元素 D, list_head(00B204B0), list_tail(00B21120) 弹出元素 D 插入元素 D, list_head(00B204B0), list_tail(00B21120) 插入元素 E, list_head(00B204B0), list_tail(00B21090) 弹出元素 E 插入元素 E, list_head(00B204B0), list_tail(00B21090) 插入元素 G, list_head(00B204B0), list_tail(00B21060) 弹出元素 G 弹出元素 E 弹出元素 D 插入元素 D, list_head(00B204B0), list_tail(00B21120) 插入元素 F, list_head(00B204B0), list_tail(00B21090) 弹出元素 F 插入元素 F, list_head(00B204B0), list_tail(00B21090) 插入元素 C, list_head(00B204B0), list_tail(00B21060) 弹出元素 C 弹出元素 F 弹出元素 D 弹出元素 B 弹出元素 A 深度遍历完毕,遍历顺序为: A -> B -> D -> E -> G -> F -> C -> 请按任意键继续. . .
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。