树的浅析与实现

Posted chenshikun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树的浅析与实现相关的知识,希望对你有一定的参考价值。

一、基本概念

  树是一种简单的非线性结构,所有元素之间具有明显的层次特性。在树结构中,每一个结点只有一个前驱节点,称为父结点,没有前驱节点的结点只有一个,称为树的根结点,简称树的根。每一个结点可以有多个后继节点,称为该结点的子结点。没有后继节点的结点称为叶子结点。在树结构中,一个结点所拥有的后件的个数称为该结点的度,所有结点中最大的度称为树的度。树的最大层次称为树的深度。

二、二叉树

  定义:二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。二叉树通常分为满二叉树和完全二叉树。

  (1)满二叉树:一个深度为K且有2k+1-1个节点的二叉树。

  (2)完全二叉树:只多有最下面的两层的节点的度数可以小于2,其余各层节点的度数都等于2,并且最下面一层的节点都集中在该层最左边的若干位置。

  性质:

  (1)对于非空二叉树,其i层最大的节点数目为2i,其中i>=0。

  (2)深度为k的二叉树之多有2k+1-1个节点,其中k>=-1。

  (3)在任意一棵非空二叉树中,若终端节点的个数为n0,度为2的节点数为n2,则存在n0 = n2 +1。

  (4)具有n个节点的完全二叉树的深度为k等于log2(n+1)向上取整再减1。

  (5)如将一棵有n个节点的完全二叉树子上(根节点)向下(叶节点),同一层,子做向右连续赋予节点编号0,1,2,3,4....,n-1则对任意下标为i的节点有:

    1、若i=0,则i为根节点,无父节点;若i>0,i>0,则i的父节点下标为(i-1)/2向下取整。

    2、若2*i+1<n,则i的左子女为2*i+1。

    3、若2*i+2<n,则i的右子女为2*i+2。

    4、若i为偶数,且i≠0,则左兄弟为i-1。

    5、若i为奇数,且i≠n-1,则右兄弟为i+1。

    6、节点i所在的层次为log2(i+1)向下取整。

  实现:

树节点定义

技术分享图片
 1 #pragma once
 2 #include <iostream>  
 3 #include <assert.h>  
 4 using namespace std;
 5 template <class T>
 6 class BinaryTreeNode
 7 {
 8 public:
 9     BinaryTreeNode();
10     BinaryTreeNode(BinaryTreeNode* node);
11     void setData(const T &value);                        //设置节点值
12     void setParent(BinaryTreeNode<T>*parent);            //设置父节点
13     void setLeftChild(BinaryTreeNode<T>*leftchild);        //设置左孩子节点
14     void setRightChild(BinaryTreeNode<T>*rightchild);    //设置右孩子节点
15     T& getData();                                        //获取节点值
16     BinaryTreeNode<T>* getparent();                        //获取父节点
17     BinaryTreeNode<T>* getLeftChild();                    //获取左孩子节点
18     BinaryTreeNode<T>* getRightChild();                    //获取右孩子节点
19 
20 private:
21     T m_value;                               //存储值
22     BinaryTreeNode<T>* m_parent;             //指向父节点
23     BinaryTreeNode<T>* m_leftChilde;         //指向左孩子节点
24     BinaryTreeNode<T>* m_rightChilde;         //指向右孩子节点
25 };
26 
27 
28 
29 
30 template <class T>
31 BinaryTreeNode<T>::BinaryTreeNode()
32 {
33     m_parent = NULL;
34     m_leftChilde = NULL;
35     m_rightChilde = NULL;
36 }
37 
38 template <class T>
39 BinaryTreeNode<T>::BinaryTreeNode(BinaryTreeNode* node)
40 {
41     m_value = node->getData();
42     m_parent = node->getparent();
43     m_leftChilde = node->getLeftChild();
44     m_rightChilde = node->getRightChild();
45 }
46  
47 template <class T>
48 void BinaryTreeNode<T>::setData(const T &value)
49 {
50     m_value = value;
51 }
52 
53 template <class T>
54 void BinaryTreeNode<T>::setParent(BinaryTreeNode<T>*parent)
55 {
56     m_parent = parent;
57 }
58 
59 template <class T>
60 void BinaryTreeNode<T>::setRightChild(BinaryTreeNode<T>*rightchild)
61 {
62     m_rightChilde = rightchild;
63 }
64 
65 template <class T>
66 void BinaryTreeNode<T>::setLeftChild(BinaryTreeNode<T>*leftchild)
67 {
68     m_leftChilde = leftchild;
69 }
70 
71 template <class T>
72 T& BinaryTreeNode<T>::getData()
73 {
74     return m_value;
75 }
76 
77 template <class T>
78 BinaryTreeNode<T>* BinaryTreeNode<T>::getparent()
79 {
80     return m_parent;
81 }
82 
83 template <class T>
84 BinaryTreeNode<T>* BinaryTreeNode<T>::getRightChild()
85 {
86     return m_rightChilde;
87 }
88 
89 template <class T>
90 BinaryTreeNode<T>* BinaryTreeNode<T>::getLeftChild()
91 {
92     return m_leftChilde;
93 }
binaryTreeNode.h

