二叉树的构建与遍历,二叉树元素的排序
程序员文章站
2022-05-13 19:32:45
...
构建二叉树 , 定义一个节点空间 , 一个数据域 , 和左右节点域 , 并先序遍历一次树 .
#include<iostream>
using namespace std;
//前置声明
class tree;
//节点:
class node
{
public:
friend class tree;
node(char);
protected:
char data;//数据域
node* lchild;//指向左孩子
node* rchild;//指向右孩子
};
node::node(char d):data(d),lchild(NULL),rchild(NULL)
{
}
//构造树
class tree
{
public:
tree();
bool createTree(char*&,node*&);//地址 地址变量引用
node*& getRoot();//定义公有接口
//遍历 前序 中序 后序
//前序
void preOrder(node*);
//void inOrder(); //中序
//void postOrder(); //后序
protected:
node* root; //根节点---堆区
};
//前序遍历
void tree::preOrder(node* ploc)
{
if(NULL==ploc)
return;
cout<<ploc->data<<" ";
preOrder(ploc->lchild);
preOrder(ploc->rchild);
}
node*& tree::getRoot()
{
return this->root;
}
tree::tree():root(NULL)
{
}
//前序创建树
bool tree::createTree(char*& d,node* & ploc) //为什么不能用 char d[] 来传递树的数据?
{
if('\0'==*d)
return true; //递归需要停止的条件,当遇到'\0'的时候停止
//分配节点
if('#'==*d) //当传递过来的是'#' 元素,则将子节点赋值为NULL
ploc=NULL;
else
{
ploc=new node(*d); //new 对象---构造器分配空间 new一个节点当作根节点用,所以直接将根节点传递过来,用来root的别名,所以node* & ploc
if(NULL==ploc)
return false;
//修改指向域
createTree(++d,ploc->lchild); //通过递归来构建下一个子节点
createTree(++d,ploc->rchild);
return true;
}
}
//先序构建二叉树
void main() // a
{ // # b
char* buf="a#bc##d##"; // c d
//实例化 // # # # #
tree t;//构造器
t.createTree(buf,t.getRoot());
t.preOrder(t.getRoot()); //先序遍历
}
关于 bool tree::createTree(char*& d,node* & ploc) 的 char*& d 传递树元素的讲解 .
实现树的先序遍历 , 实现中序遍历 , 实现后序遍历 , 实现查找树的元素 , 实现修改树的元素 .
#include<iostream>
using namespace std;
//前置声明
class tree;
//节点:
class node
{
public:
friend class tree;
node(char);
protected:
char data;//数据域
node* lchild;//指向左孩子
node* rchild;//指向右孩子
};
node::node(char d):data(d),lchild(NULL),rchild(NULL){}
//树
class tree
{
public:
tree();
bool createTree(char*&,node*&);//地址 地址变量引用
node*& getRoot();//定义公有接口
//遍历 前序 中序 后序
//前序:
void preOrder(node*);//前序
void inOrder(node*);//中序
void postOrder(node*);//后序
//查找
node* find(node*,char);
node* match(char key,node* ploc);//判断ploc节点是否在存在key值
bool alter(char key,node* ploc,char vaule);//修改
protected:
node* root;//根节点---堆区
};
tree::tree():root(NULL)
{
}
//判断ploc节点是否存在key值,存在返回该节点地址 不存在则遍历查找
node* tree::match(char key,node* ploc)
{
node* result=NULL;
if(NULL==ploc)
return NULL;
if(key==ploc->data)
return ploc;
//左子树
result=match(key,ploc->lchild); //返回地址 或 NULL
if(result!=NULL)
return result;
//右子树
return match(key,ploc->rchild);
}
//修改
bool tree:: alter(char key,node* ploc,char value)
{
node* result=NULL;
result=this->match(key,ploc);
if(NULL!=result)
{
result->data=value;
return true;
}
else
return false;
}
//查找
node* tree:: find(node* ploc,char key)
{
node* result=NULL;
if(NULL==ploc)
return result;
if(ploc->data==key)
return ploc;
//左子树
if(NULL!=(result=find(ploc->lchild,key)))
return result;
//右子树
if(NULL!=(result=find(ploc->rchild,key)))
return result;
}
//前序遍历:每次调用函数时只打印当前节点信息,左子树/右子树交给下一次函数来打印
void tree::preOrder(node* ploc)
{
if(NULL==ploc)
return;
//只打印ploc节点的信息
cout<<ploc->data<<" ";
//左子树的节点
preOrder(ploc->lchild);//递归打印左子树的节点
preOrder(ploc->rchild);//递归打印右子树的节点
}
//前序创建树
bool tree::createTree(char* &d,node* &ploc)
{
if('\0'==*d)
return true;
//1分配节点空间
if('#'==*d)//当前节点为空节点
ploc=NULL;
else
{
ploc=new node(*d);//new对象---由构造器分配空间
if(NULL==ploc)
return false;
//2修改指针向域
createTree(++d,ploc->lchild);//当前节点的左子树
createTree(++d,ploc->rchild);//当前节点的右子树
return true;
}
}
void tree:: postOrder(node* ploc)//后序
{
if(NULL==ploc)
return;
//遍历左子树
postOrder(ploc->lchild);
//遍历右子树
postOrder(ploc->rchild);
//访问当前节点
cout<<ploc->data<<" ";
}
void tree::inOrder(node* ploc)
{
if(NULL==ploc)
return;
//遍历左子树
inOrder(ploc->lchild);
//打印当前节点
cout<<ploc->data<<" ";
//遍历右子树
inOrder(ploc->rchild);
}
node* &tree::getRoot()
{
return this->root;
}
int main()
{
char *buf="a#bc##d##";
//实例化
tree t;//构造器
t.createTree(buf,t.getRoot());
t.preOrder(t.getRoot());
cout<<endl;
t.inOrder(t.getRoot());
cout<<endl;
t.postOrder(t.getRoot());
cout<<endl;
if(NULL!=t.match('c',t.getRoot()))
cout<<"查找成功"<<endl;
else
cout<<"查找失败"<<endl;
t.alter('c',t.getRoot(),'Y');
t.preOrder(t.getRoot());
cout<<endl;
}
二叉树的查找,插入,中序遍历排序 .
#include<iostream>
using namespace std;
template<typename T1>
class sortTree;
//根的类型
template<typename T>
class node
{
public:
//有参构造
node(T);
//友元类
friend class sortTree<T>;
protected:
T data; //数据域
node* lchild;//左孩子
node* rchild;//右孩子
};
//有参构造
template<typename T>
node<T>::node(T k):data(k),lchild(NULL),rchild(NULL)
{
}
template<typename T1>
class sortTree
{
public:
sortTree();
sortTree(T1*,int);
//定义接口:查找指定插入位置
bool SearchTN(node<T1>* ploc,node<T1>** pos,int key,node<T1>*);
//插入节点
bool InsertTN(int key,node<T1>* ploc);
//中序
void inOrder(node<T1>* ploc);
//接口
node<T1>* getRoot();
protected:
//根节点
node<T1>* root;
};
//构造函数
template<typename T1>
sortTree<T1>::sortTree(T1* data,int ilen):root(NULL)
{
int i=0;
while(i<ilen)
{
//cout<<*(data+i)<<endl;
this->InsertTN(*(data+i),this->root);//构造成排序树
i++;
}
}
template<typename T1>
//无参构造
sortTree<T1>::sortTree():root(NULL)
{
}
//查找节点
template<typename T1>
bool sortTree<T1>::SearchTN(node<T1>* ploc,node<T1>** pos,int key,node<T1>* fn)
{
if(NULL==ploc) //查找失败
{
*pos=fn;//记录父节点地址
return false;
}
else if(key==ploc->data)//
{
*pos=ploc;//记录查找成功的地址
return true;
}
else if(key > ploc->data)//右边
return SearchTN(ploc->rchild,pos,key,ploc);
else
return SearchTN(ploc->lchild,pos,key,ploc);
}
//插入节点
template<typename T1>
bool sortTree<T1>::InsertTN(int key,node<T1>* ploc)
{
//1分配空间
node<T1>* pnew=new node<T1>(key);
if(NULL==pnew)
return false;
//2修改指向域---查找节点位置
node<T1>* pos=NULL;
if(false==this->SearchTN(this->root,&pos,key,NULL))
{
if(NULL==pos)//说明Pnew成为根节点
this->root=pnew;
else
{
if(key<pos->data)//成为左孩子
{
pos->lchild=pnew;
}
else //成为右孩子
pos->rchild=pnew;
}
return true;
}
}
template<typename T1>
void sortTree<T1>::inOrder(node<T1>* ploc)
{
if(NULL==ploc)
return ;
//左子树
inOrder(ploc->lchild);
cout<<ploc->data<<" ";
//右子树
inOrder(ploc->rchild);
}
template<typename T1>
node<T1>* sortTree<T1>:: getRoot()
{
return this->root;
}
int main()
{
//实例化:
int b[]={10,1,0,8,3,5,4,6,7,12,11,30,28,27,26};
sortTree<int> s(b,15);//有参构造
s.inOrder(s.getRoot());
}
用树构造一个带复杂类型的数据 .
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
//数量+逻辑点=100个
#define LOGNUM 100
//前置声明
class student;
istream& operator>>(istream&,student&);
ostream& operator<<(ostream&,student&);
//学生类:作为节点的数据域
class student
{
public:
student();
student(int ,const char*,short);//有参构造
student(const student&);//拷贝构造
//友元
friend istream& operator>>(istream&,student&);
friend ostream& operator<<(ostream&,student&);
protected:
int id; //ID
char name[10]; //姓名
short score; //成绩
};
//重载运算符cin
istream& operator>>(istream& input,student& s)
{
cout<<"please input:";
input>>s.id>>s.name>>s.score;
return input;
}
//重载运算符cin
ostream& operator<<(ostream& output,student& s)
{
output<<"学生信息:"<<s.id<<" "<<s.name<<" "<<s.score;
return output;
}
//拷贝构造
student::student(const student& s)
{
*this=s;
}
student::student()
{
}
//有参构造
student::student(int i,const char* n,short s):id(i),score(s)
{
strcpy(this->name,n);
}
//节点: 数据域|左孩子|右孩子
class Node
{
public:
Node(); //无参
Node(student& t);//有参
//由于tree中用到Node中的lchild,rchild成员,故声明为友元类
friend class tree;
private:
student data; //节点的数据域
Node* lchild; //节点的联系
Node* rchild; //节点的联系
};
//空构造
Node::Node():lchild(NULL),rchild(NULL)
{
}
//有参构造:由于data是对象,由该对象的构造器来初始化
Node::Node(student& t):data(t),lchild(NULL),rchild(NULL)
{
}
//树
class tree
{
public:
tree();
tree(const char*,int ilen);//有参构造
bool insertBST(const char* &,Node* &);
void ProOrder(Node*);//前序遍历
Node* getRoot();
bool saveMsg(Node*);//保存信息:树中的信息写入节点
bool writeMsg(bool,short,short,student);
protected:
//根节点的头指针
Node* root;
};
Node* tree::getRoot()
{
return this->root;
}
//前序遍历
void tree::ProOrder(Node* ploc)
{
if(NULL==ploc)
return;
//先当前
cout<<ploc->data<<endl;//输出对象
//再左子树
ProOrder(ploc->lchild);
//再右子树
ProOrder(ploc->rchild);
}
//存储信息:遍历
bool tree::saveMsg(Node* ploc)
{
static int loc=0;//遍历的次数
static int pnum=0;//pnum物理节数
loc++;
if(NULL==ploc)
{
//写入信息到文件中 偏移量
this->writeMsg(true,(short)0,\
(short)(sizeof(short)*loc),\
student());//true逻辑节点 内容
return true;
}
else//有节点
{
//写入信息到文件中:物理地址
short result=LOGNUM*sizeof(short)+pnum*sizeof(student);
//写入信息到文件中:物理
this->writeMsg(false,result,sizeof(short)*loc,ploc->data);
pnum++;
}
//遍历
saveMsg(ploc->lchild);
saveMsg(ploc->rchild);
}
//存储信息到文件中:逻辑结点() 物理结点
//opt=true 逻辑节点 opt=false 物理节点
//sval偏移量的值 lseek代表写入的位置 studetn s=student()
bool tree::writeMsg(bool opt,short sval,short lseek,student s)
{
//1打开文件:创建对象
ofstream of("stu.data",ios::out|ios::binary);
//2操作
if(opt)//逻辑节点
{
cout<<"opt="<<opt<<" sval="<<sval<<" lseek="<<lseek<<endl;
of.seekp(lseek,ios::beg);
of.write((char*)&sval,sizeof(sval));
}
else
{
cout<<"opt="<<opt<<" sval="<<sval<<" lseek="<<lseek<<" "<<s<<endl;
//先存放逻辑的值
of.seekp(lseek,ios::beg);
of.write((char*)&sval,sizeof(sval));
//再存放物理内容
of.seekp(sval,ios::beg);
of.write((char*)&s,sizeof(student));
}
//3关闭
of.close();
}
//无参构造
tree::tree():root(NULL)
{
}
//有参构造
tree::tree(const char* buf,int ilen):root(NULL)
{
//char buf[]="ab#d##c#e##";
//调用函数来生成树
this->insertBST(buf,this->root);
}
//插入节点
bool tree::insertBST(const char*& buf,Node* & ploc)
{
if('\0'==*buf)
return true;
if('#'==*buf)//当前节点为空节点
ploc=NULL;
else//有点
{
//1申请节点
ploc=new Node;//初始化:构造器
//为Node的数据域填写内容
cin>>ploc->data;
if(NULL==ploc)
return false;
//构造当前节点的左子树
insertBST(++buf,ploc->lchild);
//构造当前节点的右子树
insertBST(++buf,ploc->rchild);
}
return true;
}
int main()
{
//实例化:
char buf[]="ab#d##c#e##";
tree t(buf,11);//有参
t.saveMsg(t.getRoot());
}