算法-树的相关算法

原创 2016年08月31日 09:50:12


树是一种递归的数据结构。树的种类从子孩子的数目上可以简单分为二叉树和多叉树。其中二叉树常见的考虑有红黑树和AVL树。另外,多叉树常见的有B树系列、Trie树系列。


有关树的算法可以从最基础的遍历(前中后层)、遍历延伸(公共祖先、对称树)、集合思想(并查集找直系亲属)。

1.遍历

遍历就是按照一定的顺序访问树的节点,由于树是非线性结构,遍历树其实就是将非线性结构转换为线性序列展示。

前、中、后遍历常有的是递归遍历和非递归遍历。

1.1递归访问的模式如下:

<span style="font-size:18px;">void Order(TreeNode *root)
{  
  if(root != NULL) 
{         //preVisit(T);         //前序访问根节点  
        Order(T->lchild);   //访问左子结点  
        //inVisit(T);           //中序访问根节点  
        Order(T->rchild);  //访问右子结点   
        //postVisit(T);        //后序访问根节点  

    }  
} </span>




1.2非递归遍历

非递归算法主要是利用循环+栈数据结构实现的。模式如下

1.2.1先序或中序遍历(非递归)

   思路:访问T->data后,将T入栈,(先序遍历左子树);遍历完左子树返回时,栈顶元素应为T,(中序遍历左子树),出栈,再遍历T的右子树。

<span style="font-size:18px;">void Order2(TreeNode* root)
{
	stack<TreeNode*> stack;
	TreeNode*p = root;//p是遍历指针
	while(p || !stack.empty())//栈不空或者p不空时循环
<span style="white-space:pre">	</span>{
		if(p != NULL)
<span style="white-space:pre">		</span>{
			stack.push(p);//存入栈中	
			//preVisit(p);//前序遍历访问根节点
			p = p->lchild;//遍历左子树
		}
		else
<span style="white-space:pre">		</span>{	
			p = stack.top();//退栈
			//inVisit(p);//中序遍历访问根节点
			stack.pop();
			p = p->rchild;//遍历右子树
		}
<span style="white-space:pre">	</span>}
}</span>



1.2.2后序遍历.

有一篇经典的总结非递归遍历二叉树的方法  http://www.jianshu.com/p/49c8cfd07410

总结出来的模式为

<span style="font-size:18px;">void order(TreeNode *root, vector<int> &path)
{
    stack< pair<TreeNode *, bool> > s;
    s.push(make_pair(root, false));
    bool visited;
    while(!s.empty())
    {
        root = s.top().first;
        visited = s.top().second;
        s.pop();
        if(root == NULL)
            continue;
        if(visited)
        {
            path.push_back(root->val);//访问根节点
        }
        else
        {
            //s.push(make_pair(root, true));//后序遍历,访问根节点<span style="font-family: Arial, Helvetica, sans-serif;">权限开通</span>
            s.push(make_pair(root->right, false));
            //s.push(make_pair(root, true));//中序遍历,访问根节点权限开通
            s.push(make_pair(root->left, false));
            //s.push(make_pair(root, true));//前序遍历,访问根节点权限开通
        }
    }
}</span>


1.2.3层序遍历(队列)

层序遍历相对简单,采用队列思维,每层压队列,直到队列为空即可结束。

</pre><p><span style="font-size:18px;"></span></p><h2><span style="font-size:18px;">1.3公共祖先问题</span></h2><div><span style="font-size:18px;">求解公共祖先问题主要有:<span style="font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25.2px;">在线法和离线法.</span></span><p style="margin: 10px auto; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25.2px;"><span style="font-size:18px;">在线法:指每提出一次请求,便给出一次应答</span></p><p style="margin: 10px auto; font-family: verdana, Arial, Helvetica, sans-serif; line-height: 25.2px;"><span style="font-size:18px;">离线法:收集所有的请求,然后统一进行处理</span></p></div><p><span style="font-size:18px;">1.3.1采用递归方法求公共祖先</span><pre name="code" class="cpp"><span style="font-size:18px;">/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution 
{
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) 
    {
        if(root == NULL || root == p || root == q) return root;

        TreeNode *ltree = lowestCommonAncestor(root->left,p,q);
        TreeNode *rtree = lowestCommonAncestor(root->right,p,q);

        if(ltree && rtree) return root;

        return ltree?ltree:rtree;
    }
  
};</span>

1.3.2Tarjan算法(离线法dfs+并查集)

算法的基本思想为:任选一结点开始进行深度优先搜索dfs(若深度优先搜索结束后仍有未访问的结点,则再从中任选一点再次进行)。搜索过程中已访问的结点不再访问。搜索树的若干子树构成了图的强连通分量。

推荐一篇文章:http://blog.csdn.net/v_july_v/article/details/18312089


1.3.3RMQ算法(在线法dfs+RMQ)

 RMQ,全称为Range Minimum Query,顾名思义,则是区间最值查询,它被用来在数组中查找两个指定索引中最小值的位置。

推荐一篇文章:http://www.cnblogs.com/qianye/archive/2012/12/03/2800384.html

1.4 对称树

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

二叉树相关算法

二叉树Path Sum判断二叉树是否有一条path,路径和等于sum递归遍历二叉树,每到一个节点判断是否是叶子节点,是叶子节点再判断路径和是否和sum相等。路径和由compare函数的result参数...

决策树和相关算法PPT

  • 2010-04-09 17:04
  • 176KB
  • 下载

(二叉树相关算法实现-iOS)

什么是二叉树? 在计算机科学中,二叉树是每个节点最多有两个子树的树结构。通常子树被称作“左子树”和“右子树”,左子树和右子树同时也是二叉树。二叉树的子树有左右之分,并且次序不能任意颠倒。二叉树是递归定...

二叉树及18个相关算法

数据结构-树相关算法

二叉树前序遍历非递归算法:void preOrder(TreeNode* root) { if(root == NULL) { return; } stack ...

二叉树的相关算法(不包含线索二叉树、排序二叉树以及哈弗曼树,后序补上)

#ifndef NEWTREE_H #define NEWTREE_H #include using namespace std; struct TreeNode { char data; Tr...

二叉树的相关算法

/** * 具体实现部分 * @param node */ //输出二叉树的所有叶子节点 public void yezi(Node node) { ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)