二叉树遍历之递归、父结点、栈
来源:互联网 发布:c语言数据类型有哪些 编辑:程序博客网 时间:2024/06/06 01:46
二叉树结构
struct bst_node { struct bst_node *parent; struct bst_node *left; struct bst_node *right; int key;};
1. 递归
这个代码最直接,不需要父结点,不多解释
void bst_inorder(struct bst_node *node){ if (node) { if (node->left) bst_inorder(node->left); printf("%d ", node->key); if (node->right) bst_inorder(node->right); }}void bst_postorder(struct bst_node *node){ if (node) { if (node->left) bst_postorder(node->left); if (node->right) bst_postorder(node->right); printf("%d ", node->key); }}void bst_preorder(struct bst_node *node){ if (node) { printf("%d ", node->key); if (node->left) bst_preorder(node->left); if (node->right) bst_preorder(node->right); }}
2. 父结点
使用父结点回溯
2.1中序void bst_nonrecur_inorder(struct bst_node *root){ struct bst_node *p = root, *parent; while (p && p->left) p = p->left; for (;p;) { printf("%d ", p->key); if (p->right) { p = p->right; while (p && p->left) p = p->left; } else { parent = p->parent; while (parent) { if (parent->left == p) { break; } p = parent; parent = parent->parent; } p = parent; } }}
遍历过程很简单,首先找到最左结点,即找根结点树的最小结点。
访问当前结点,如果当前结点有右子结点,则访问其右子结点的最左结点;否则回溯,直到某个祖先结点为其父结点的左子结点,此为后继结点;然后继续循环。
这个遍历过程就是算法导论中的两个过程,一个是取最小值,另一个是找后继结点
2.2 前序
void bst_nonrecur_preorder(struct bst_node *root){ struct bst_node *p = root, *parent; while(p) { printf("%d ", p->key); if (p->left) p = p->left; else if (p->right) p = p->right; else { for (;;) { if (!(parent = p->parent)) { p = NULL; break; } if (parent->left == p && parent->right) { p = parent->right; break; } p = parent; } } }}前序遍历最简单,首先访问当前结点,然后优先访问左子树,然后右子树,如果遇到叶子结点,则回溯,直到其祖先结点为其父结点的左子结点而且该祖先结点有右子树
2.3 后序
void bst_nonrecur_postorder(struct bst_node *root){ struct bst_node *p = root, *parent; while(p) { if (p->left) p = p->left; else if (p->right) p = p->right; else { printf("%d ", p->key); for (;;) { if (!(parent = p->parent)) { p = NULL; break; } if (parent->left == p) { if (parent->right) { p = parent->right; break; } printf("%d ", parent->key); } else if (parent->right == p) { printf("%d ", parent->key); } p = parent; } } }}
后序遍历类似前序,只不过优先访问左子树,其次右子树,最后才是根结点。上述代码先访问叶子结点,在回溯的过程中,分两种情况讨论:
1. 该叶子结点在其某祖先结点的左子树,如果该祖先结点没有右子树,则直接访问该祖先结点,否则转向其右子树
2. 该叶子结点在其某祖先结点的右子树,由于从右子树回溯,表示左右子树都访问过了,直接访问该祖先结点3. 栈
使用数组实现栈结构
3.1 中序
void bst_stack_inorder(struct bst_node *root){ int i = 0; struct bst_node *s[1024] = {0, }; struct bst_node *p = root; /* use s[0] as NULL pointer */#define PUSH_S(n, i) s[++(i)]=(n)#define POP_S(i) s[(i)--] PUSH_S(p, i); while (p->left) { PUSH_S(p->left, i); p = p->left; } while (i > 0) { /* pop top && visit top var */ p = POP_S(i); printf("%d ", p->key); /* push right */ if (p->right) { PUSH_S(p->right, i); p = p->right; /* push all left */ while (p->left) { PUSH_S(p->left, i); p = p->left; } } }}遍历过程和使用父结点类似,只不过将回溯过程使用栈来处理
3.2 前序
void bst_stack_preorder(struct bst_node *root){ int i = 0; struct bst_node *s[1024] = {0, }; struct bst_node *p = root; /* use s[0] as NULL pointer */#define PUSH_S(n, i) s[++(i)]=(n)#define POP_S(i) s[(i)--] PUSH_S(p, i); while (i > 0) { /* pop top && visit top var */ p = POP_S(i); printf("%d ", p->key); /* push right */ if (p->right) { PUSH_S(p->right, i); } /* push left */ if (p->left) PUSH_S(p->left, i); }}此遍历过程最简单,首先访问当前结点,再将右子结点压栈,最后再压入左子结点,因为栈的后进先出原则保证优先访问左子结点
3.3 后序
static inline void bst_stack_post_push(struct bst_node *p, struct bst_node **s, int *i){ int index = *i; s[++index] = p; while (p->left || p->right) { if (p->left) p = p->left; else p = p->right; s[++index] = p; } *i = index;}void bst_stack_postorder(struct bst_node *root){ int i = 0; struct bst_node *s[1024] = {0, }; struct bst_node *p = root, *last;; /* use s[0] as NULL pointer */#define PUSH_S(n, i) s[++(i)]=(n)#define POP_S(i) s[(i)--]#define TOP_S(i) s[(i)] bst_stack_post_push(p, s, &i); while (i > 0) { /* get top */ p = TOP_S(i); if (p->left == last && p->right) { bst_stack_post_push(p->right, s, &i); } else { p = POP_S(i); printf("%d ", p->key); last = p; } }}
此遍历过程最复杂,优先访问左子结点,其次右子结点,一直到叶子结点,将其所有祖先结点入栈,这个过程由函数bst_stack_post_push完成
使用last 来保存上一个遍历的结点
遍历时,先查看栈顶元素,分两种情况讨论:
1. 如果遍历路径是从左子树到根,则查看根结点是否有右子树,如果有右子树,则需要先将右子树使用bst_stack_post_push处理,否则直接访问
2. 如果遍历路径是从右子树到根,则直接访问- 二叉树遍历之递归、父结点、栈
- 二叉树遍历之递归
- 二叉树建立、遍历(递归非递归),求结点等
- 二叉树模板 先中后序遍历,非递归算法,层次遍历,叶子结点数,深度
- 二叉树遍历之递归算法
- 二叉树遍历之递归算法
- 二叉树遍历之非递归算法
- 二叉树遍历之递归算法
- 二叉树遍历之非递归算法
- 二叉树遍历之非递归算法
- 二叉树遍历之非递归实现
- 二叉树遍历之递归算法
- 二叉树学习之非递归遍历
- 二叉树遍历之递归算法
- 二叉树遍历之非递归算法
- 二叉树递归遍历
- 二叉树遍历(递归)
- 二叉树递归遍历
- ios png
- Linux USB Gadget--软件结构
- Android APK安装常见错误
- SQL中判断字符串中包含字符的方法
- py2exe打包后dos窗口随着软件同启同关解决
- 二叉树遍历之递归、父结点、栈
- XML 处理
- Flex URLLoader 跨域访问weblogic发布的图像问题
- MySQL中文全文索引插件 mysqlcft 1.0.0 安装使用文档[原创]
- 第八周C++上机报告(项目3__分数运算符重载)
- Js五子棋游戏
- mq
- setup.py打包程序对资源文件的搜索方式
- WinCE下自动启动多个应用程序