二叉树算法(递归与非递归)

来源:互联网 发布:淘宝卖的德国护肤品 编辑:程序博客网 时间: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");}



0 0