二叉树基本操作 part1

二叉树的存储结构有两种。第一种是顺序存储结构。若对一棵具有n个结点的完全二叉树的所有结点按层从上到下,每层从左到右的顺序依次对结点从1开始编号,则编号为i的结点具有以下性质:

1.i=1的结点为二叉树的根结点。

2.如果i>1,则结点i的双亲结点编号为i/2(向下取整)。

3.如果2i<=n,则编号为i的结点的左孩子结点编号为2i;如果2i>n,则该结点没有左孩子。

4.如果2i+1<=n,则编号为i的结点的右孩子结点编号为2i+1;如果2i+1>n,则该结点没有右孩子。

利用以上的性质,我们可以开辟一块连续的储存空间(ie.数组),将结点编号与数组下标对应,主要对于非完全二叉树,不存在的结点在数组中也要相应地留空,尽管这会导致空间的浪费。

代码如下:

 1 //顺序存储实现二叉树,结点编号与数组下标对应
 2 template <typename Type> class SeqBT{
 3 private:
 4     int max_size;
 5     Type *data;
 6 public:
 7     SeqBT(int input_size){
 8         max_size=input_size;
 9         data=new Type[max_size];
10     }
11     ~SeqBT(){
12         delete[] data;
13     }
14 };

第二种存储结构是链式存储结构,即结点中包括两个指针指向左右孩子结点。在这种结构下,二叉树的遍历可以通过递归实现,根据输出顺序可分为先序、中序、后序和层序遍历。这里先介绍前三种以及如何通过先序和中序遍历的结果建立二叉树。代码如下:

  1 //链式存储实现二叉树
  2 //结点的定义
  3 template <typename Type> class Node{
  4 public:
  5     Type data;
  6     Node<Type> *lchild;
  7     Node<Type> *rchild;
  8     Node(Type _data){
  9         data=_data;
 10         lchild=NULL;
 11         rchild=NULL;
 12     }
 13     ~Node(){
 14         if(lchild!=NULL){
 15             delete lchild;
 16         }
 17         if(rchild!=NULL){
 18             delete rchild;
 19         }
 20     }
 21     //先序遍历
 22     void preorder(){
 23         cout<<data<<" ";
 24         if(lchild!=NULL){
 25             lchild->preorder();
 26         }
 27         if(rchild!=NULL){
 28             rchild->preorder();
 29         }
 30     }
 31     //中序遍历
 32     void inorder(){
 33         if(lchild!=NULL){
 34             lchild->inorder();
 35         }
 36         cout<<data<<" ";
 37         if(rchild!=NULL){
 38             rchild->inorder();
 39         }
 40     }
 41     //后序遍历
 42     void postorder(){
 43         if(lchild!=NULL){
 44             lchild->postorder();
 45         }
 46         if(rchild!=NULL){
 47             rchild->postorder();
 48         }
 49         cout<<data<<" ";
 50     }
 51 
 52     //用先序和中序遍历建立二叉树
 53     Node* build(const string &pre_str,const string &in_str, int len){
 54         //先序遍历的第一位一定是当前树的根节点
 55         Node *p=new Node(pre_str[0]-'0');
 56         //找到根节点在中序遍历中的位置
 57         //根的左边就是左子树,右边的就是右子树
 58         int pos=in_str.find(pre_str[0]);
 59         //若左子树不为空,递归建立左子树
 60         if(pos>0){
 61             p->lchild=build(pre_str.substr(1,pos),in_str.substr(0,pos),pos);
 62         }
 63         //若右子树不为空,递归建立右子树
 64         if(len-pos-1>0){
 65             p->rchild=build(pre_str.substr(pos+1),in_str.substr(pos+1),len-pos-1);
 66         }
 67         //返回根节点
 68         return p;
 69     }
 70 };
 71 
 72 template <typename Type> class BinaryTree{
 73 private:
 74     Node<Type> *root;
 75 public:
 76     BinaryTree(){
 77         root=NULL;
 78     }
 79     ~BinaryTree(){
 80         delete root;
 81     }
 82 
 83     //利用先序和中序建树的构造函数
 84     BinaryTree(const string &pre_str, const string &in_str, int len){
 85         root=root->build(pre_str,in_str,len);
 86     }
 87 
 88     //for testing
 89     void build_demo() {
 90         root = new Node<int>(1);
 91         root->lchild = new Node<int>(2);
 92         root->rchild = new Node<int>(3);
 93         root->lchild->lchild = new Node<int>(4);
 94         root->lchild->rchild = new Node<int>(5);
 95         root->rchild->rchild = new Node<int>(6);
 96     }
 97     void preorder(){
 98         if(root!=NULL){
 99             root->preorder();
100         }
101     }
102     void inorder(){
103         if(root!=NULL){
104             root->inorder();
105         }
106     }
107     void postorder(){
108         if(root!=NULL){
109             root->postorder();
110         }
111     }
112 
113 };
114 
115 //for testing
116 int main() {
117     BinaryTree<int> binarytree1;
118     binarytree1.build_demo();
119     binarytree1.preorder();
120     cout<<endl;
121     binarytree1.inorder();
122     cout<<endl;
123     binarytree1.postorder();
124     cout<<endl;
125 
126     string pre_str = "136945827";
127     string in_str = "963548127";
128     BinaryTree binarytree2(pre_str,in_str,in_str.length());
129     binarytree2.postorder();
130     cout<<endl;
131 
132     return 0;
133 }

 

转载于:https://www.cnblogs.com/NoviScl/p/7018323.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值