二叉排序树的完整实现

在排序中,之前利用大小根堆的方式,保持最小值或者最大值在堆顶端

二叉排序树是保持这棵树一直是有序的


二叉排序树的建立,不同于堆操作只需要对非叶子节点进行处理,保持其大于左右孩子,或者是小于左右孩子,而是需要对每一个点都进行处理,因为他是相对而言更加

严谨的操作

查找一个数据:对于大根堆操作,如果当前值小于根节点,那么这个值在左右分支出现都是由可能得,但是对于BST,如果小那么肯定在左分支,如果大,那么肯定在右分支

删除一个元素:对于堆,一般都是由于排序会删除堆顶元素,那么删除之后由最后一个元素补上,然后再检验其情况

                            对于二叉树,如果删除的元素只有一个孩子,那么由这个孩子代替,如果有两个孩子,那么在右分支中找到最小的元素代替


#include <iostream>  
#include <stack>  
using namespace std;  
//二叉排序树,完成创建节点,插入节点,删除节点,查找节点,中序遍历的功能  
//节点类定义  
class Node{  
public:  
	int data;//数据  
	Node *parent;//父节点  
	Node *left;//左子节点  
	Node *right;//右子节点  
public:  
	Node():data(-1),parent(NULL),left(NULL),right(NULL){}  
	Node(int num):data(num),parent(NULL),left(NULL),right(NULL){}  
};  

//二叉排序树类定义  
class Tree{  
public:  
	Tree(int num[],int len);//插入num数组的前len个数据  
	void InsertNode1(int data);//插入节点,非递归方法  
	void InsertNode(int data);//插入节点,递归方法  
	Node* SearchNode(int data);//查找节点,递归方法  
	void DeleteNode(int data);//删除节点及其子树,递归方法  
	void InOrderTree();//中序遍历,递归方法  
	void InOrderTreeUnRec();  
private:  
	void InsertNode(Node *current,int data);//递归插入方法  
	Node *SearchNode(Node *current,int data);//递归查找方法  
	void DeleteNode(Node *current);//递归删除方法  
	void InOrderTree(Node *root);//中序遍历,递归方法  
private:  
	Node *root;//二叉排序树的根节点  
};  

//构造函数中创建二叉排序树  
//首先生成根节点,然后循环调用插入节点函数使二叉排序树进行插入操作  
Tree::Tree(int num[], int len){  
	root=new Node(num[0]);//建立root节点  
	//把数组中的其他数据插入到二叉排序树中  
	for (int i=1;i<len;i++){  
		//InsertNode(num[i]);  
		InsertNode1(num[i]);  
	}  
}  
//插入节点操作  
//插入数据为参数data的节点,非递归方法  
void Tree::InsertNode1(int data){  
	Node *p,*par;  
	Node *newNode=new Node(data);//创建节点  
	p=par=root;  
	while (p!=NULL){//查找插入在哪个节点下面  
		par=p;//保存节点  
		if (data>p->data){ //如果data大于当前节点的data  
			p=p->right;//下一步到右子节点  
		}  
		else if (data<p->data){//如果data小于当前节点的data  
			p=p->left;//下一步到左子节点  
		}  
		else if (data==p->data){//不能插入重复数据  
			delete newNode;  
			return;  
		}  
	}  
	newNode->parent=par;  
	if (par->data>newNode->data){ //把新节点插入在目标节点的正确位置  
		par->left=newNode;  
	}  
	else  
		par->right=newNode;  
}  
//插入节点操作  
//插入数据为参数data的节点,递归方法,内部调用了private成员函数InsertNode()  
void Tree::InsertNode(int data){  
	if (root!=NULL){  
		InsertNode(root,data);//调用递归插入方法  
	}  
}  
//递归插入方法  
void Tree::InsertNode(Node *current, int data){  
	if (data<current->data){//如果data小于当前节点数据,在当前节点的左子树插入  
		if (current->left==NULL){//如果左子节点不存在,则插入到左节点  
			current->left=new Node(data);  
			current->left->parent=current;  
		}  
		else  
			InsertNode(current->left,data);//对左节点进行递归调用  
	}  
	else if (data>current->data){//如果data大于当前节点数据,则当前节点的右边子树插入  
		if (current->right==NULL){//如果右子树不存在,则插入到右节点  
			current->right=new Node(data);  
			current->right->parent=current;  
		}  
		else  
			InsertNode(current->right,data);//对右节点进行递归调用  
	}  
	return; //data等于当前节点数据时,不插入  
}  
//递归查找方法  
Node* Tree::SearchNode(Node *current, int data){  
	if (data<current->data){//如果data小于当前节点数据,递归搜索其左子树  
		if (current->left==NULL){//如果不存在左子树,返回NULL  
			return NULL;  
		}  
		return SearchNode(current->left,data);  
	}  
	else if (data>current->data){//如果data大于当前节点数据,递归搜索其右子树  
		if (current->right==NULL){//如果不存在右子树,返回NULL  
			return NULL;  
		}  
		return SearchNode(current->right,data);  
	}  

	return current;//如果相等返回current  
}  

