考研复试系列——第三节 二叉树&二叉排序树
前言
二叉树是非常重要的一个概念,也是复试中经常考察的内容,对于二叉树的各种遍历我们都需要熟练的掌握,并在此基础上
解决一系列的问题。
基础知识
首先我们要学会二叉树的构造,在C++中常常使用类来实现二叉树的定义,这里举个例子。
/*给定一棵用链表表示的二叉树,求二叉树结点数目*/
#include<iostream>
using namespace std;
typedef char datatype;
typedef struct node
{
datatype data;
struct node *lchild; //左孩子指针
struct node *rchild; //右孩子指针
}Binnode,*Bintree;
void createBintree(Bintree &btree) //创建一颗二叉树,以'?'结束,空节点为'#'
{ //如输入ABC##DE##G##F###?即表示建立了一颗二叉树,其节点数目为7
datatype item;
cin>>item;
if(item=='?')
return;
if(item!='#')
{
btree=new Binnode;
if(btree==NULL)
{
cerr<<"存储分配失败!"<<endl;
exit(1);
}
btree->data=item;
createBintree(btree->lchild); //递归建立左子树
createBintree(btree->rchild); //递归建立右子树
}
else
btree=NULL;
}
int count=0; //记录节点的个数
void heightBintree(Bintree &btree)
{
if(btree!=NULL)
{
count++;
heightBintree(btree->lchild);
heightBintree(btree->rchild);
}
}
int main()
{
Bintree tree;
cout<<"请输入要创建的树的序列:"<<endl;
createBintree(tree);
heightBintree(tree);
cout<<"二叉树的节点数为:"<<count<<endl;
return 0;
}
关于二叉树的各种遍历这里不再累牍,在下面的例题中会有所体现。
二叉树例题
输入:两个字符串(由字母A-Z组成,其长度n都不大于26),其中第一个字符串表示前序遍历,后一个字符串表示中序遍历。
输出:后序遍历的结果。
这道题目在王道论坛计算机考研复试上机指南上有答案,看了半天表示看的很累,于是自己写了一个,代码量多了些,但感觉
更加清楚一些。
#include<iostream>
using namespace std;
typedef char datatype;
typedef struct node
{
node *lchild;
node *rchild;
datatype data;
}Node,*Btree;
void createBtree(Btree &bTree,const char* pre,const char *mid)
{
if(pre == NULL)
return;
if(mid == NULL)
return;
if(bTree = new node)
{
bTree->data = pre[0];
bTree->lchild = NULL;
bTree->rchild = NULL;
}
char ch = pre[0];
int length = strlen(mid);
int i,leftcount = 0;
for(i=0;i<length;i++)
{
if(mid[i] == ch)
break;
leftcount++;
}
//cout<<leftcount<<endl;
char* pre_copy = NULL;
char* mid_copy = NULL;
if(leftcount != 0)
{
pre_copy = new char[leftcount+1];
mid_copy = new char[leftcount+1];
for(i=1;i<leftcount+1;i++)
pre_copy[i-1] = pre[i];
pre_copy[leftcount] = '\0';
//cout<<"left_pre"<<pre_copy<<endl;
for(i=0;i<leftcount;i++)
mid_copy[i] = mid[i];
mid_copy[leftcount] = '\0';
//cout<<"left_mid"<<mid_copy<<endl;
}
int rightcount = length - leftcount - 1;
char* right_pre = NULL;
char* right_mid = NULL;
if(rightcount != 0)
{
right_pre = new char[rightcount+1];
right_mid = new char[rightcount+1];
int j;
for(i=leftcount+1,j=0;i<length;i++)
right_pre[j++] = pre[i];
right_pre[rightcount] = '\0';
//cout<<"right_pre:"<<right_pre<<endl;
for(i=leftcount+1,j=0;i<length;i++)
right_mid[j++] = mid[i];
right_mid[rightcount] = '\0';
//cout<<"right_mid:"<<right_mid<<endl;
}
createBtree(bTree->lchild,pre_copy,mid_copy);
createBtree(bTree->rchild,right_pre,right_mid);
}
void preorder(Btree &bTree) //前序遍历
{
if(bTree == NULL)
return;
cout<<bTree->data<<" ";
preorder(bTree->lchild);
preorder(bTree->rchild);
}
void midorder(Btree &bTree) //中序遍历
{
if(bTree == NULL)
return;
midorder(bTree->lchild);
cout<<bTree->data<<" ";
midorder(bTree->rchild);
}
void lastorder(Btree &bTree) //后序遍历
{
if(bTree == NULL)
return;
lastorder(bTree->lchild);
lastorder(bTree->rchild);
cout<<bTree->data<<" ";
}
int main()
{
char pre[27] = {"XDAGFE\0"};
char mid[27] = {"ADGXFE\0"};
//char pre[27] = {"ABCDE\0"}; //test sample
//char mid[27] = {"CBDAE\0"};
Btree bTree;
createBtree(bTree,pre,mid);
preorder(bTree);
cout<<endl;
midorder(bTree);
cout<<endl;
lastorder(bTree);
cout<<endl;
return 0;
}
这道题目还是很不错的 结合了二叉树的构造以及遍历,以此为基础,常常考察判断二叉树的深度,叶节点个数等等的问题。但是掌握了构造和遍历其它问题都很容易解决。
对于遍历还需要掌握非递归的算法。
二叉排序树
二叉排序树的构造要比二叉树简单的多,这里直接给出一道题目:
输入一行包括一个整数n (1<=n<=100) 接下来一行包括n个整数,由此建立一颗二叉排序树。并对其进行中序遍历。
(注意:输入元素可有重复的 但输出不要输出重复的元素)
#include<iostream>
using namespace std;
typedef int datatype;
typedef struct node
{
node *lchild;
node *rchild;
datatype data;
}Bsnode,*Bstree;
void insertBstree(Bstree &bsTree,const datatype data)
{
if(bsTree == NULL)
{
bsTree = new Bsnode;
bsTree->data = data;
bsTree->lchild = NULL;
bsTree->rchild = NULL;
return;
}
Bsnode *node = new Bsnode;
node->data = data;
node->lchild = NULL;
node->rchild = NULL;
Bsnode *p = bsTree;
while(true)
{
if(data >= p->data && p->rchild == NULL)
{
p->rchild = node;
break;
}
else if(data >= p->data && p->rchild != NULL)
p = p->rchild;
else if(data < p->data && p->lchild == NULL)
{
p->lchild = node;
break;
}
else if(data < p->data && p->lchild !=NULL)
p = p->lchild;
}
}
void midorder(Bstree &bsTree,const datatype cmp) //中序遍历
{
if(bsTree == NULL)
return;
midorder(bsTree->lchild,cmp);
if(bsTree->data != cmp)//判断是否以及输出过
cout<<bsTree->data<<" ";
midorder(bsTree->rchild,bsTree->data);
}
int main()
{
int n;
cin>>n;
int i;
Bstree bsTree = NULL;
for(i=0;i<n;i++)
{
datatype data;
cin>>data;
insertBstree(bsTree,data);
}
midorder(bsTree,-1);
return 0;
}