DFS : 栈实现(后进先出: 吃饱了吐的)

操作方法: (来源网络)

  1. 把起始点放入栈
  2. 重复 一下步骤
  1. 访问栈顶元素的点
  2. 找出该该点没有被访问过的邻接点,将其压栈
  3. 如果这个点没有尚未遍历的邻接点,将其弹出

说明: 这个示例和上面的操作方法有点不一样 具体实现方式如下:

  1. 先将初始访问点访问了, 再将他的邻接点全部压栈
  2. 重复一下步骤:
  3. 在栈不空的时候: 访问栈顶元素(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);
}