树定义

技术分享图片
  1 #pragma once
  2 #include <iostream>  
  3 #include <assert.h> 
  4 #include <stack>
  5 #include <queue>
  6 #include "binaryTreeNode.h"
  7 using namespace std;
  8 template <class T>
  9 class BinaryTree
 10 {
 11 public:
 12     BinaryTree(T &value);
 13     BinaryTree(BinaryTreeNode<T>* node);
 14     BinaryTreeNode<T>* getRoot();   //获取根节点
 15     void insertLeftChild(BinaryTreeNode<T>* root, T &value);  //插入左孩节点
 16     void insertRightChild(BinaryTreeNode<T>* root,T &value);  //插入右孩子节点
 17     bool isEmpty(); //判断是否为空
 18     //树的遍历
 19     //前序遍历
 20     void preOrderTraverse1(BinaryTreeNode<T>* root) const; //使用递归实现
 21     void preOrderTraverse2(BinaryTreeNode<T>* root) const; //使用栈结构实现
 22     //中序遍历
 23     void inOrderTraverse1(BinaryTreeNode<T>* root) const; //使用递归实现
 24     void inOrderTraverse2(BinaryTreeNode<T>* root) const; //使用栈结构实现
 25     //后序遍历
 26     void postOrderTraverse1(BinaryTreeNode<T>* root) const; //使用递归实现
 27     void postOrderTraverse2(BinaryTreeNode<T>* root) const; //使用栈结构实现
 28     //层序遍历
 29     void levelOrderTraverse(BinaryTreeNode<T>* root) const;
 30 private:
 31     BinaryTreeNode<T>* m_root;  //根节点
 32 };
 33 
 34 
 35 
 36 
 37 
 38 //构造函数
 39 template <class T>
 40 BinaryTree<T>::BinaryTree(T &value)
 41 {
 42     m_root = new BinaryTreeNode<T>();
 43     m_root->setData(value);
 44 }
 45 
 46 template <class T>
 47 BinaryTree<T>::BinaryTree(BinaryTreeNode<T>* node)
 48 {
 49     m_root = new BinaryTreeNode<T>(); //创建一个新的节点
 50     m_root = node;
 51 }
 52 
 53 //设置子节点函数
 54 template <class T>
 55 void BinaryTree<T>::insertRightChild(BinaryTreeNode<T>* root, T &value)
 56 {
 57     BinaryTreeNode<T>* childNode = new BinaryTreeNode<T>();
 58     childNode->setData(value);
 59     childNode->setParent(root);
 60     root->setRightChild(childNode);
 61 }
 62 
 63 template <class T>
 64 void BinaryTree<T>::insertLeftChild(BinaryTreeNode<T>* root, T &value)
 65 {
 66     BinaryTreeNode<T>* childNode = new BinaryTreeNode<T>();
 67     childNode->setData(value);
 68     childNode->setParent(root);
 69     root->setLeftChild(childNode);
 70 }
 71 
 72 //获取根节点函数
 73 template <class T>
 74 BinaryTreeNode<T>* BinaryTree<T>::getRoot()
 75 {
 76     return m_root;
 77 }
 78 
 79 template <class T>
 80 bool BinaryTree<T>::isEmpty()
 81 {
 82     return m_root->getparent();
 83 }
 84 
 85 //遍历函数
 86 //1、前序遍历
 87 template <class T>
 88 void BinaryTree<T>::preOrderTraverse1(BinaryTreeNode<T>* root) const
 89 {
 90     if (NULL !=root)
 91     {
 92         cout << root->getData() << "->";
 93         preOrderTraverse1(root->getLeftChild());
 94         preOrderTraverse1(root->getRightChild());
 95     }
 96 }
 97 
 98 template <class T>
 99 void BinaryTree<T>::preOrderTraverse2(BinaryTreeNode<T>* root) const
