张小二求职之 深度搜索和先序遍历 (绝非你想象那样简单)

经过一段时间的闭馆修炼,张小二我又学到了不少东西,准备去会一会那个变态的面试官,我的未来他做主。

M:是你小子。

z:心理说,(是你大爷我),脸上满脸堆笑,连声说,是我是我,

M:我们的大门随时向你打开,只要你达到我们的要求,废话少说,我们开始吧;

3z:so eazy,1 。树有边和点组成,是一种特殊的图,每个点只有一个入度,出了root以外,也就是每个点有且只有一个爹,

树是联通的,无欢的,所以一颗n个节点的树有满足以下三点中的两条就行:

1.联通

2.没有环

3 n-1条边

任意连个都能导出第三个.

M:不过,你觉得如何判断一个图是否是一棵树呢?

z:利用上文中的n-1条边,很好查出来

可以判断是否有环?(有向图可以用topsort,无向图用并查集更方面)

可以判断是否联通(随便搜索一次)

M:功力见长啊,那我问你,深度优先搜索会吧?写出代码吧,递归和非递归两种

z:伪代码行吗?

M:你要人看懂就行

z:我怕你看不懂,我写了,你别盯着我啊,我害羞啊。

void dfs(int v)

{

if()

visited[v]=true;

for(int i=0;i<len;i++)

{

if(dfs(neig[v].i==1)&&!visited[i])

{

dfs(i);

}

}

M:你这个代码有问题呢?

z:是的,他没有考虑这个图是多个联通图,写出来很简单。

M:好吧,写个非递归的出来行吗:

z:小意思(此处STL代码可能出错,我对这些不太熟)这个代码和bfs一样,

  void dfs(int *G,int v)

{

stack<int> ;

s.push(v);起始点入队

vistied[v]=true;//该点已经访问

while(!s.IsEmpty())//如果栈不为空

{

int v2=s.top();

  cout<<v2<<endl;//输出栈顶元素

q.pop(); //出栈

//孩子入站

for(所有v邻接点且未访问过)

{

s.push(改点);

 

}

 

 

 

 

}

 

 

 

 

 

 

 

 

}

 

 

 

 

 

M:二叉树有三种遍历方式,哪一种是和深度搜索的思想是一样的?

z:应该是先序遍历

M吐舌鬼脸不赖,写出个先序遍历吧

z:非递归的,还是递归的?

M:小伙子,别急,其实我还没有看你的dfs两个版本,你不说两者思想都一样吗?哪里一样了

z:你看,我写个递归方式

void  preorder(node *root)

{

if(root!=NULL)

{

cout<<root->data<<endl;

preorder(root->left);

preorder(root->right);

 

}

 

 

}

其实,树的先序是深度搜索的特殊形式,这就意味着我们可以直接使用深度优先搜索来找到先序结果,同时,我们从代码层面思考,树是一种特殊的图,树只有一个父亲,因此树不会重复访问,所以去掉visited访问数组,同时以前的for循环取未访问的邻接点,数中只有两个,因此我们完全可以更改为dfs(左),dfs(右边);

M;你领悟的很好啊,非递归呢?非递归的先序写出来,不对,你改一改,

void dfs(node* v)

{

stack<int> ;

s.push(v);起始点入队

 vistied[v]=true;//该点已经访问  visited数组去掉

while(!s.IsEmpty())//如果栈不为空

{

int v2=s.top();

  cout<<v2<<endl;//输出栈顶元素

q.pop(); //出栈

//孩子入站

for(所有v邻接点且未访问过)

{

s.push(改点);

 

}去掉黄色的

改为

if(v->left==NULL) s.push(v->left);

if(v->right==NULL) s.push(v->right);

 

 

 

}

M:你的代码不够精准,但是思想是正确的,深度搜索和回溯的关系知道吗?八皇后能写出来吗,

z:对不起,我现在还不会

M;没关系,你可以回去看看,但是我想告诉你深度搜索是一种具有智能性的算法,他的功能比你想象的多的多,同时你提到拓扑排序,如何用深度搜索实现,深度搜索可以判断是否联通,也可以判断drg是否有环呢。

z:,大哥你好牛逼的

M;心理很得意,但是嘴上说,你一定会超过我的,很年轻

z:最烦的就是这句换,表面谦虚,实际是你现在比我差远了,大

哥后会有期

你可能感兴趣的:(遍历)