先序遍历

二叉树的非递归遍历与层次遍历

孤人 提交于 2020-03-01 13:50:44
二叉树的递归遍历很好写,也很好理解。但因为是递归程序,不可避免地需要调用系统栈,耗时较长,这里我们来探究一下二叉树的非递归遍历的算法。这种方法需要使用栈这种数据结构,这里关于栈的一些操作函数可以看成伪代码吧,先给出线序、中序、后序遍历的代码即说明。 先序遍历: 1 void PreOrderTraverse(BinTree b) 2 { 3 InitStack(S);///初始化创建栈 4 BinTree p=b;///p为工作指针 5 while(p||!isEmpty(s)) 6 { 7 while(p)///到最左下的孩子 8 { 9 printf(" %c ",p->date);///先序先遍历结点 10 Push(S,p);///入栈 11 p=p->lchild; 12 } 13 if(!isEmpty(s))///在栈不为空的情况下,左孩子为空,弹出该结点,遍历右孩子 14 { 15 p=Pop(s); 16 p=p->rchild; 17 } 18 } 19 } 再给出使用数组模拟的函数 1 void Preorder_n(BiTree bt) /*先序遍历的非递归算法*/ 2 { 3 BiTree stack[MAX],p; 4 int top=0,i; 5 for(i=0; i<MAX; i++) 6 { 7 stack[i]=NULL; /*初始化栈*/ 8

问题 D: 二叉树遍历

此生再无相见时 提交于 2020-02-25 22:40:23
题目链接 : http://codeup.cn/problem.php?cid=100000611&pid=3 题目描述 编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。 输入 输入包括1行字符串,长度不超过100。 输出 可能有多组测试数据,对于每组数据, 输出将输入字符串建立二叉树后中序遍历的序列,每个字符后面都有一个空格。 每个输出结果占一行。 样例输入 a#b#cdef##### a## 样例输出 a b f e d c a 代码 # include <cstdio> char pre [ 110 ] ; int i ; struct node { char data ; node * lchild ; node * rchild ; } ; node * create ( ) { if ( pre [ i ] == '#' ) { i ++ ; return NULL ; } node * root = new node ; root -> data = pre [ i ] ; i ++ ; root -> lchild = create ( ) ; root ->

剑指offer-根据前序和中序遍历构建二叉树,年龄排序

夙愿已清 提交于 2020-02-19 11:13:57
根据前序和中序遍历序列构建二叉树 思路: 根据前序序列找到根在中序序列中的位置,从而找到左右子树的中序序列,再根据左右子树的长度,找到它们的前序序列,递归计算。 代码: """ 使用先序遍历和中序遍历的结果重建二叉树 """ from collections import deque class TreeNode(object): """ 二叉树结点定义 """ def __init__(self, x): self.val = x self.left = None self.right = None class Tree(object): """ 二叉树 """ def __init__(self): self.root = None def bfs(self): ret = [] queue = deque([self.root]) while queue: node = queue.popleft() if node: ret.append(node.val) queue.append(node.left) queue.append(node.right) return ret def pre_traversal(self): ret = [] def traversal(head): if not head: return ret.append(head.val)

【数据结构】树

我的未来我决定 提交于 2020-02-16 18:28:58
树 客观世界中许多事物存在层次关系 eg:人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率 查找(Searching):给定某个关键字K,从集合R中找出关键字与K相同的记录 静态查找:集合中记录是固定的 没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的 除查找,还可能发生查找和删除 静态查找 顺序查找 typedef struct LNode *List; struct LNode{ ElementType Element[MAXSIZE]; int Length; } int SequentialSearch(List Tb1, ElementType K){ int i; Tb1->Element[0]=K;//哨兵!这样可以减少判断 for(i=Tb1->Length;Tb1->Element[i]!=K;i--); return i; } 二分查找 Binary Search O(log(n)) 假设n个数据元素的关键字满足有序 \(k_1<k_2<k_3<...<k_n\) ,并且是连续存放(数组),那么可以进行二分查找。 typedef LNode *List; struct LNode{ ElementType Element[MAXSIZE]; int Length; } int BinarySearch(List PtrL

由二叉树的前序遍历字符串得到其中序遍历字符串

删除回忆录丶 提交于 2020-02-14 02:15:11
Case1:满二叉树 题目描述 给出一棵满二叉树的先序遍历,有两种节点:字母节点(A-Z,无重复)和空节点(#)。要求这个树的中序遍历。输出中序遍历时不需要输出#。满二叉树的层数n满足1<=n<=5。 示例1 Sample Input: ABC#D#ESample Output:CBADE Solution: 满二叉树的特征很明显,左右子树结点个数相等,那么以某一个结点为根的子树中,该根节点在先序遍历中排在第一位,其在中序遍历中一定排在最中间的位置上。利用分治的思想,建立一个数组,   根节点插入到数组中间位置,   左子树根节点插入到数组左边的中间位置,   一直这样直至数组左边中间位置已满开始插入到右边数组的中间位置,   依次递归 . . . . . . 以示例为例,遍历前序遍历字符串插入到数组中,最后输出数组中字符串,即为中序遍历字符串。 #include <iostream> #include <string.h> using namespace std; int i; // 全局变量,控制字符串的遍历 string s; void insert(char a[], int left, int right){ // 将字符串各个元素插入数组对应位置 int mid = (left + right) / 2; if(left <= right && a[mid] != s

二叉树相关

安稳与你 提交于 2020-02-12 18:14:42
镜面反转 :是指将所有非叶结点的左右孩子对换。 1.已知先序遍历,中序遍历,求层序遍历 (这道题求层序的镜面反转,所以每一层 从右向左 遍历) #include<iostream> #include<algorithm> #include<queue> using namespace std; const int N = 10110; int pre[N],mid[N]; //前序遍历 中序遍历结果 int n,cnt; queue<int> q; struct Node { int w; int l,r; }node[N]; void bulid(int l,int r,int pos) { if(l>=r) { node[pos].w = -1; return; } int root = pre[cnt++]; node[pos].w = root; node[pos].l = 2*pos;//左子结点 node[pos].r = 2*pos+1;//右子结点 int m = find(mid,mid+r,root)-mid; //algorithm中的find()函数,返回指针 bulid(l,m,2*pos); bulid(m+1,r,2*pos+1); } void LevelPrint() { q.push(1); int pos; while(!q.empty())

Leetcode——863.二叉树中所有距离为 K 的结点

余生长醉 提交于 2020-02-09 12:53:05
给定一个二叉树(具有根结点 root), 一个目标结点 target ,和一个整数值 K 。 返回到目标结点 target 距离为 K 的所有结点的值的列表。 答案可以以任何顺序返回。 示例 1: 输入:root = [3,5,1,6,2,0,8,null,null,7,4], target = 5, K = 2 输出:[7,4,1] 解释: 所求结点为与目标结点(值为 5)距离为 2 的结点, 值分别为 7,4,以及 1 注意,输入的 "root" 和 "target" 实际上是树上的结点。 上面的输入仅仅是对这些对象进行了序列化描述。 提示: 给定的树是非空的,且最多有 K 个结点。 树上的每个结点都具有唯一的值 0 <= node.val <= 500 。 目标结点 target 是树上的结点。 0 <= K <= 1000. 来源:力扣(LeetCode) 链接: https://leetcode-cn.com/problems/all-nodes-distance-k-in-binary-tree 一 这道题给了我们一棵二叉树,一个目标结点 target,还有一个整数K,让返回所有跟目标结点 target 相距K的结点。我们知道在子树中寻找距离为K的结点很容易,因为只需要一层一层的向下遍历即可,难点就在于符合题意的结点有可能是祖先结点,或者是在旁边的兄弟子树中

二叉树三种遍历方式的非递归实现

南楼画角 提交于 2020-02-09 07:50:11
1、二叉树的先序遍历。 节点->左孩子->右孩子 用递归很容易解决,但是会遇到内存溢出情况。用栈可以解决找个问题。 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:   对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3)直到P为NULL并且栈为空,则遍历结束。 1 public void xianxu(TreeNode root){ 2 Stack<TreeNode> stack = new Stack<>(); 3 TreeNode p = root; 4 while ( !stack.isEmpty() ){ 5 while ( p != null ){ 6 System.out.println(p.val); 7 stack.push(p); 8 p = p.left; 9 } 10 if ( !stack.isEmpty() ){ 11 p = stack.pop(); 12 p = p.right; 13 } 14 } 15

二叉树的遍历方式(迭代)

妖精的绣舞 提交于 2020-02-09 07:49:41
1.先序遍历 根据前序遍历访问的顺序,优先访问根结点,然后再分别访问左孩子和右孩子。即对于任一结点,其可看做是根结点,因此可以直接访问,访问完之后,若其左孩子不为空,按相同规则访问它的左子树;当访问其左子树时,再访问它的右子树。因此其处理过程如下:   对于任一结点P: 1)访问结点P,并将结点P入栈; 2)判断结点P的左孩子是否为空,若为空,则取栈顶结点并进行出栈操作,并将栈顶结点的右孩子置为当前的结点P,循环至1);若不为空,则将P的左孩子置为当前的结点P; 3)直到P为NULL并且栈为空,则遍历结束。 vector<int> PreOrder(TreeNode* root){ vector<int>res; if (!root)return res; stack<TreeNode*>ss; TreeNode* cur = root; while (cur || !ss.empty()){ if (cur){ res.push_back(cur->val); ss.push(cur); cur = cur->left; } else{ cur = ss.top(); cur = cur->right; ss.pop(); } } return res; } 2.中序遍历 根据中序遍历的顺序,对于任一结点,优先访问其左孩子,而左孩子结点又可以看做一根结点,然后继续访问其左孩子结点

