二叉树算法(递归与非递归)
来源:互联网 发布:淘宝卖的德国护肤品 编辑:程序博客网 时间:2024/06/05 12:03
首先我们来了解下二叉树的基本概念和构造
1. 父节点,子节点,兄弟节点
很容易理解,2和3的父节点就是1,反过来说就是2和3是1的子节点。2和3就是兄弟节点。
2. 结点的度
其实”度“就是”分支数“,比如1的分支数有两个“2和3",那么1的度为2。
3. 树的度
看似比较莫名其妙吧,他和”结点的度“的区别就是,树的度讲究大局观,乃树中最大的结点度,其实也就是2。
4.叶结点,分支结点
叶结点就是既没有左孩子也没有右孩子结点,也就是结点度为0。
5. 结点的层数
这个很简单,也就是树有几层。
6. 森林
现实中,很多的树形成了森林,那在数据结构中,我们把上图的“1”节点砍掉,那么2,3子树合一起就是森林。
7.树的表示
树这个结构的表示其实有很多种,常用的也就是“括号”表示法。
比如上面的树就可以表示为:(1(2(4),(5(,7))),3(,6(,8)))
8.树的一些基本算法:下面除了层序遍历的非递归算法用到了队列的知识点,其他的非递归算法基本用到了栈的知识点
对队列或者是栈不懂得可以点击文字连接了解。
1.创建树
创建树有两种方式,顺序储存和链表储存。由于顺序储存存在操作不方便,且占用资源多的缺点。故一般我们采 用链表形式来创建一个二叉树。我们需要定义一个二叉树的结构体,在这个结构体中,需要定义两个指针,分别指向左子树和右子树。在这里我们在创建上图二叉树时,一般采取的是按照先左后右的方式创建二叉树。而且我们需要将上图转化为一个数组方便我们进行操作。
typedef int ValueType;typedef struct Node {ValueType value;struct Node *LChild;struct Node *RChild;}*BinaryTree;const ValueType elem[] = { 1,2,4,0,0,5,0,7,0,0,3,0,6,0,8,0,0 };BinaryTree _Create(const ValueType* &elem) { //创建树ValueType v = *elem;++elem;BinaryTree t;if (!v) t = NULL;else {t = new Node;t->value = v;t->LChild = _Create(elem);t->RChild = _Create(elem);}return t;}BinaryTree _Create1(const ValueType *value) { //创建树,非递归const ValueType *v = value;BinaryTree node = new Node;BinaryTree tree = node;stack<BinaryTree> s;while (*v || !s.empty()) {while (*v) {node->value = *v;++v;s.push(node);if (*v) {node->LChild = new Node;node = node->LChild;}else node->LChild = NULL;}BinaryTree top = s.top();s.pop();++v;if (*v) {top->RChild = new Node;node = top->RChild;}else top->RChild = NULL;}return tree;}2.先序遍历
按先进先出的方式,如上面在创建二叉树是先创建的就先输出来:结果应该为:12457368
void _PreOrder_Traverse(BinaryTree tree) { //前序遍历if (tree) {cout << tree->value << " ";_PreOrder_Traverse(tree->LChild);_PreOrder_Traverse(tree->RChild);}}void _PreOrder_Traverse1(BinaryTree tree) { //前序遍历,非递归stack<BinaryTree> s;Node *node = tree;while (node || !s.empty()) {while (node) {cout << node->value << " ";s.push(node);node = node->LChild;}Node *top = s.top();s.pop();node = top->RChild;}cout << endl;}void _PreOrder_Traverse2(BinaryTree tree) { //这种方法更加简洁stack<BinaryTree> s;BinaryTree p = tree;while (p || !s.empty()) {if (p) {cout << p->value << " ";s.push(p);p = p->LChild;}else {p = s.top();s.pop();p = p->RChild;}}cout << endl;}3.中序遍历:在输出一个节点后,返回输出该节点的父节点,然后输出父节点的右子树。void _InOrder_Traverse(BinaryTree tree) { //中序遍历,递归法if (tree) {_InOrder_Traverse(tree->LChild);cout << tree->value << " ";_InOrder_Traverse(tree->RChild);}}void _InOrder_Traverse1(BinaryTree tree) { //中序遍历,非递归Node *node = tree;stack<BinaryTree> s;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;}Node *top = s.top();cout << top->value << " ";s.pop();if (top->RChild != NULL)node = top->RChild;}cout << endl;}void _InOrder_Traverse2(BinaryTree tree) { //中序遍历,非递归,简洁版stack<BinaryTree> s;BinaryTree p = tree;while (p || !s.empty()) {if (p) {s.push(p);p = p->LChild;}else { p = s.top();s.pop();cout << p->value << " ";p = p->RChild;}}cout << endl;}
3.后序遍历,按照从左往右的方式,先输出一个节点的左右子树,在输出该节点,接着输出该节点的兄弟子树,让后输出该节点的父节点。void _PostOrder_Traverse(BinaryTree tree) { //后序遍历,递归法if (tree) {_PostOrder_Traverse(tree->LChild);_PostOrder_Traverse(tree->RChild);cout << tree->value << " ";}}void _PostOrder_Traverse1(BinaryTree tree) { //后序遍历,非递归法Node *node = tree;stack<BinaryTree> s;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;}Node *top = s.top();if (!top->RChild) {cout << top->value << " ";s.pop();Node *tmp = s.top();while (top == tmp->RChild) {top = s.top();cout << top->value << " ";s.pop();if (!s.empty())tmp = s.top();}}else {top = s.top();node = top->RChild;}}cout << endl;}
4.层序遍历。顾名思义就是一层一层的输出啦!这里需要用到队列的来解决这个问题。void _Level_Traverse(BinaryTree tree) { //层次遍历queue<BinaryTree> q;BinaryTree tmp = tree;q.push(tmp);while(!q.empty()) {tmp=q.front();cout << tmp->value << " ";q.pop();if (tmp->LChild != NULL)q.push(tmp->LChild);if (tmp->RChild != NULL)q.push(tmp->RChild);}}
5.求深度:就是求这棵树最多有几层int _Depth(BinaryTree tree) { //求树的深度,递归法if (!tree)return 0;else {int LDepth = _Depth(tree->LChild);int RDepth = _Depth(tree->RChild);if (LDepth > RDepth)return 1 + LDepth;else return 1 + RDepth;}}int _Depth1(BinaryTree tree) { //求树的深度,非递归法if (!tree)return 0;int depth = 0;int flag = 0; //用于标记正在遍历的在大深度stack<BinaryTree> s;Node *node = tree;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;++flag;}if (flag > depth)depth = flag; //当某一子树大于已经求得的子树深度时,将深度重赋值Node *top = s.top();if (top->RChild)node = top->RChild;else {s.pop();Node *tmp = s.top();while (top == tmp->RChild&&!s.empty()) {top = s.top();s.pop();--flag;if (!s.empty())tmp = s.top();}--flag;}}return depth;}
6.求叶子数,就是求没有左右子树的节点数int _Leaves(BinaryTree tree) { //求叶子数,递归法if (!tree)return 0;BinaryTree tmp = tree;int num = 0;if (tmp->LChild == NULL&&tmp->RChild == NULL)return num+1;if (tmp->LChild != NULL)num += _Leaves(tmp->LChild);if (tmp->RChild != NULL)num += _Leaves(tmp->RChild);return num;}int _Leaves1(BinaryTree tree) { //求叶子数,非递归if (!tree)return 0;int leaves = 0;BinaryTree node = tree;stack<BinaryTree> s;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;++leaves;}Node *top = s.top();if (!top->RChild) {s.pop(); Node *tmp=new Node;if (!s.empty()) tmp = s.top(); //防止栈空时赋值while (top == tmp->RChild) {top = s.top();s.pop();if(!s.empty())tmp = s.top();}}else node = top->RChild;}return leaves;}
7.求树的大小:树总共有几个节点int _Size(BinaryTree tree) { //求树的大小 ,递归法if (!tree) return 0;else return 1 + _Size(tree->LChild) + _Size(tree->RChild);}int _Size1(BinaryTree tree) { //求树的大小 ,非递归法if (!tree)return 0;int size = 0;stack<BinaryTree> s;Node *node = tree;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;++size;}Node *top = s.top();s.pop();node = top->RChild;}return size;}8.拷贝。没啥好说的,就是拷贝一个新的树出来。BinaryTree _Copy1(BinaryTree tree) { //拷贝,非递归if (!tree) return NULL;BinaryTree n_tree;BinaryTree n_node = new Node;n_tree = n_node;BinaryTree prev = tree;stack<BinaryTree> s;stack<BinaryTree> n_s;while (prev || !s.empty()) {while (prev) {n_node->value = prev->value;s.push(prev);n_s.push(n_node);prev = prev->LChild;if (!prev)n_node->LChild = NULL;else {n_node->LChild = new Node;n_node = n_node->LChild;}}BinaryTree top = s.top();BinaryTree n_top = n_s.top();s.pop();n_s.pop();if (!top->RChild)n_top->RChild = NULL;else {n_top->RChild = new Node;n_node = n_top->RChild;prev = top->RChild;}}return n_tree;}
9.反转二叉树,这个算法可是有个有趣的故事,直接从网上截图过来:BinaryTree _InverseTree(BinaryTree tree) { //翻转二叉树,递归if (!tree) return NULL;Node *n_tree = new Node;n_tree->value = tree->value;n_tree->LChild = _InverseTree(tree->RChild);n_tree->RChild = _InverseTree(tree->LChild);return n_tree;}BinaryTree _InverseTree1(BinaryTree tree) { //翻转二叉树,非递归if (!tree) return NULL;BinaryTree n_tree;BinaryTree n_node = new Node;n_tree = n_node;BinaryTree prev = tree;stack<BinaryTree> s;stack<BinaryTree> n_s;while (prev || !s.empty()) {while (prev) {n_node->value = prev->value;s.push(prev);n_s.push(n_node);prev = prev->RChild;if (!prev)n_node->LChild = NULL;else {n_node->LChild = new Node;n_node = n_node->LChild;}}BinaryTree top = s.top();BinaryTree n_top = n_s.top();s.pop();n_s.pop();if (!top->LChild)n_top->RChild = NULL;else {n_top->RChild = new Node;n_node = n_top->RChild;prev = top->LChild;}}return n_tree;}
好了,经常会用到的一些操作的算法就是这么一些了。当然,以后我会尽量收集二叉树的一些题目。最后献上运行结果以及源代码吧。#include<iostream>#include<queue>#include<stack>using namespace std;typedef int ValueType;typedef struct Node {ValueType value;struct Node *LChild;struct Node *RChild;}*BinaryTree;BinaryTree _Create(const ValueType* &elem) { //创建树ValueType v = *elem;++elem;BinaryTree t;if (!v) t = NULL;else {t = new Node;t->value = v;t->LChild = _Create(elem);t->RChild = _Create(elem);}return t;}BinaryTree _Create1(const ValueType *value) { //创建树,非递归const ValueType *v = value;BinaryTree node = new Node;BinaryTree tree = node;stack<BinaryTree> s;while (*v || !s.empty()) {while (*v) {node->value = *v;++v;s.push(node);if (*v) {node->LChild = new Node;node = node->LChild;}else node->LChild = NULL;}BinaryTree top = s.top();s.pop();++v;if (*v) {top->RChild = new Node;node = top->RChild;}else top->RChild = NULL;}return tree;}void _PreOrder_Traverse(BinaryTree tree) { //前序遍历if (tree) {cout << tree->value << " ";_PreOrder_Traverse(tree->LChild);_PreOrder_Traverse(tree->RChild);}}void _PreOrder_Traverse1(BinaryTree tree) { //前序遍历stack<BinaryTree> s;Node *node = tree;while (node || !s.empty()) {while (node) {cout << node->value << " ";s.push(node);node = node->LChild;}Node *top = s.top();s.pop();node = top->RChild;}cout << endl;}void _PreOrder_Traverse2(BinaryTree tree) { //这种方法更加简洁stack<BinaryTree> s;BinaryTree p = tree;while (p || !s.empty()) {if (p) {cout << p->value << " ";s.push(p);p = p->LChild;}else {p = s.top();s.pop();p = p->RChild;}}cout << endl;}void _InOrder_Traverse(BinaryTree tree) { //中序遍历,递归法if (tree) {_InOrder_Traverse(tree->LChild);cout << tree->value << " ";_InOrder_Traverse(tree->RChild);}}void _InOrder_Traverse1(BinaryTree tree) { //中序遍历,非递归Node *node = tree;stack<BinaryTree> s;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;}Node *top = s.top();cout << top->value << " ";s.pop();if (top->RChild != NULL)node = top->RChild;}cout << endl;}void _InOrder_Traverse2(BinaryTree tree) { //中序遍历,非递归,简洁版stack<BinaryTree> s;BinaryTree p = tree;while (p || !s.empty()) {if (p) {s.push(p);p = p->LChild;}else { p = s.top();s.pop();cout << p->value << " ";p = p->RChild;}}cout << endl;}void _PostOrder_Traverse(BinaryTree tree) { //后序遍历,递归法if (tree) {_PostOrder_Traverse(tree->LChild);_PostOrder_Traverse(tree->RChild);cout << tree->value << " ";}}void _PostOrder_Traverse1(BinaryTree tree) { //后序遍历,非递归法Node *node = tree;stack<BinaryTree> s;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;}Node *top = s.top();if (!top->RChild) {cout << top->value << " ";s.pop();Node *tmp = s.top();while (top == tmp->RChild) {top = s.top();cout << top->value << " ";s.pop();if (!s.empty())tmp = s.top();}}else {top = s.top();node = top->RChild;}}cout << endl;}void _Level_Traverse(BinaryTree tree) { //层次遍历queue<BinaryTree> q;BinaryTree tmp = tree;q.push(tmp);while(!q.empty()) {tmp=q.front();cout << tmp->value << " ";q.pop();if (tmp->LChild != NULL)q.push(tmp->LChild);if (tmp->RChild != NULL)q.push(tmp->RChild);}}int _Depth(BinaryTree tree) { //求树的深度,递归法if (!tree)return 0;else {int LDepth = _Depth(tree->LChild);int RDepth = _Depth(tree->RChild);if (LDepth > RDepth)return 1 + LDepth;else return 1 + RDepth;}}int _Depth1(BinaryTree tree) { //求树的深度,非递归法if (!tree)return 0;int depth = 0;int flag = 0; //用于标记正在遍历的在大深度stack<BinaryTree> s;Node *node = tree;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;++flag;}if (flag > depth)depth = flag; //当某一子树大于已经求得的子树深度时,将深度重赋值Node *top = s.top();if (top->RChild)node = top->RChild;else {s.pop();Node *tmp = s.top();while (top == tmp->RChild&&!s.empty()) {top = s.top();s.pop();--flag;if (!s.empty())tmp = s.top();}--flag;}}return depth;}int _Size(BinaryTree tree) { //求树的大小 ,递归法if (!tree) return 0;else return 1 + _Size(tree->LChild) + _Size(tree->RChild);}int _Size1(BinaryTree tree) { //求树的大小 ,非递归法if (!tree)return 0;int size = 0;stack<BinaryTree> s;Node *node = tree;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;++size;}Node *top = s.top();s.pop();node = top->RChild;}return size;}int _Leaves(BinaryTree tree) { //求叶子数,递归法if (!tree)return 0;BinaryTree tmp = tree;int num = 0;if (tmp->LChild == NULL&&tmp->RChild == NULL)return num+1;if (tmp->LChild != NULL)num += _Leaves(tmp->LChild);if (tmp->RChild != NULL)num += _Leaves(tmp->RChild);return num;}int _Leaves1(BinaryTree tree) { //求叶子数,非递归if (!tree)return 0;int leaves = 0;BinaryTree node = tree;stack<BinaryTree> s;while (node || !s.empty()) {while (node) {s.push(node);node = node->LChild;++leaves;}Node *top = s.top();if (!top->RChild) {s.pop(); Node *tmp=new Node;if (!s.empty()) tmp = s.top(); //防止栈空时赋值while (top == tmp->RChild) {top = s.top();s.pop();if(!s.empty())tmp = s.top();}}else node = top->RChild;}return leaves;}BinaryTree _Copy(BinaryTree tree) { //拷贝if (!tree)return NULL;BinaryTree p = tree;BinaryTree n_tree = new Node;n_tree->value = p->value;n_tree->LChild = _Copy(p->LChild);n_tree->RChild = _Copy(p->RChild);return n_tree;}BinaryTree _Copy1(BinaryTree tree) { //拷贝,非递归if (!tree) return NULL;BinaryTree n_tree;BinaryTree n_node = new Node;n_tree = n_node;BinaryTree prev = tree;stack<BinaryTree> s;stack<BinaryTree> n_s;while (prev || !s.empty()) {while (prev) {n_node->value = prev->value;s.push(prev);n_s.push(n_node);prev = prev->LChild;if (!prev)n_node->LChild = NULL;else {n_node->LChild = new Node;n_node = n_node->LChild;}}BinaryTree top = s.top();BinaryTree n_top = n_s.top();s.pop();n_s.pop();if (!top->RChild)n_top->RChild = NULL;else {n_top->RChild = new Node;n_node = n_top->RChild;prev = top->RChild;}}return n_tree;}BinaryTree _InverseTree(BinaryTree tree) { //翻转二叉树,递归if (!tree) return NULL;Node *n_tree = new Node;n_tree->value = tree->value;n_tree->LChild = _InverseTree(tree->RChild);n_tree->RChild = _InverseTree(tree->LChild);return n_tree;}BinaryTree _InverseTree1(BinaryTree tree) { //翻转二叉树,非递归if (!tree) return NULL;BinaryTree n_tree;BinaryTree n_node = new Node;n_tree = n_node;BinaryTree prev = tree;stack<BinaryTree> s;stack<BinaryTree> n_s;while (prev || !s.empty()) {while (prev) {n_node->value = prev->value;s.push(prev);n_s.push(n_node);prev = prev->RChild;if (!prev)n_node->LChild = NULL;else {n_node->LChild = new Node;n_node = n_node->LChild;}}BinaryTree top = s.top();BinaryTree n_top = n_s.top();s.pop();n_s.pop();if (!top->LChild)n_top->RChild = NULL;else {n_top->RChild = new Node;n_node = n_top->RChild;prev = top->LChild;}}return n_tree;}void test() {BinaryTree root;root = new Node;const ValueType elem[] = { 1,2,4,0,0,5,0,7,0,0,3,0,6,0,8,0,0 };const ValueType *p = elem;root = _Create1(p);_PreOrder_Traverse(root);cout << endl;_PreOrder_Traverse1(root);_PreOrder_Traverse2(root);_InOrder_Traverse(root);cout << endl;_InOrder_Traverse1(root);_InOrder_Traverse2(root);_PostOrder_Traverse(root);cout << endl;_PostOrder_Traverse1(root);_Level_Traverse(root);cout << endl;cout << "Leaves:" << _Leaves(root) << endl;cout << "Leaves:" << _Leaves1(root) << endl;cout << "Depth:" << _Depth(root) << endl;cout << "Depth:" << _Depth1(root) << endl;cout << "Size:" << _Size(root) << endl;cout << "Size:" << _Size1(root) << endl;BinaryTree tree1 = _Copy(root);_PreOrder_Traverse1(tree1);BinaryTree tree2 = _Copy1(root);_PreOrder_Traverse1(tree2);BinaryTree tree3 = _InverseTree(root);_PreOrder_Traverse1(tree3);BinaryTree tree4 = _InverseTree1(root);_PreOrder_Traverse1(tree4);cout << endl;}void main() {test();system("pause");}
- 二叉树的遍历算法(递归与非递归)
- 二叉树算法的实现(递归与非递归)
- 二叉树算法(递归与非递归)
- 遍历二叉树的递归算法与非递归算法
- 遍历二叉树递归算法与非递归算法
- 【数据结构与算法】二叉树递归与非递归遍历
- (codes)二叉树的系列算法,递归与非递归
- 二叉树遍历的递归与非递归算法
- 求二叉树的深度,递归与非递归算法
- 一步一步写算法--二叉树递归与非递归遍历
- 二叉树的递归遍历与非递归算法实现
- 二叉树的递归遍历与非递归算法实现
- 遍历二叉树的递归与非递归算法
- 二叉树的递归与非递归遍历算法
- 二叉树遍历的递归与非递归算法
- Java二叉树,递归与非递归遍历算法
- 二叉树遍历(递归算法和非递归算法)
- 【数据结构与算法】二叉树深度遍历(非递归)
- 3月25日,Calculation,每日20行。
- SaaS独角兽成长秘籍:40%法则+7步走战略
- 自己封装的jdbc代码
- [Codeforces]B. Lorry
- 1560: [JSOI2009]火星藏宝图
- 二叉树算法(递归与非递归)
- C语言测试一个函数运行时间的模板
- 画图题
- n的倍数BFS小水题
- Java IO学习总结
- [编程题] 称砝码
- 初识PHP
- 栈
- 剑鱼行动-SSL 1618