首先我们来了解下二叉树的基本概念和构造
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
3.中序遍历:在输出一个节点后,返回输出该节点的父节点,然后输出父节点的右子树。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; }
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.求树的大小:树总共有几个节点8.拷贝。没啥好说的,就是拷贝一个新的树出来。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; }
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"); }
二叉树算法(递归与非递归)
最新推荐文章于 2023-07-30 12:28:05 发布