二叉树操作

Posted

tags:

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

#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
#include <stdio.h>
#include <process.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

struct BiTNode //二叉树结点类型

int data; //数据
int tem1,tem2; //辅助数据(实习题不用)
BiTNode *left; //左子树指针
BiTNode *right; //右子树指针
;

BiTNode *Tree; //本程序操作的二叉树根指针

const max=100;
int elem[max]; //存放原始数据

//从键盘输入个数和随机数种子,在数组elem中生成指定个数的数据,供其他程序使用,0表示数据结束
void init0(int list[]);

//在本程序所在的位置生成文本文件Map.txt,其中显示以Tree为根指针的二叉树
void showBinTree(BiTNode *Tree);

//从键盘输入个数和随机数种子,以Tree为根指针,生成指定结点个数的二叉树,供其他程序使用
BiTNode *init1();

//主函数,显示功能菜单(包括生成二叉树、显示二叉树),键盘选择后执行对应功能
void main()




#include "BinT.h"

/*
2、用递归方法分别先序、中序、后序遍历以Tree为根指针的二叉树。
3、编写递归算法,计算二叉树中叶子结点的数目。
4、编写递归算法,计算二叉树的深度。
5、编写递归算法,将二叉树中所有结点的左、右子树相互交换。
6、使用数组elem中的随机数序列(以0表示结束,不包括0),生成以Tree为根指针的二叉排序树。
7、在以Tree为根指针的二叉排序树中查找结点。
8、从以Tree为根指针的二叉排序树中删除结点(适用各种位置的结点)。
9、不用递归,先序遍历以Tree为根指针的二叉树。
提示:用数组 BiTNode *stack[max] 构成堆栈,利用这个堆栈实现功能。
10、用凹入表示法的表示以Tree为根指针的二叉树,例如:
// 324
// 123
// 746
// 690
// 567
11、用广义表表示以Tree为根指针的二叉树,例如
// (324(123(746(),()),(690(),())),(567(),()))
12、对以Tree为根指针的二叉树,从根结点开始,逐层从左到右输出各结点的数据。
提示:用数组 BiTNode *queue[max] 构成队列,利用这个队列实现功能
提高题:

13*、根据Huffman编码原理,使用数组elem中的随机数序列(以0表示结束,不包括0)作为结点的权重,生成赫夫曼树,以及赫夫曼编码,计算平均带权径长度。
14*、(1)随机生成二叉树。 (2)生成并保存先(后)序、中序输出序列。 (3)按照保存的一对输出序列恢复出二叉树。(4)生成先(后)序输出序列。
*/

/*
源文件名:P3.cpp
功能:二叉树操作
*/
#include <iostream.h>
#include <iomanip.h>
#include <conio.h>
#include <stdio.h>
#include <process.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <stack>
using namespace std;
typedef int DataType;
const max=100;
typedef struct
DataType data[max];
int top;
SeqStack;

struct BiTNode //二叉树结点类型

int data; //数据
int tem1,tem2; //辅助数据(实习题不用)
BiTNode *left; //左子树指针
BiTNode *right; //右子树指针
;

BiTNode *Tree; //本程序操作的二叉树根指针

int elem[max]; //存放原始数据
//从键盘输入个数和随机数种子,在数组elem中生成指定个数的数据,供其他程序使用,0表示数据结束
void init0(int list[]);

//在本程序所在的位置生成文本文件Map.txt,其中显示以Tree为根指针的二叉树
void showBinTree(BiTNode *Tree);

//从键盘输入个数和随机数种子,以Tree为根指针,生成指定结点个数的二叉树,供其他程序使用
BiTNode *init1();

//主函数,显示功能菜单(包括生成二叉树、显示二叉树),键盘选择后执行对应功能
void Preorder(BiTNode *Tree);//先序遍历
void Inorder(BiTNode *Tree); //中序遍历
void Postorder(BiTNode *Tree); //后序遍历
int leafs(BiTNode *Tree); //总叶子数
void swap(BiTNode *Tree); //交换左右子树
int depth(BiTNode *Tree); //计算二叉树的深度
void search(BiTNode *T); //查找结点
BiTNode *CreatBST(int A[],int n) ;/
void insert(BiTNode *Tree);
int ELEM(int A[]);/
void del(BiTNode *Tree);/
void preorderl(BiTNode *Tree);/
void main()


//int list[max];
char choice;
while (1)

