5.二叉树

本文介绍了一个程序,用于实现二叉树的构建、遍历、线索化等操作。包括利用先序和中序遍历序列构建二叉树、二叉树节点数量及叶子节点数量的计算、二叉树的后序遍历(递归与非递归)、层次遍历及转换为一维数组,最后完成了二叉树的中序线索化及其遍历。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、编写一个程序,实现由先序遍历序列和中序遍历序列构造一棵二叉树
先序序列:A B D M R N S C E P G Q F H T J
中序序列:R M D N S B A P E Q G C H T F J
要求:
1. 用凹入表示法输出该二叉树。其中二叉树用二叉链表结构存储。
2. 用递归算法实现对此二叉树各结点的后序遍历。
3. 用非递归算法实现对此二叉树各结点的后序遍历。

注意:根据这两个序列构造二叉树来验证程序,后面的题目用到的二叉树均用这个二叉树来验证。
注释:凹入表示法输出, 比如给定一棵二叉树
       a
       / /
     b   c
    /  /  /  /
  d   e f  g
凹入表示法输出结果为:
a
   b
      d
      e
   c
      f
      g

二、设计将二叉链表存储的二叉树转换为一维数组结构的算法,并输出这个数组,空值则用‘*’代替。并以第一题中实验数据来验证。
例如给定一棵二叉树
   a
  /   /
b     c
/        /
d        f
输出: a b c d * * f
 

三、以第一题的实验数据来验证完成下列问题:
1. 求一二叉链表存储的二叉树的结点个数,并输出。
2. 求一二叉链表存储的二叉树的叶结点个数,并输出。

四、编写一个程序,实现对一棵给定二叉链表结构存储的二叉树中序线索化,并完成该线索化二叉树遍历的算法。以第一题的实验数据来验证。

#include <iostream>
#include <string>
using namespace std;
//******************************
//结点
struct Binary_node

 Binary_node();
 char data;
 Binary_node *left;
 Binary_node *right;
 int f_left;
 int f_right;
};
Binary_node::Binary_node()
{
f_left=0;
f_right=0;
left=NULL;
right=NULL;
}
//***************************************
//这个栈用来存放Binary_node型数据
const int maxstack = 30; 
class Stack
{
public:
   Stack();
   bool empty() const;
   Binary_node pop();
   Binary_node gettop();
   void push(const Binary_node &item);
private:
   friend class Binary_tree;
   int count;
   Binary_node entry[maxstack];
};
void Stack::push(const Binary_node &item)
{
 if(count>=maxstack)
  cout<<"overflow "<<endl;
 else
  entry[count++]=item;
}
Binary_node Stack::pop()
{
 Binary_node item;
  if(count==0)
  { 
  
      return item;
  }
  else
  {
   item=entry[count-1];
      --count;
      return item;
  }
}
Binary_node Stack::gettop()
{
 Binary_node item;
  if(count==0)
  {
   item.data='/0';
  
  }
  else
  {
   item=entry[count-1];     
  }
  return item;
 }
bool Stack::empty() const
{
  bool outcome=true;
  if(count>0)
  outcome=false;
  return outcome;
}
Stack::Stack()
{
count=0;
}
//*********************************************
//这个栈用来存放int型数据
const int maxstack1 = 100; 
class IntStack
{
public:
   IntStack();
   bool empty() const;
   int pop();
   int gettop();
   void push(const int &item);
private:
   friend class Binary_tree;
   int count;
   int entry[maxstack1];
};
void IntStack::push(const int &item)
{
 if(count>=maxstack)
  cout<<"overflow "<<endl;
 else
  entry[count++]=item;
}
int IntStack::pop()
{
 int item;
  if(count==0)
  { 
   item=-1;
      return item;
  }
  else
  {
   item=entry[count-1];
      --count;
      return item;
  }
}
int IntStack::gettop()
{
 int item;
  if(count==0)
  {
   item=-1;
  }
  else
  {
   item=entry[count-1];     
  }
  return item;
 }
bool IntStack::empty() const
{
  bool outcome=true;
  if(count>0)
  outcome=false;
  return outcome;
}
IntStack::IntStack()
{
   count=0;
}
//***********************************************
//队列
#define max_queue 50
class Queue
{
public:
 Queue():current(0),first(0){}
 bool empty() const;
 bool full() const;
 Binary_node* append(Binary_node *sub_root);                        
 Binary_node* serve();                                              
protected:
 Binary_node* workspace[max_queue];
 int current, first;
};

