整理了一下关于二叉树的各种操作,为了方便直接全程使用排序二叉树。
涉及到的有如下的几种功能:
1、定义二叉树数据结构;
2、由前序遍历及中序遍历构造二叉树;
3、将一组数构造成二叉搜索树;
4、求二叉树的高度;
5、查找某个结点的递归与非递归实现;
6、在指定位置插入的实现(递归与非递归);
7、寻找最大、最小结点的递归与非递归实现;
8、删除指定结点;
首先是定义相应的数据结构类型,此处结合struct和class来实现。
一开始定义的typedef int T;
可以方便地对数据类型进行修改。
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef int T;
typedef struct treenode
{
T value;
treenode *left,*right;
}treenode;
static treenode* build_node(T value) //创建结点
{
treenode* tree=new treenode;
tree->value=value;
tree->left=NULL;
tree->right=NULL;
return tree;
}
class Btree
{
static int n,m;
public:
Btree()
{
root=NULL;
}
void creat_Bsearch_tree(T x); //建立二叉查找树;
T GetHeight(); //求树高;
protected:
T GetHeight(treenode*);
private:
treenode* root;
};
之后是由已知数组直接构造二叉搜索树的操作以及求树的高度。
void Btree::creat_Bsearch_tree(T x) //建立排序二叉树 规则是
{
treenode *newnode=new treenode;
newnode->value=x;
newnode->left=NULL;
newnode->right=NULL;
if(root=NULL)
{
root=newnode;
}
else
{
treenode *back,*current=root;
while(current!=NULL)
{
back=current;
if(current->value>x)
{
current=current->left;
}
else
{
current=current->right;
}
}
if(back->value>x)
{
back->left=newnode;
}
else
{
back->right=newnode;
}
}
}
T Btree::GetHeight(treenode* tree) //求二叉树的高度
{
if(tree==0) return 0;
else
{
int l_h=GetHeight(tree->left);
int r_h=GetHeight(tree->right);
return (l_h>r_h) ? l_h+1:r_h+1;
}
}
然后是由先序遍历以及中序遍历序列来构造二叉树。
//由先序遍历及中序遍历建立二叉树
treenode* fm_creat_Btree(T preOrder[],T p_l,T p_r,T inOrder[],T i_l,T i_r)
{
if((p_r-p_l)!=(i_r-i_l)||p_r<p_l)
{
return NULL; //当两个遍历序列长度不一或始位置大于末位置时
}
//第一个元素是先序遍历的第一个元素,是根结点
treenode* tree=(treenode*)malloc(sizeof(treenode));
tree->value=preOrder[p_l];
tree->left=NULL;
tree->right=NULL;
if(p_l==p_r)
{
return tree; //显然是只有一个点的树
}
//在中序遍历中寻找根结点
T itemp;
for(itemp=i_l;itemp<=i_r;itemp++)
{
if(inOrder[itemp]==preOrder[p_l])
{
break;
}
}
if(itemp>i_r)
{
return NULL; //找不到的情况
}
T length;
if(itemp>i_l) //有左叶子时,递归调用
{
length=itemp-i_l;
tree->left=fm_creat_Btree(preOrder,p_l+1,p_l+length,inOrder,i_l,i_l+length-1);
}
if(itemp<i_r) //有右叶子时,递归调用
{
length=i_r-itemp;
tree->right=fm_creat_Btree(preOrder,p_r-length+1,p_r,inOrder,i_r-length+1,i_r);
}
return tree;
}
之后是分别采用递归或非递归思想来实现的查找、插入。
treenode* re_search(treenode* tree,T x) //查找关键字为x的结点(递归)
{
if(tree->value==x)
{
return tree;
}
else if(tree->value>x)
{
if(tree->left!=NULL)
{
return re_search(tree->left,x);
}
else
{
return NULL;
}
}
else if(tree->value<x)
{
if(tree->right!=NULL)
{
return re_search(tree->right,x);
}
else
{
return NULL;
}
}
}
treenode* search(treenode* tree,T x) //查找关键字为x的结点(非递归)
{
if(!tree)
{
return NULL;
}
treenode* p=tree;
while(p)
{
if(p->value<x)
{
p=p->right;
}
else if(p->value>x)
{
p=p->left;
}
return p;
}
return NULL;
}
treenode* re_BSTinsert(treenode* tree,T x) //排序二叉树的插入(递归)
{
if(!tree)
{
return build_node(x);
}
if(tree->value>x)
{
tree->left=re_BSTinsert(tree->left,x);
}
else
{
tree->right=re_BSTinsert(tree->right,x);
}
return tree;
}
treenode* BSTinsert(treenode* tree,T x) //排序二叉树的插入(非递归)
{
treenode* p;
treenode* p_f; //p_f为待插入结点的父结点
p=tree;
p_f=NULL;
while(p)
{
p_f=p;
if(p->value<x)
{
p=p->right;
}
else
{
p=p->left;
}
if(tree==NULL)
{
tree=build_node(x);
return tree;
}
else
{
if(p_f->value<x)
{
p_f->right=build_node(x);
}
else
{
p_f->left=build_node(x);
}
return tree;
}
}
}
treenode* re_findmax(treenode* tree) //寻找最大结点(递归)
{
if(tree->right==NULL)
{
return tree;
}
else
{
re_findmax(tree->right);
}
}
treenode* findmax(treenode* tree) //寻找最大结点(非递归)
{
treenode* p;
p=tree;
while(p->right)
{
p=p->right;
}
return p;
}
treenode* re_findmin(treenode* tree) //寻找最小结点(递归)
{
if(tree->left==NULL)
{
return tree;
}
else
{
re_findmin(tree->left);
}
}
treenode* findmin(treenode* tree) //寻找最小结点(非递归)
{
treenode* p;
p=tree;
while(p->left)
{
p=p->left;
}
return p;
}
最后是删除的操作。
treenode* remove(treenode* tree,T x) //删除指定结点
{
if(!tree)
{
return NULL;
}
treenode* back;
if(x==tree->value)
{
if(tree->left==NULL) //没有左子树的情况
{
back=tree;
tree=tree->right;
delete back;
}
else if(tree->right==NULL) //没有右子树的情况
{
back=tree;
tree=tree->left;
delete back;
}
else //寻找前驱替代(有左右子树)
{
treenode* temp;
temp=findmax(tree->left);
tree->value=temp->value;
remove(tree->left,temp->value);
}
}
else if(x<tree->value) //递归调用以查找
{
remove(tree->left,x);
}
else if(x>tree->value)
{
remove(tree->right,x);
}
}
总结后发现在对于二叉树的操作中,不止一次地需要领会理解递归,这也和二叉树在此处采用了单链表的存储方式有莫大的关系。