欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 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());
}

 

相关标签: 原创