数据结构 - 二叉排序树的实现

二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。 

它或者是一棵空树;或者是具有下列性质的二叉树: 

(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; 

(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; 

(3)左、右子树也分别为二叉排序树;

上机代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;

#define KeyType int
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)< (b))
#define LQ(a,b) ((a)<=(b))
#define FALSE 0
#define TRUE 1
#define OK 1
//#define OVERFLOW 0
#define ERROR 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10

typedef struct
{
	KeyType key;                                                //关键字域
} ElemType;                                                                                   

typedef struct BiTNode               //定义二叉树二叉链表
{
	ElemType  data;
	struct BiTNode *lchild, *rchild;
}BiTNode,*BiTree,*SElemType;

typedef struct
{
	SElemType *base;
	SElemType *top;
	int stacksize;
}SqStack;

int DestroyBiTree(BiTree &T) //销毁树
{
	if(T!=NULL)
	free(T);
	return 0;
}

int ClearBiTree(BiTree &T) //清空树
{
	if(T!=NULL)
	{
		T->lchild=NULL;
		T->rchild=NULL;
		T=NULL;
	}
	return 0;
}

int SearchBST(BiTree T,KeyType key,BiTree f,BiTree &p)    //查找关键字,指针p返回
{
	if(!T)
	{
		p=f;
		return FALSE;
	}
	else if EQ(key,T->data.key)
	{
		p=T;
		return TRUE;
	}
	else if LT(key,T->data.key)
		return SearchBST(T->lchild,key,T,p);
	else
		return SearchBST(T->rchild,key,T,p);
}

int InsertBST(BiTree &T,ElemType e)   //插入节点元素
{
	BiTree s,p;
	if(!SearchBST(T,e.key,NULL,p))
	{
		s=(BiTree)malloc(sizeof(BiTNode));
		s->data=e;
		s->lchild=s->rchild=NULL;
		if(!p)
			T=s;
		else if LT(e.key,p->data.key)
			p->lchild=s;
		else
			p->rchild=s;
		return TRUE;
	}
	else return FALSE;
}

int ShowBST(BiTree T,int nlayer)      //显示树形二叉排序树
{
	int i;
	if(T==NULL)
		return FALSE;
	ShowBST(T->rchild,nlayer+1);
	for(i=0;i<nlayer;i++)
		printf("    ");
	printf("%d\n",T->data);
	ShowBST(T->lchild,nlayer+1);
	return OK;
}

int Visit(ElemType e)  //Visit函数
{
	printf("%d ",e.key);
	return OK;
}

int InitStack(SqStack &S)   //构造空栈
{
	S.base=(SElemType*)malloc(STACK_INIT_SIZE *sizeof(SElemType));
	if(!S.base) exit(OVERFLOW);
	S.top=S.base;
	S.stacksize=STACK_INIT_SIZE;
	return OK;
}//InitStack

int Push(SqStack &S, SElemType e)  //插入元素e为新栈顶
{
	if(S.top-S.base>=S.stacksize)
	{
		S.base=(SElemType*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(SElemType));
		if(!S.base) exit(OVERFLOW);
		S.top=S.base+S.stacksize;
		S.stacksize+=STACKINCREMENT;
	}
	*S.top++=e;
	return OK;
}//Push

int Pop(SqStack &S,SElemType &e)  //删除栈顶,应用e返回其值
{
	if(S.top==S.base)  return ERROR;
	e=*--S.top;
	return OK;
}//Pop

int StackEmpty(SqStack S)          //判断是否为空栈
{
	if(S.base==S.top) return TRUE;
	return FALSE;
}

int PreOrderTraverse(BiTree T,int(*Visit)(ElemType e))  //先序遍历,运用栈
{
	SqStack S;
	BiTree p;
	InitStack(S);
	p=T;
	while(p|| !StackEmpty(S))
	{
		if(p)
		{
			Push(S,p);
			if(!Visit(p->data)) return ERROR;
			p=p->lchild;
		}
		else
		{
			Pop(S, p);
			p=p->rchild;
		}
	}
	return OK;
}

int InOrderTraverse(BiTree T, int(*Visit)(ElemType e))  //中序遍历,运用栈
{
	SqStack S;
	BiTree p;
	InitStack(S);
	p=T;
	while(p|| !StackEmpty(S))
	{
		if(p)
		{
			Push(S,p);
			p=p->lchild;
		}
		else
		{
			Pop(S,p);
			if(!Visit(p->data)) return ERROR;
			p=p->rchild;
		}

	}
	return OK;
}

