树(Tree)
1. 概念
树,顾名思义,长得像一棵树,不过通常我们画成一棵倒过来的树,根在上,叶在下。不说那么多了,图一看就懂:
当然了,引入了树之后,就不得不引入树的一些概念,这些概念我照样尽量用图,谁会记那么多文字?
树这种结构还可以表示成下面这种方式,可见树用来描述包含关系是很不错的,但这种包含关系不得出现交叉重叠区域,否则就不能用树描述了,看图:
面试的时候我们经常被考到的是一种叫“二叉树”的结构,二叉树当然也是树的一种了,它的特点是除了叶以外的节点都有两个子,图:
由此我们还可以推出“三叉树”:
当然还有“四叉树”,“五叉树”,“六叉树”……但太难画了,节点太多,略过。
2、树的遍历(Traversal)
树的遍历是树的一种重要的运算。所谓遍历是指对树中所有结点的系统的访问,即依次对树中每个结点访问一次且仅访问一次。
值得再提一下的是二叉树,因为它确实比较特别,节点有两个子,这两个子是有左右之分的,颠倒一下左右,就是不一样的二叉树了,所以左右是不能随便颠倒的。
算法类型:
(1)广度优先遍历
(2) 深度优先遍历:包括前序遍历、后序遍历
中序遍历只有对二叉树才有意义,下图解释这几种遍历:
它的实际用途比较多,比如说目录的查找就是深度优先遍历。我们使用资源管理器时使用的是广度优先查找。
3.普通树的遍历算法表示
二叉树的遍历可以参考教科书,或者这里 http://blog.csdn.net/msnlxl/article/details/5601079
下面讨论多叉树的遍历
节点表示:
struct Node_t
{
int iver;//节点数据
Node_t * parent;
std::list< Node_t * > childs;
}
1.深度优先算法c++ 使用递归
void tral(Node_t *p)
{
Cout << p->iver << endl;
std::list< Node_t * >iterator it;
for (it = p->childs.begin(); it != p->childs.end(); it++)
Node_t * sp = *it;
tral(sp);
}
2.广度优先算法
void tral(Node_t *pp)
{
std::list< Node_t * > bl;
bl.push_back(pp);
while (!bl.empty())
{
Node_t * sp = bl.front();
cout << sp->iver << endl;
bl.pop_front();
std::list< Node_t * >::iterator it;
for (it = sp->childs.begin(); it != sp->childs.end(); it++)
{
Node_t *p = *it;
bl.push_back(p);
}
}
}