system("cls");
cout << "\n\n\n\n";
cout << "\t\t 二叉树操作 \n";
cout << "\t\t======================================";
cout << "\n\n";
cout << "\t\t a:生成二叉树 \n";
cout << "\t\t b:显示 \n";
cout << "\t\t c:先序遍历 \n";
cout << "\t\t d:中序遍历 \n";
cout << "\t\t e:后序遍历 \n";
cout << "\t\t f:计算二叉树中叶子结点的数目 \n";
cout << "\t\t g:计算二叉树的深度 \n";
cout << "\t\t h:左、右子树相互交换 \n";
cout << "\t\t i:构建以Tree为根指针的二叉排序树 \n";
cout << "\t\t j:查找结点 \n";
cout << "\t\t k:删除结点 \n";
cout << "\t\t l:不用递归,先序遍历以Tree为根指针的二叉树。 \n";
cout << "\t\t m:凹入表示法的表示以Tree为根指针的二叉树 \n";
cout << "\t\t n:用广义表表示以Tree为根指针的二叉树 \n";
cout << "\t\t o:从根结点开始,逐层从左到右输出各结点的数据 \n";
cout << "\t\t p:生成赫夫曼树,以及赫夫曼编码,计算平均带权径长度 \n";
cout << "\t\t 0:退出 \n";
cout << "\n";
cout << "\t\t请选择:" << flush;

choice = getch();
system("cls");
switch(choice)

case 'a':
Tree=init1();
break;
case 'b':
showBinTree(Tree);
break;
case 'c':
cout<<"先序遍历:"<<endl;
Preorder(Tree);
cout <<flush;
getch();
break;
case 'd':
cout<<"中序遍历:"<<endl;
Inorder(Tree);
cout <<flush;
getch();
break;
case 'e':
cout<<"后序遍历:"<<endl;
Postorder(Tree);
cout <<flush;
getch();

break;
case 'f':
cout<<"二叉树的总叶子结点数为:"<<leafs(Tree)<<endl;
cout <<flush;
getch();
break;
case 'g':
cout<<"二叉树的深度为:"<<depth(Tree)<<endl;
cout <<flush;
getch();
break;
case 'h':
swap(Tree);
cout<<"交换成功!"<<endl;
showBinTree(Tree);
cout <<flush;
getch();
break;
case 'i':
init0(elem);
Tree=CreatBST(elem,ELEM(elem));
break;
case 'j':
cout<<"请输入要查找的元素:";
search(Tree);
cout <<flush;
getch();
break;
case 'k':
cout<<"请输入需要删除的元素:";
del(Tree);
Tree=CreatBST(elem,ELEM(elem));
showBinTree(Tree);
cout <<flush;
getch();
break;
case 'l':
break;
case 'm':
break;
case 'n':
break;
case 'o':
break;
case 'p':
break;
case 'q':
break;
case 'r':
break;

case '0':
exit(0);





#include "BinT.h"
//公用的等待函数
void wait()

cout << "\n\n请按任意键继续" << flush;
getch();

void Preorder(BiTNode *T)//先序遍历


if(T)

cout<<T->data<<" ";
Preorder(T->left);
Preorder(T->right);


void Inorder(BiTNode *T)//中序遍历

if(T)

Inorder(T->left);
cout<<T->data<<" ";
Inorder(T->right);


void Postorder(BiTNode *T)//后序遍历

if(T)

Postorder(T->left);
Postorder(T->right);
cout<<T->data<<" ";


int leafs(BiTNode *T)//总叶子数

if(T==NULL)
return 0;
if((T->left==NULL) && (T->right==NULL))
return 1;
else
return leafs(T->left) + leafs(T->right);

int depth(BiTNode *T)//计算二叉树的深度


int n1,n2;
if(!T)
return 0;
else

n1=depth(T->left);
n2=depth(T->right);
if(n1>n2)
return n1+1;
else
return n2+1;


void swap(BiTNode *T)//交换左右子树

BiTNode *Q;
if(T)

Q = T->left ;
T->left = T->right ;
T->right = Q;
swap(T->left);
swap(T->right);


int InsertBST(BiTNode *&T,int k)

if (T==NULL)

T=(BiTNode *)malloc(sizeof(BiTNode));
T->data=k;
T->left=T->right=NULL;
return 1;

else if (k==T->data)
return 0;
else if (k<T->data)
return InsertBST(T->left,k);
else
return InsertBST(T->right,k);

BiTNode *CreatBST(int A[],int n)

BiTNode *bt=NULL;
int i=0;
while (i<n)

InsertBST(bt,A[i]);
i++;

return bt;


void search(BiTNode *T)//查找结点

int x,count=0;
cin>>x;
while(T!=NULL)

if(T->data==x)

count++;break;

else if(x<T->data)

T=T->left;

else

T=T->right;


if(count>0)

cout<<"查找到该元素。"<<endl;

else

cout<<"不存在该元素。"<<endl;


int ELEM(int A[])

int i;
for(i=0;elem[i]!=0;i++);
return i;

