二叉排序树的完整实现

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

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

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

严谨的操作

查找一个数据:对于大根堆操作,如果当前值小于根节点,那么这个值在左右分支出现都是由可能得,但是对于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;
}  
时间: 2024-10-16 15:35:23

二叉排序树的完整实现的相关文章

POJ 3481

这是利用treap写的二叉排序树,只要理解其中旋转能够改变树的左右子树平衡度,即高度之差,差不多就能掌握treap树的要领了. 相对于其他高级BST,treap树实现应该算最简单了,利用的是随机树产生的理论的二叉排序树时间复杂度为O(nlgn)来实现,具体证明 算法导论 中有. 推荐NOCOW中的讲解,关于二叉排序树相当完整! treap动画展示:http://www.ibr.cs.tu-bs.de/courses/ss98/audii/applets/BST/Treap-Example.htm

BST二叉排序树的查找和删除的完整C代码

二叉排序树的查找算法 假定二叉排序树的根节点指针为root,给定的关键字值为key,则查找算法可描述为: 置初值:p = root : 如果 key = p -> data ,则查找成功,算法结束: 否则,如果key < p->data ,而且 p 的左子树非空,则将 p 的左子树根送 p ,转步骤 2 :否则,查找失败,算法结束: 否则,如果 key > p->data ,而且 p 的右子树非空,则将 p 的右子树根送 p ,转步骤 2 :否则,查找失败,算法结束. //B

重温数据结构:二叉排序树的查找、插入、删除

读完本文你将了解到: 什么是二叉排序树 Binary Sort Tree BST 二叉排序树的关键操作 查找 插入 删除 运行代码测试 一道面试题 总结 Thanks 我们知道,二分查找可以缩短查找的时间,但是有个要求就是 查找的数据必须是有序的.每次查找.操作时都要维护一个有序的数据集,于是有了二叉排序树这个概念. 上篇文章 我们介绍了 二叉树 的概念,二叉树有左右子树之分,想必在区分左右子树时有一定的规则. 现在我们来介绍二叉树的一种特殊形式 - 二叉排序树,了解它的区分策略及常用操作. 什

二叉查找树 C++实现(含完整代码)

一般二叉树的查找是通过遍历整棵二叉树实现,效率较低.二叉查找树是一种特殊的二叉树,可以提高查找的效率.二叉查找树又称为二叉排序树或二叉搜索树. 二叉查找树的定义 二叉排序树(Binary Search Tree)又称二叉排序树(Binary Sort Tree),或者是一颗空二叉树,或者是具有一下特性的二叉树: 若它的左子树不为空,则左子树上的所有结点的值均小于根节点的值. 若它的右子树不为空,则右子树上的所有结点的值均小于根节点的值. 它的左右子树又分别是二叉排序树. 由定义可知,二叉查找树中

二叉排序树第二版(平衡二叉树)

由于二叉排序树插入随意,毫无规则可言,自然时间效率就不能保证,极端情况下会退化成链表(左空右慢或反之). 平衡二叉树就是在二叉排序树的基础上进行优化,平衡二叉树就是保证任何父节点的左右子树深度只能相差1.0.-1(左-右),所以每次插入一个新点都要修改这棵树使其平衡,学名叫旋转(其实不像旋转),这样效率就能达到log(n).旋转的讲解 http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html 这里写很好, 不过代码有些问题. 附

二叉排序树的插入与删除

一.二叉排序树的插入 首先检查要插入的数据是否已存在,若存在则不插入,若不存在,则把元素插入到在二叉树上查找失败时的结点的左孩子和右孩子上.需要考虑的特殊情况是插入第一个元素前,二叉树为空. 1 bool insert(BiTreeNode *&root,DataType *item) { 2 BiTreeNode *current = NULL,*parent = NULL,*p = NULL; 3 current = root; 4 while(current != NULL) { 5 if

创建二叉查找树的完整C代码

BST 基本概念 二叉查找树(Binary Search Tree),又称二叉排序树(Binary Sort Tree),亦称二查搜索书. 它或者是一棵空树:或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值: (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值: (3)左.右子树也分别为二叉排序树: 简单的说就是:左孩子<双亲结点<右孩子. 因此,对查找二叉树进行中序遍历,得到的是一个从小到大排序的数列. 创建BST的完整C代码 /* 创

查找系列之二叉排序树

二叉排序树的创建.查询.插入与删除 一.简述二叉排序树的思想: 动态查找表中主要有二叉树结构和树结构两种,而二叉树结构分为二叉排序树和平衡二叉树,树结构分为B-树和B+树等. 二叉排序树可以是一颗空树二叉排序树的性质:二叉排序树上的节点满足左子树<父节点<右子树 也就是说二叉排序树必须有顺序,且满足左子树<父节点<右子树 二.构建二叉排序树 创建二叉排序树通常我们用链式存储结构的节点作为存储单位:如 typedef struct Node{ TypeData data; struc

二叉排序树-经典排序

定义:一颗二叉排序树(BST)是一棵二叉树,其中的每个节点都包含一个Comparable的键(以及相关联的值),并且每个键都大于其左子树中的任意键而小于右子数的任意结点的键. 复杂度:一个由N个随机键构造的二叉排序树,查找的平均所需比较次数为~2lgN(约1.39lgN). 接下来是完整的代码,包括二叉树的创建,插入,遍历,删除 1 #include<stdio.h> 2 #include<stdlib.h> 3 #ifdef _DEBUG 4 #define new DEBUG_