二叉树的构建与遍历,二叉树元素的排序

   构建二叉树 , 定义一个节点空间 , 一个数据域 , 和左右节点域 , 并先序遍历一次树 .

#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());
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值