bool Queue::empty() const
{
 bool outcome = true;
 if (current>0)
  outcome = false;
 else
  cout<<"empty queue"<<endl;
 return outcome;
}
bool Queue::full()const
{
 return current==max_queue;
}
Binary_node* Queue::append(Binary_node *sub_root)//入队
{
 if (full())
 {
  return NULL;
 }
 workspace[current]=sub_root;
 current++;
 return sub_root;
}
Binary_node* Queue::serve()       //出队
{
 if (empty())
 {
  return NULL;
 }
 Binary_node *sub_root;
 sub_root = workspace[first];
 first++;
 return sub_root;
}
//***********************************************
//二叉树
class Binary_tree
{
public:
 Binary_tree(){}
 Binary_node* createtree(char *pre,char *in);                                  //用先序遍历序列和中序创遍历序列建二叉树
    int countsize(Binary_node *sub_root);                                         //输出所有结点个数
 int leaf_countsize(Binary_node *sub_root);                                    //输出叶子节点个数
 void postorder(Binary_node *sub_root) const;                                  //后序递归遍历
 void levelorder(Binary_node *sub_root, int sheight) const;                    //层次遍历,将二叉树转换为一维数组结构
 void showtree(Binary_node* sub_root,int depth);                               //凹入表示法输出
 int height(Binary_node* sub_root) const;                                      //树的深度
    void postorder_norecursion(Binary_node *sub_root);                            //后序非递归遍历

protected:
 Binary_node *createNode(char &c);                                             //建立新结点
 int searchchar(char &c,char *order);                                          //找先序第一个元素在中序中的位置
};
Binary_node* Binary_tree::createNode(char &ch)                 //初始化结点
{
 Binary_node *n=new Binary_node;
 n->data=ch;
 n->left=NULL;
 n->right=NULL;
 return n;
}
int Binary_tree::searchchar(char &ch,char *order)              //找先序第一个元素在中序中的位置
{
 for(unsigned int i=0;i<strlen(order);i++)
 {
  if(ch==order[i])
   return i;
 }
 return -1;
}

Binary_node* Binary_tree::createtree(char *pre,char *in)         //用先序遍历序列和中序创遍历序列建二叉树
{
 char ch=pre[0];
 char temppre[100];
 char tempin[100];
 char *p;
 int i=0;
 Binary_node* bnode;
 if(pre=='/0')
  return NULL;


 for (int ix=0;ix!=100;ix++)                                      //初始化tempin
 {
  tempin[ix]='/0';
 }
 for (int ix=0;ix!=100;ix++)                                       //初始化temppre
 {
  temppre[ix]='/0';
 }

 bnode=createNode(ch);                                              //初始化结点
 i=searchchar(pre[0],in);                                           //找先序第一个元素在中序中的位置,划分左右子树
 if(i==-1)
  return 0;
 p=in;
 strncpy_s(tempin,p,i);                                                  //将in的前i个元素赋给tempin
 p=pre;
 strncpy_s(temppre,p+1,i);
 bnode->left=createtree(temppre,tempin);                                                //左子树
 for (int ix=0;ix!=100;ix++)
 {
  tempin[ix]='/0';
 }
 for (int ix=0;ix!=100;ix++)
 {
  temppre[ix]='/0';
 }
 p=in+i+1;
 strncpy_s(tempin,p,strlen(in)-i);
 p=pre+i+1;
 strncpy_s(temppre,p,strlen(in)-i);
 bnode->right=createtree(temppre,tempin);                                                //右子树
 return bnode;
}
void Binary_tree::showtree(Binary_node* sub_root,int depth)                         //凹入表示法输出
{
 if(sub_root!=NULL)
 {
  for (int i=0; i<depth+1; i++)
  {
   cout<<" ";                                                              //输出空格
  }
  cout<<sub_root->data<<endl;
  showtree(sub_root->left, depth+1);
  showtree(sub_root->right, depth+1);
 }
}

void Binary_tree::postorder(Binary_node *sub_root) const                         //后续递归遍历
{
 if ( sub_root!=NULL){
  postorder(sub_root->left);                                               // 遍历左子树
  postorder(sub_root->right);                                              // 遍历右子树
  cout<<sub_root->data<<" ";
 }
}

void Binary_tree::postorder_norecursion(Binary_node *sub_root)                  //后序非递归遍历
                                      //标志栈中  0表示结点暂时不访问
           //1表示结点可以访问
{
  
            Stack stackForNode;                       //存储结点          
            IntStack stackForTag;                      //存储标志

   stackForNode.push(*sub_root);
   stackForTag.push(0);

   Binary_node *tempNode= sub_root->left;

   while (tempNode!=NULL|| stackForNode.empty()!= true)
            {
    while (tempNode!=NULL)
                {
                    stackForNode.push(*tempNode);
                    stackForTag.push(0);

     tempNode= tempNode->left;
                }

    while (stackForNode.empty()!= true && stackForTag.gettop() == 1)
                {
                    stackForTag.pop();
     cout<<stackForNode.pop().data<<" ";
                  
                }

    if (stackForNode.empty() != true)
                {
     stackForTag.pop();
     stackForTag.push(1);

     tempNode = stackForNode.gettop().right;
                }
            }
}
                         //第二题