//查找节点  
Node* Tree::SearchNode(int data){  
	if (root==NULL){  
		return NULL;  
	}  
	return SearchNode(root,data);  
}  
//删除数据为data的节点及其子树  
void Tree::DeleteNode(int data){  
	Node *current=NULL;  
	current=SearchNode(data);//查找节点  
	if (current!=NULL){  
		DeleteNode(current);//删除节点及其子树  
	}  
}  
//删除current节点及其子树的所有节点  
void Tree::DeleteNode(Node *current){  
	if (current->left!=NULL){ //删左子树  
		DeleteNode(current->left);  
	}  
	if (current->right!=NULL){//删右子树  
		DeleteNode(current->right);  
	}  

	if (current->parent==NULL){//如果current是根节点,把root置空  
		delete current;  
		root=NULL;  
		return;  
	}  
	//将current父亲节点的相应指针置空  
	if (current->parent->data>current->data){ //current为其父节点的左子节点  
		current->parent->left=NULL;  
	}  
	else{//current为其父节点的右子节点  
		current->parent->right=NULL;  
	}  
	//最后删除此节点  
	delete current;  
}  
//中序遍历,递归方法  
void Tree::InOrderTree(Node *current){  
	if (current!=NULL){  
		InOrderTree(current->left);//遍历左子树  
		cout<<current->data<<" ";//打印节点数据  
		InOrderTree(current->right);//遍历右子树  
	}  
}  
//中序遍历  
void Tree::InOrderTree(){  
	if (root==NULL){  
		cout<<"The Tree Is Empty!"<<endl;  
		getchar();  
		return;  
	}  
	InOrderTree(root);  
}  
//中序遍历,非递归方法  
/*可以用栈来临时存储节点 
先将根节点存入栈中,遍历左子树 
遍历完左子树返回时,栈顶元素应为根节点,此时出栈,并打印节点数据 
在中序遍历右子树 
*/  
void Tree::InOrderTreeUnRec(){  
	stack<Node *>s;  
	Node *p=root;  
	while (p!=NULL ||!s.empty()){  
		while (p!=NULL){//遍历左子树  
			s.push(p);//把遍历的节点全部压栈  
			p=p->left;  
		}  
		if (!s.empty()){  
			p=s.top();//得到栈顶内容  
			s.pop();//出栈  
			cout<<p->data<<" ";//打印  
			p=p->right;//指向右子节点,下一次循环时就会中序遍历右子树  
		}  
	}  
}  
int main()  
{  
	/* 测试程序*/  
	int num[5]={1,2,6,4};  
	Tree t(num,4);  
	Node *p=NULL;  
	t.InOrderTree();  
	cout<<endl;  
	t.InOrderTreeUnRec();  
	cout<<endl;  
	//t.InsertNode1(7);  
	t.InsertNode(0);  
	t.InOrderTree();  
	cout<<endl;  
	t.InOrderTreeUnRec();  
	cout<<endl;  
	p=t.SearchNode(4);  
	if (p!=NULL){  
		cout<<p->data<<endl;  
	}  
	else  
		cout<<"Not Find!"<<endl;  
	t.DeleteNode(2);  
	t.InOrderTree();  
	cout<<endl;  
	t.InOrderTreeUnRec();  
	system("pause");  
	return 0;  
}  


还有用C写的比较简单的程序

/*二叉排序树*/ 
#include <stdio.h>
#include <crtdbg.h>  
#define _CRTDBG_MAP_ALLOC  
typedef struct Node{  
public:  
	int data;//<数据   
	Node *left;//<左子节点  
	Node *right;//<右子节点  
}Node;
void NodeInit(Node *N,int val)
{
	N->data = val;
	N->left = NULL;
	N->right = NULL;
}
void buildPoint(int val,Node * root)
{
	if (val < root->data)
	{
		if (root->left != NULL)
		{
			buildPoint(val,root->left);
		}
		else
		{
			root->left = new Node;
			NodeInit(root->left,val);
		}
	}
	if (val >= root->data)
	{
		if (root->right != NULL)
		{
			buildPoint(val,root->right);
		}
		else
		{
			root->right = new Node;
			NodeInit(root->right,val);
		}
	}
}
void buildBST(int *a, int size,Node * root) //<建立二叉排序树,每一个节点都需要
{
	int i = 0;
	NodeInit(root,a[0]);
	for (i = 1; i < size; i++)
	{
		buildPoint(a[i],root);
	}

} 
void scanBST(Node * root) //<类似于中序遍历
{
	if (root == NULL)
	{
		return;
	}
	if (root->left)
	{
		scanBST(root->left);
	}
	printf("%d  ",root->data);
	if (root->right)
	{
		scanBST(root->right);
	}
}
void destoryPoint(Node *root) //<删除内存
{
	Node *left = root->left;
	Node *right = root->right;
	if (left)
	{
		destoryPoint(left);
	}
	delete root;
	root = NULL;
	if (right)
	{
		destoryPoint(right);
	}	
}
int main(int argc, char *argv[])
{
	int a[]={0,16,20,3,11,17,8,32,33,232,4,36,0};
	int size = sizeof(a)/sizeof(int);
	Node * root = new Node;
	buildBST(a,size,root);
	scanBST(root);
	destoryPoint(root);  //<如果没有这个,会产生相应的内存泄露
	_CrtDumpMemoryLeaks();  
	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值