教你如何迭代地遍历二叉树

牧云@^-^@ 提交于 2020-02-09 07:49:21
为何要迭代? 二叉树遍历是一个非常常见的操作,无论是中序遍历、先序遍历还是后续遍历,都可以用递归的方法很好地完成,但是相对来说迭代的方法难度就高不少,而且除此之外,迭代地遍历树至少有两个现实意义的优点: 1.比递归节省空间,递归是用栈实现的,因此如果树的高度h很大的话,递归很有可能会造成栈溢出 2.迭代的代码利用循环,而循环可以用循环不变量来证明代码的正确性 我们现在就分别详解这几个迭代地遍历树的方法。 先序遍历 我们先来看看先序遍历,因为在这个里面先序遍历用迭代实现是最简单的。我们先看递归的代码: class Solution: # @param root, a tree node # @return a list of integers def preorder(self,root): ans=[] self.dfs(root, ans) return ans def dfs(self,root,ans): if not root: return ans.append(root.val) self.dfs(root.left, ans) self.dfs(root.right,ans) 先序遍历就是先处理根节点,再处理左右子女节点,因此用迭代实现时,我们只要处理完根节点之后,把左右子女按照先右子女、后左子女的顺序推入栈来保证这个处理顺序就可以了。这个代码也很好理解: class