int PostOrderTraverse(BiTree T,int(*Visit)(ElemType e)) //后序遍历,运用栈
{
	SqStack S,SS;
	BiTree p;
	InitStack(S);
	InitStack(SS);
	p=T;
	while(p|| !StackEmpty(S))
	{
		if(p)
		{
			Push(S,p);
			Push(SS,p);
			p=p->rchild;
		}
		else
		{
			if(!StackEmpty(S))
			{
				Pop(S, p);
				p=p->lchild;
			}
		}
	}
    while(!StackEmpty(SS))
    {
        Pop(SS, p);
		if(!Visit(p->data)) return ERROR;
    }
	return OK;
}

int Delete(BiTree &p) // 三种删除节点的操作实现
{
	BiTree q,s;
	if(!p->rchild)    //右子树为空
	{
		q=p;
		p=p->lchild;
		free(q);
	}
	else if(!p->lchild)    //左子树为空
	{
		q=p;
		p=p->rchild;
		free(q);
	}
	else
	{
		q=p;
		s=p->lchild;
		while(s->rchild)
		{
			q=s;
			s=s->rchild;
		}
		p->data=s->data;
		if(q!=p)
			q->rchild=s->lchild;
		else
			q->lchild=s->lchild;
		free(s);
	}
	return TRUE;
}

int DeleteBST(BiTree &T,KeyType key) //实现二叉排序树的删除操作
{
	if(!T)
		return FALSE;
	else
	{
		if (EQ(key,T->data.key))       //T->data.key等于key
			return Delete(T);
		else if (LT(key,T->data.key))   //T->data.key是否小于key
			return DeleteBST(T->lchild,key);
		else
			return DeleteBST(T->rchild,key);
	}
	return 0;
}

int main()
{
	int i,nlayer;
	ElemType k,d;
    BiTree  BT,p;
	BT=NULL;
	p=NULL;
	nlayer=1;
	printf("请输入插入的二叉树节点的数值(输入数字0结束节点赋值):\n");
	scanf("%d",&k.key);
	for(i=0;k.key!=NULL;i++)
	{
		if(!SearchBST(BT,k.key,NULL,p))         //查找关键字
		{
			InsertBST(BT,k);                    //二叉树节点数值插入
			scanf("%d",&k.key);
		}
		else
		{
			printf("输入数据重复!\n");
			return 0;
		}
	}
	printf("二叉排序树树形输出为:\n");
	ShowBST(BT,nlayer);                        //树形显示二叉排序树
	printf("请输入删除的数据:");
	scanf("%d",&d.key);
	DeleteBST(BT,d.key);                       //删除关键字
	ShowBST(BT,nlayer);
	printf("先序遍历为:");                    //先序遍历、中序遍历、后序遍历
	PreOrderTraverse(BT,Visit);
	printf("\n中序遍历为:");
	InOrderTraverse(BT, Visit);
	printf("\n后序遍历为:");
	PostOrderTraverse(BT,Visit);
	printf("\n清空该二叉排序树.\n");            //清空二叉树
	ClearBiTree(BT);
	ShowBST(BT,nlayer);
	printf("\n销毁该二叉排序树.\n");	        //销毁二叉树
	ClearBiTree(BT);

	return 0;
}
时间: 2024-10-03 13:38:42

数据结构 - 二叉排序树的实现的相关文章

(编程训练)再回首,数据结构——二叉排序树的建立

最近在复习数据结构,顺便看看大一的时候写的代码,看完之后比当初有了更加深刻的体会. 希望这些能提供给初学者一些参考. 在VC++6.0下可运行,当初还写了不少注释. [问题描述] 以输入的一组整数作为关键字的值,构造其对应的二叉排序树,并对给点的值在该二叉排序树上进行查找 [基本要求] ·输入:输入一组关键字(整数)及要查找的值 ·输出:排好序的关键字及查找的结果 样例输入 60 35 69 84 96 13 66 34 21 -1 40 样例输出 13 21 34 35 60 66 69 84

[数据结构]二叉排序树

在数据的查找这个问题上,如果查找的数据集是有序线性表,并且是顺序存储的,查找可以使用折半.插值.斐波那契等查找算法实现,可惜,因为有序,在插入和删除操作上,就需要耗费大量的时间. 那么有没有一种可以使得插入和删除的效率不错,又可以比较高效地实现查找的算法呢?也就是说有没有一种算法能够使用与动态查找. 动态查找:在查找时插入或者删除的查找表称为动态查找表. 所以就引入了二叉排序树,它是这样的一个二叉树: 左子树上的所有结点的值小于它的根结点的值: 右子树上的所有结点的值大于它的根结点的值: 它的左