void Binary_tree::levelorder(Binary_node *sub_root, int sheight) const  //层次遍历,将二叉树转换为一维数组结构
{
 
 
 Queue que;
 Binary_node *p;
 que.append(sub_root);                            
 for(int i=-1; i!=sheight+1;++i)                    // 继续进行以下处理,直到队列为空
 {
  p = que.serve();                               // 出队列
  if (p->data!='0')
  {
   cout<<p->data<<" ";                        // 访问结点
  }
  else
   cout<<"* ";
  if (p->left !=NULL)
   que.append( p->left);                      //左孩子入队
  else
  {
   Binary_node *n1 = new Binary_node;
   n1->data = '0';
   que.append(n1);
  }
  if (p->right!=NULL)
  {
   que.append(p->right);                      //右孩子入队
  }
  else
  {
   Binary_node *n2 = new Binary_node;
   n2->data = '0';
   que.append(n2);
  }
 }
}
int Binary_tree::height(Binary_node* sub_root) const
{
 int lheight = 0,rheight = 0,sheight = 0;
 if (sub_root == NULL)
  sheight = 0;
 else
 {
  lheight = height(sub_root->left);                                    // 计算左子树深度
  rheight = height(sub_root->right);                                   // 计算右子树深度
  sheight = 1+(lheight>rheight ? lheight:rheight);                     //取较大者
 }
 return sheight;
}
int Binary_tree::countsize(Binary_node* sub_root)   //计算结点数            第三题(a)
{
 int ileft = 0,iright = 0,count = 0;
 if(sub_root == NULL)
  count = 0;
 else
 {
  ileft = countsize(sub_root->left);                          
  iright = countsize(sub_root->right);
  count = ileft + iright + 1;
 }
 return count;
}
int Binary_tree::leaf_countsize(Binary_node* sub_root)            //计算叶子节点数   第三题(b)
{  
 int count;
 if(sub_root==NULL)
 {
  count=0;
 }
 else if((sub_root->left==NULL)&&(sub_root->right==NULL))                       //叶子节点
 {
  count=1;
 }
 else
  count=leaf_countsize(sub_root->left)+leaf_countsize(sub_root->right);
 return count;
}
//*********************************************Thread_tree 类                   第四题

class Thread_tree
{
public:
 Thread_tree():pre(NULL){}
 Binary_node* inthrRealize();                                            //线索化二叉树
 void thread_inorder(Binary_node* current);                              //中序线索化
 void in_thr_travel(Binary_node* head) ;                                 //线索化二叉树的中序遍历
 Binary_node *root;
protected:
 Binary_node *pre;                                                     
};

Binary_node* Thread_tree::inthrRealize()                                    //线索化二叉树
{
 Binary_node* head = new Binary_node;
 head->f_left = head->f_right = 1;
 if(root == NULL)
 {
  head->left = head;
  head->right = head;
 }
 else
 {
  head->left = root;
  head->f_left = 0;
  thread_inorder(root);
  pre->right = head;
  pre->f_right = 1;
  head->right = pre;
 }
 return head;
}

void Thread_tree::thread_inorder(Binary_node* current)
{
 if(current != NULL)
 {
  thread_inorder(current->left);                   // 左子树线索化
  if(current->left == NULL)
  {                                               
   current->left = pre;
   current->f_left = 1;
  }
  if(pre != NULL)
   if (pre->right == NULL)
   {                                             
    pre->right = current;
    pre->f_right = 1;
   } 
   pre = current;                               
   thread_inorder(current->right);                 // 右子树线索化
 }
}

void Thread_tree::in_thr_travel(Binary_node* head)                          //线索化二叉树的中序遍历
{
 Binary_node* current;
 current = head->left;
 while(current != head)
 {
  while(current->f_left == 0)
   current=current->left;
  cout<<current->data;
  while(current->f_right == 1 && current->right != head)
  {
   current = current->right;
   cout << current->data;
  }
  current = current->right;
 }
}


int main()
{
 Binary_tree tree;
 Binary_node* root;
 char pre_order[100];
 char in_order[100];
 cout<<"第一题"<<endl;
 cout<<"请输入前序序列:";
 cin>>pre_order;
 cout<<"请输入中序序列: ";
 cin>>in_order;
 root = tree.createtree(pre_order,in_order);
 cout<<endl;
 tree.showtree(root,-1);
 cout<<endl;
 cout<<"递归方法后序遍历的结果为: ";
 tree.postorder(root);
    cout<<endl;
    cout<<"非递归方法后序遍历的结果为: ";
 tree.postorder_norecursion(root);
 cout<<endl;
 cout<<endl;
 cout<<"第二题"<<endl;
 int isize;
 isize=tree.height(root);
    tree.levelorder(root,isize);
 cout<<endl;
    cout<<endl;
 cout<<"第三题"<<endl;
 int number,leaf_number;
    number=tree.countsize(root);
 leaf_number=tree.leaf_countsize(root);
 cout<<"BiTree中结点个数为 "<<number<<", 叶节点个数为 "<<leaf_number<<endl;
 cout<<endl;

 cout<<"第四题"<<endl;
 Thread_tree *Ttree = new Thread_tree;
 Ttree->root=root;
 Binary_node* head = Ttree->inthrRealize();
 cout << "二叉树中序线索化遍历结果:";
 Ttree->in_thr_travel(head);
 cout<<endl;
 delete Ttree;
 return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值