void del(BiTNode *T)

int x,i=0,j=-1;
cin>>x;
for(i;elem[i]!=0;i++)

if(elem[i]==x)

j=i;break;


if(j>=0)

for(j;elem[j]!=0;j++)

elem[j]=elem[j+1];

cout<<"删除成功。"<<endl;

else

cout<<"删除元素不存在。"<<endl;



void preorderl(BiTNode T) //不用递归,先序遍历以Tree为根指针的二叉树

SeqStack s;
s.top= -1;
while(T||s.top!= -1) //当前处理的子树不为空或栈不为空则循环

while(T)
printf(“%c”,T->data);
s.top++;
s.data[s.top]=T;
T=T->left;

If(s.top>-1)
T=pop(&s);
T=T->right;




/*
2、用递归方法分别先序、中序、后序遍历以Tree为根指针的二叉树。
3、编写递归算法,计算二叉树中叶子结点的数目。
4、编写递归算法,计算二叉树的深度。
5、编写递归算法,将二叉树中所有结点的左、右子树相互交换。
6、使用数组elem中的随机数序列(以0表示结束,不包括0),生成以Tree为根指针的二叉排序树。
7、在以Tree为根指针的二叉排序树中查找结点。
8、从以Tree为根指针的二叉排序树中删除结点(适用各种位置的结点)。
9、不用递归,先序遍历以Tree为根指针的二叉树。
提示:用数组 BiTNode *stack[max] 构成堆栈,利用这个堆栈实现功能。
10、用凹入表示法的表示以Tree为根指针的二叉树,例如:
// 324
// 123
// 746
// 690
// 567
11、用广义表表示以Tree为根指针的二叉树,例如
// (324(123(746(),()),(690(),())),(567(),()))
12、对以Tree为根指针的二叉树,从根结点开始,逐层从左到右输出各结点的数据。
提示:用数组 BiTNode *queue[max] 构成队列,利用这个队列实现功能
提高题:

13*、根据Huffman编码原理,使用数组elem中的随机数序列(以0表示结束,不包括0)作为结点的权重,生成赫夫曼树,以及赫夫曼编码,计算平均带权径长度。
14*、(1)随机生成二叉树。 (2)生成并保存先(后)序、中序输出序列。 (3)按照保存的一对输出序列恢复出二叉树。(4)生成先(后)序输出序列。
*/
参考技术A 推荐你看下严蔚敏的数据结构,上面的算法都有。

二叉树的操作

二叉树的比较与相加

二叉树的克隆操作
克隆操作就是将当前的二叉树复制一份出来,其复制接口的返回值为堆空间中的一颗新二叉树,这个二叉树的地址是不一样的,但是这颗树的其他属性和数据元素在对应位置都是相当的,接口的定义如下所示

sharedPointer <BTree<T>> clone()const

设计思路
在堆空间里面先创建一个二叉树结点出来,然后把数据元素复制到新创建的二叉树结点中,接下来就递归的克隆左子树和右子树,然后指定左右子树的父亲,也就是新创建出来的结点,递归公式如下

             return NULL;                     node == NULL
clone(node)
             n = NewNode();
             n->value = node->value;
             n->left  = clone(node->left);    node != NULL
             n->right = clone(node->right);

代码实现

protected:
BTreeNode<T>*  clone(BTreeNode<T>* node)const

    BTreeNode<T>* ret = NULL;
    if(node!=NULL)
    
         ret = BTreeNode<T>::NewNode();
         if(ret!=NULL)
         
             ret->value = node->value;
             ret->l_pointer = clone(node->l_pointer);
             ret->r_pointer = clone(node->r_pointer);
             if(ret->l_pointer!=NULL)
             
                ret->l_pointer->parent = ret;
             
             if(ret->r_pointer!=NULL)
             
                ret->r_pointer->parent = ret;
             
         
         else
         
           THROW_EXCEPTION(NoEnougMemoryException,"No EnoungMemory");
         
    
    return ret;

public:
SharedPointer < BTree<T> > clone()const

    BTree<T>* ret = new BTree<T>();
    if(ret!=NULL)
    
        ret->m_root = clone(root());
    
    else
    
        THROW_EXCEPTION(NoEnougMemoryException,"No enoug memory to malloc");
    
   return ret;

二叉树比较操作

二叉树比较操作就是判断两个二叉树中的数据元素是否对应相等,就是两个树的根节点数据元素,左子树,右子树对应相等,因为引入了比较操作,所以我们得重载比较操作符,可以看出比较也是一个递归调用的过程,递归公式如下所示

                 return true;          lh==rh
                 return false;         lh == 0&& rh!=0
                 retunr false;         lh != 0&& rh==0