大话数据结构—二叉排序树

二叉排序树(Binary Sort Tree),又称二叉查找树.它或者是一颗空树,或者是具有下列性质的二叉树. 若它的左子树不空,则左子树上所有节点的值都小于它的根节点的值: 若它的右子树不空,则右子树上所有节点的值都大于它的根节点的值: 它的左.右子树也分别为二叉排序树. 上面就是一棵二叉排序树,当我们对它进行中序遍历时,就可以得到一个有序的序列{35,37,47,51,58,62,73,88,93,99}. 构造一颗二叉排序树,不是为了排序,而是为了提高查找和插入删除关键字的速度. 二叉排序

数据结构 二叉排序树 操作及实现

#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> using namespace std; typedef struct Bitnode { int data; struct Bitnode *lchild,*rchild; } Bitnode,*Bitree; int Searchtree(Bitree T,int num,Bitree F,Bitree &

(考研)(精华)二叉树的知识结构图以及各种特殊的二叉树

关于二叉树有一点需要注意:二叉树并不是树的一种特殊形式. 二叉树又有几种特殊的形式:二叉排序树(二叉查找树).最优二叉树(哈弗曼树).二叉堆(大顶堆,小顶堆)等.斜线是数据结构 二叉排序树(二叉查找树)(BST)它或者是一棵空树:或者是具有下列性质的二叉树:(常用二分查找) 1,若左子树不空,则左子树上所有结点的值均小于它的根结点的值: 2,若右子树不空,则右子树上所有结点的值均大于它的根结点的值: 3,左.右子树也分别为二叉排序树: 特有的性质:对于每个结点,左孩子均小于它,右孩子均大于它 A

经典排序算法总结和比较

排序算法可以说是一项基本功,解决实际问题中经常遇到,针对实际数据的特点选择合适的排序算法可以使程序获得更高的效率,有时候排序的稳定性还是实际问题中必须考虑的,这篇博客对常见的排序算法进行整理,包括:插入排序.选择排序.冒泡排序.快速排序.堆排序.归并排序.希尔排序.二叉树排序.计数排序.桶排序.基数排序. 代码都经过了CodeBlocks的调试,但是很可能有没注意到的BUG,欢迎指出. 比较排序和非比较排序 常见的排序算法都是比较排序,非比较排序包括计数排序.桶排序和基数排序,非比较排序对数据有

【数据结构】简单谈一谈二分法和二叉排序树BST查找的比较

二分法查找: 『在有序数组的基础上通过折半方法不断缩小查找范围,直至命中或者查询失败.』 二分法的存储要求:要求顺序存储,以便于根据下标随机访问 二分法的时间效率:O(Log(n)) 二分法的空间效率:原地查询 O(1) 二分法对应的搜索树是确定的. 二叉排序树查找: 『借助二叉排序树进行搜索,但因为所建立的树本身不一定是轴对称的,所以每次比较并不能确保减小一半范围.』 二叉树的存储要求:需要树形结构,相比顺序存储需要占用更多的空间,但也有链接型数据结构灵活可拓展的有点. 二叉排序树查找的时间复

【数据结构】平衡二叉排序树BBST之AVL树

平衡二叉排序树 平衡二叉排序树(Balanced Binary Sort Tree),上一篇博客[数据结构]二叉排序树BST讲了BST,并且在最后我们说BST上的操作不会超过O(h),既然树高这么重要,那么BBST的研究就是为了使得树的深度在可接受的范围内渐近意义下达到O(lgn) n个节点组成的二叉树,其高度为lgn取下限时,这棵树是理想平衡的,满足这样条件的树只有完全二叉树和满二叉树,这样的要求未免太苛刻,并且实际中没有意义. 适度平衡:保证树高在渐近意义上不超过O(lgn)适度平衡的树也称

数据结构学习之二叉排序树

介绍:二叉排序树是以一定的规则排列树中元素,因而可以进行快速的排序和查询的树状数据结构,一般规则是:对于树中任意一个节点,左孩子严格小于根,根严格小于右孩子,有点像大根堆.(只是大根堆中左右孩子关系并不确定,且和根的关系是统一的,而且有上浮和下沉操作使得大根堆总是一棵完全二叉树,其不断弹出堆顶形成有序列的过程叫做堆排序.虽然二叉排序树中也有旋转操作使得树尽量平衡,但是由于数值大小分明的左右孩子,在进行平衡操作时远不如大根堆方便快捷.)对于一棵已经构造完成的排序二叉树,它的中序遍历序列即为升序排列