DFS : 栈实现(后进先出: 吃饱了吐的)
操作方法: (来源网络)
- 把起始点放入栈
- 重复 一下步骤
- 访问栈顶元素的点
- 找出该该点没有被访问过的邻接点,将其压栈
- 如果这个点没有尚未遍历的邻接点,将其弹出
说明: 这个示例和上面的操作方法有点不一样 具体实现方式如下:
- 先将初始访问点访问了, 再将他的邻接点全部压栈
- 重复一下步骤:
- 在栈不空的时候: 访问栈顶元素(pop)出来), 将他尚未被访问的邻接点全部压栈 (个人想法,不知道对不对)
在这里插入代码片#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 100
typedef struct List //边表结点
{
struct List* next; // 链域: 指向下一个邻接点
int index; //存储下一个顶点
}List;
typedef struct Index //顶点表
{
int data; //顶点
int move; //遍历时用到的标记
struct List* Node; //边表头指针
}Index;
typedef struct Stack
{
int* base;
int* top;
int stackSize;
}Stack;
Stack* stack;
Index array[4];
List* list;
//函数功能: 填充边表
//入口参数: line 为边连接的顶点
// n 当前顶点下标
//返回值 : 当前顶点的指针域
struct List* Insert(int line, int n)
{
if (array[n].Node == NULL)
{
array[n].Node = (List*)malloc(sizeof(List));
array[n].Node->index = line;
array[n].Node->next = NULL;
}
else
{
List* temp;
temp = (List*)malloc(sizeof(List));
temp->index = line;
temp->next = array[n].Node->next;
array[n].Node->next = temp;
}
return array[n].Node;
}
void drawpic(int a )
{
int line = 0, j = 0, i =0, x = 0;
for (i = 0; i < a; i++)
{
printf("输入V%d顶点的边数\n", i); //由用户输入每一个顶点的边
scanf("%d", &x);
array[i].move = 0; //遍历标记点,先全部设置为0
array[i].data = i; // 顶点域
if (x>0)
{
printf("输入V%d结点连接的其他结点\n", i);
for (j = 0; j < x; j++)
{
scanf("%d", &line); //将邻接表当前顶点的下标放到链表中
//(*node)->next = Insert(line, i); //i是顶点下标
array[i].Node = Insert(line, i);
}
}
}
}
Stack* InitStack(Stack *s)
{
//链式栈的结构: 先是有一个这样的栈,再用栈里的指针指向这样一个整型数组:
s = (Stack*)malloc(sizeof(Stack));
s->top = (int*)malloc(sizeof(int) * MAXSIZE ) ;
s->base = s->top;
s->stackSize = 0;
return s;
}
void pushStack(Stack** s, int x )
{
if ((*s)->stackSize >= MAXSIZE)
return;
*((*s)->top) = x;
((*s)->top )++;
((*s)->stackSize)++;
}
int popStack(Stack** s)
{
if ((*s)->stackSize == 0)
{
return -1 ;
}
(*s)->top--;
(*s)->stackSize--;
int x = *((*s)->top);
return x;
}
//空的返回1 ,不空返回0
int isEmpty(Stack* s)
{
if (s->stackSize == 0)
return 1;
else
{
return 0;
}
}
//参数array: 图的顶点的集合, 每一个顶点都有他的边表:
//参数 arraysize: 就是这个顶点数组的大小, 就是有多少个顶点:
//参数 s 栈
//参数first 从哪个顶点开始遍历:
void DFSTraverse(Index *array , int arraysize ,Stack *s , int first )
{
if (array == NULL)
{
return;
}
int Node = 0;
int* visted = (int*)malloc(sizeof(int) * arraysize); //创建一个数组标记是否被访问的 ;
memset(visted, 0, arraysize); //将这个数组清零
if (first > arraysize-1)
first = 0; //如果想要遍历的顶点根本就不存在: 默认从0开始遍历
//处理遍历的第一个点: 1. 先将第一个标记为1,将他的邻接点压栈
visted[first] = 1;
printf("%d ", array[first].data);
List* p = array[first].Node; //访问他的边表:
while (p!= NULL)
{
//将结点数据压栈
pushStack(&s, p->index);
//标志已经走过了
visted[p->index] = 1;
p = p->next ;
}
//压栈完毕: 在栈不为空的时候 ,都要pop出来
while (isEmpty(s) == 0)
{
Node = popStack(&s);
printf("%d ", Node); //打印顶点
//将顶点的邻接点压栈
List* q = array[Node].Node; //访问边表:
while ( q!= NULL)
{
//要查看这个顶点的邻接表!
if (visted[q->index] != 1)
{//将这个顶点的邻接表塞进来:
pushStack(&s, q->index);
visted[q->index] = 1;
}
q= q->next;
}
}
}
int main()
{
int a = 6, i = 0, x = 0;
drawpic( a );
stack = InitStack(stack);
DFSTraverse(array, a, stack, 5);
}