equal(rh,lh)
                 lh->value==rh->value&&
                 equal(lh->left,rh->left)&&   lh!=0&&rh!=0
                 equal(lh->right,rg->right)

代码:

protected:
bool operator ==(const BTree<T>* btree)

    return equal(this->root(),btree->root());

bool operator !=(const BTree<T>* btree)

    return !(this==btree);

public:
bool equal(BTreeNode<T>* lh,BTreeNode<T>* rh)

    if(lh==rh)
    
        return true;
    
    else if((lh!=NULL)&&(rh!=NULL))
    
        return (lh->value==rh->value)&&equal(lh->l_pointer,rh->l_pointer)&&equal(lh->r_pointer,rh->r_pointer);
    
    else
    
         return false;
    

二叉树的相加操作

相加操作就是将当前二叉树与参数btree中的数据元素在对应位置处相加,返回值为堆空间中的一颗新二叉树,当然对于二叉树来说它还有一些特殊的结点,比如上图中的2号结点,6号结点相加操作,需要将2号结点的左子树赋值结果二叉树对应结点的左子树,同样的道理2号结点的右子树也是同样的操作,将lh为根节点的二叉树与递归公式如下所示

             clone(rh)                            lh==0&&rh!=0
           
add(lh,rh)   clone(lh)                            lh!=0&&rh==0
             
             n =  NewNode();
             n->value = lh->value + rh->value;
             n->left  = add(lh->left,rh->left);   lh!=0&&rh!=0
             n->right = add(lh->right,rh->rigth);

代码


  protected:
  BTreeNode<T>* add(BTreeNode<T>* lh,BTreeNode<T>* rh)
  
      BTreeNode<T>* ret = NULL;
      if((lh!=NULL)&&(rh==NULL))
      
          ret = clone(lh);
      
      else if((lh==NULL)&&(rh!=NULL))
      
          ret =  clone(rh);
      
      else if((lh!=NULL)&&(rh!=NULL))
      
          ret = BTreeNode<T>::NewNode();
          if(ret!=NULL)
          
              ret->value        = lh->value+rh->value;
              ret->l_pointer    = add(lh->l_pointer,rh->l_pointer);
              ret->r_pointer    = add(lh->r_pointer,rh->r_pointer);
              if(ret->l_pointer!=NULL)
              
                 ret->l_pointer->parent = ret;
              
              if(ret->r_pointer!=NULL)
              
                 ret->r_pointer->parent = ret;
              
          
          else
          
              THROW_EXCEPTION(NoEnougMemoryException,"no EnougMemory Exception");
          
      
      return ret;
  
  public:
  SharedPointer < BTree<T> > add(const BTree<T>& btree)
 
      BTree<T>* ret = new BTree<T>();
      if(ret!=NULL)
      
          ret->m_root = add(root(),btree.root());
      
      else
      
          THROW_EXCEPTION(NoEnougMemoryException,"no EnougMemory.....");
      
      return ret;
  

实验代码

int main()

  BTree<int> bt;
  BTreeNode<int>* n = NULL;
  bt.insert(1,NULL);

  n = bt.find(1);
  bt.insert(2,n);
  bt.insert(3,n);


  n = bt.find(2);
  bt.insert(4,n);
  bt.insert(5,n);

  n = bt.find(4);
  bt.insert(8,n);
  bt.insert(9,n);

  n = bt.find(5);
  bt.insert(10,n);

  n=bt.find(3);
  bt.insert(6,n);
  bt.insert(7,n);
  SharedPointer < BTree<int> > clonenode   = bt.clone();
  BTree<int> nbt;
  nbt.insert(0,NULL);

  n = nbt.find(0);
  nbt.insert(6,n);
  nbt.insert(2,n);

  n = nbt.find(2);
  nbt.insert(7,n);
  nbt.insert(8,n);

  SharedPointer < BTree<int> > r = bt.add(nbt);

  int a[] = 8,9,10,13,15;
  for(int i =0;i<5;i++)
  
      TreeNode<int>* node = r->find(a[i]);
      while(node)
      
          cout<<node->value<<" ";
          node = node->parent;
      
      cout<<endl;
  
  SharedPointer < Aarry<int> > tr = r->traversal(PreOrder);//先序遍历
  for(int i =0;i<tr->length();i++)
  
      cout<<(*tr)[i]<<" ";
  
  cout<<endl;
  //cout<<(bt==*clonenode)<<endl;

  return 0;

以上是关于二叉树操作的主要内容,如果未能解决你的问题,请参考以下文章

二叉树的相关操作

题解——二叉树的基本操作

链式二叉树的基本操作(建议收藏!!!)

数据结构二叉树的基本操作~~~~

二叉树的基本运算

二叉树的操作