100 {
101     stack<BinaryTreeNode<T>*> s;
102     BinaryTreeNode<T>* p = root;
103     while (!s.empty() || p!=NULL)
104     {
105         while (p)
106         {
107             s.push(p);
108             cout << p->getData() << "->";
109             p = p->getLeftChild();
110         }
111         p = s.top();
112         s.pop();
113         p = p->getRightChild();
114 
115     }
116 }
117 
118 //2、中序遍历
119 template <class T>
120 void BinaryTree<T>::inOrderTraverse1(BinaryTreeNode<T>* root) const
121 {
122     if (NULL != root)
123     {
124         inOrderTraverse1(root->getLeftChild());
125         cout << root->getData() << "->";
126         inOrderTraverse1(root->getRightChild());
127     }
128 }
129 
130 template <class T>
131 void BinaryTree<T>::inOrderTraverse2(BinaryTreeNode<T>* root) const
132 {
133     stack<BinaryTreeNode<T>*> s;
134     BinaryTreeNode<T>*p = root;
135     while (!s.empty() || p != NULL)
136     {
137         while (p)
138         {
139             s.push(p);
140             p = p->getLeftChild();
141         }
142         p = s.top();
143         s.pop();
144         cout << p->getData()<<"->";
145         p = p->getRightChild();
146     }
147 }
148 
149 //2、后序遍历
150 template <class T>
151 void BinaryTree<T>::postOrderTraverse1(BinaryTreeNode<T>* root) const
152 {
153     if (NULL!=root)
154     {
155         postOrderTraverse1(root->getLeftChild());
156         postOrderTraverse1(root->getRightChild());
157         cout << root->getData() << "->";
158     }
159 }
160 
161 template <class T>
162 void BinaryTree<T>::postOrderTraverse2(BinaryTreeNode<T>* root) const
163 {
164     stack<BinaryTreeNode<T>*> s;
165     BinaryTreeNode<T> *cur;            //当前节点
166     BinaryTreeNode<T> *pre = NULL;  //上一次访问的节点
167     s.push(root);
168     while (!s.empty() )
169     {
170         cur = s.top();
171         if ((cur->getLeftChild() == NULL) && (cur->getRightChild() == NULL)
172             || (pre != NULL)&&(pre ==cur->getLeftChild()||pre==cur->getRightChild()))
173         {
174             cout << cur->getData() << "->"; //如果当前结点没有孩子结点或者孩子节点都已被访问过 
175             s.pop();
176             pre = cur;
177         }
178         else
179         {
180             if (cur->getRightChild() != NULL)
181             {
182                 s.push(cur->getRightChild());
183             }
184             if (cur->getLeftChild() != NULL)
185             {
186                 s.push(cur->getLeftChild());
187             }
188         }
189 
190     }
191 
192 
193 }
194 //层序遍历
195 template <class T>
196 void BinaryTree<T>::levelOrderTraverse(BinaryTreeNode<T>* root) const
197 {
198     queue<BinaryTreeNode<T>* > q;
199     BinaryTreeNode<T>* p;
200     q.push(root);
201         while (!q.empty())
202         {
203             p = q.front();
204             if (p->getLeftChild() != NULL)
205                 q.push(p->getLeftChild());
206             if (p->getRightChild() != NULL)
207                 q.push(p->getRightChild());
208             q.pop();
209             cout << p->getData() << "->";
210     }
211 }
BinaryTree.h

测试代码

技术分享图片
 1 #include <stdio.h>
 2 #include <iostream>
 3 #include "BinaryTree.h"
 4 #include "binaryTreeNode.h"
 5 using namespace std;
 6 int main()
 7 {
 8     char value = A;
 9     BinaryTree<char> mytree(value);
10     value++;
11     mytree.insertLeftChild(mytree.getRoot(), value);
12     value++;
13     mytree.insertRightChild(mytree.getRoot(), value);
14     value++;
15     mytree.insertLeftChild(mytree.getRoot()->getLeftChild(), value);
16     value++;
17     mytree.insertRightChild(mytree.getRoot()->getLeftChild(), value);
18     value++;
19     mytree.insertLeftChild(mytree.getRoot()->getRightChild(), value);
20     value++;
21     mytree.insertRightChild(mytree.getRoot()->getRightChild(), value);
22  
23     cout << mytree.getRoot()->getData() << "
";
24     cout << mytree.getRoot()->getLeftChild()->getData() << "
";
25     cout << mytree.getRoot()->getRightChild()->getData() << "
";
26     cout << mytree.getRoot()->getLeftChild()->getLeftChild()->getData() << "
";
27     cout << mytree.getRoot()->getLeftChild()->getRightChild()->getData() << "
";
28     cout << mytree.getRoot()->getRightChild()->getLeftChild()->getData() << "
";
29     cout << mytree.getRoot()->getRightChild()->getRightChild()->getData() << "
";
30     cout <<"前序遍历递归实现"<<endl;
31     mytree.preOrderTraverse1(mytree.getRoot());
32     cout << endl;
33     cout << "前序遍历栈实现" << endl;
34     mytree.preOrderTraverse2(mytree.getRoot());
35     cout << endl;
36     cout << "中序遍历递归实现" << endl;
37     mytree.inOrderTraverse1(mytree.getRoot());
38     cout << endl;
39     cout << "中序遍历栈实现" << endl;
40     mytree.inOrderTraverse2(mytree.getRoot());
41     cout << endl;
42     cout << "后序遍历递归实现" << endl;
43     mytree.postOrderTraverse1(mytree.getRoot());
44     cout << endl;
45     cout << "后序遍历栈实现" << endl;
46     mytree.postOrderTraverse2(mytree.getRoot());
47     cout << endl;
48     cout << "层序遍历实现" << endl;
49     mytree.levelOrderTraverse(mytree.getRoot());
50     
51     
52     return 0;
53 }
测试代码

测试结果

技术分享图片

 

以上是关于树的浅析与实现的主要内容,如果未能解决你的问题,请参考以下文章

go语言浅析二叉树

浅析B树与硬盘数据存储

线程浅析

浅析决策树的生长和剪枝

浅析左偏树的性质及其应用

HashMap源码阅读笔记——HashMap的实现原理浅析