数据结构:二叉搜索树递归与非递归的实现 及性能,AVL,红黑树分析

二叉搜索树

二叉查找树(Binary Search Tree),(二叉搜索树 或 二叉排序树)它或者是一棵空树,

或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;

 它的左、右子树也分别为二叉排序树

二叉树实现:

二叉树及二叉树的基本操作(递归与非递归) - W_J_F_的博客 - CSDN博客 https://blog.csdn.net/W_J_F_/article/details/80408846

BinarySearchTree.h

#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<assert.h>

typedef int DataType;

typedef struct BSTreeNode
{
	struct BSTreeNode* _pleft;
	struct BSTreeNode* _pright;
	DataType _data;
}BSTNode;

// 初始化二叉搜索树 
void InitBSTree(BSTNode** pRoot);

// 插入值为data的元素 
void InsertBSTree(BSTNode** pRoot, DataType data);

// 删除值为data的结点 
void DeleteBSTree(BSTNode** pRoot, DataType data);

// 在二叉搜索树中查找值为data的结点 
BSTNode* FindBSTree(BSTNode* pRoot, DataType data);

// 中序遍历二叉搜索树 
void InOrder(BSTNode* pRoot);

// 销毁二叉搜索树 
void DestroyBSTree(BSTNode** pRoot);
//

BSTNode* _FindBSTree(BSTNode* pRoot, DataType data);

int _InsertBSTree(BSTNode** pRoot, DataType data);

int _DeleteBSTree(BSTNode** pRoot, DataType data);


BInarySearchTree.c

#include"BinarySearchTree.h"
// 初始化二叉搜索树 
void InitBSTree(BSTNode** pRoot)//改变指针的指向传二级指针
{
	assert(pRoot);
	*pRoot = NULL;
}

BSTNode* BuyNode(DataType data)
{
	BSTNode* pNew = (BSTNode*)malloc(sizeof(BSTNode));
	if (pNew == NULL)
	{
		assert(0);
		return 0;
	}
	pNew->_data = data;
	pNew->_pleft = NULL;
	pNew->_pright = NULL;
	return pNew;
}

// 插入值为data的元素 
void InsertBSTree(BSTNode** pRoot, DataType data)
{
	BSTNode* pParent = NULL;
	BSTNode* pCur = NULL;
	assert(pRoot);
	if (*pRoot == NULL)//如果树是空的
	{
		*pRoot = BuyNode(data);
		return;
	}
	//查找待插入位置
	pCur = *pRoot;
	while (pCur)
	{
		if (data < pCur->_data)
		{
			pParent = pCur;
			pCur = pCur->_pleft;
		}
		else if (data > pCur->_data)
		{
			pParent = pCur;
			pCur = pCur->_pright;
		}
		else
		{
			return;
		}
	}

	//插入节点
	pCur = BuyNode(data);
	if (data > pParent->_data)
	{
		pParent->_pright = pCur;
	}
	else
	{
		pParent->_pleft = pCur;
	}

}

// 删除值为data的结点 
void DeleteBSTree(BSTNode** pRoot, DataType data)
{
	//1:左右孩子为空,直接删除
	//2:只有左孩子(1:是否有双亲,2:是双亲的左或右孩子)
	//3:只有右孩子(1:是否有双亲,2:是双亲的左或右孩子)
	//4:左右孩子均存在       》》找代替节点      1:左子树代替——最大元素
	//                                           2:右子树代替——最小元素                       
	//                       》》将代替节点中的的数据交给待删除的节点
	//                       》》连接(待删除节点为其双亲的左或右孩子)

	//找待删除节点在二叉搜索树的位置
	BSTNode* pCur = *pRoot;
	BSTNode* pParent = pCur;
	while (pCur)
	{
		if (data == pCur->_data)
			break;
		else if (data > pCur->_data)
		{
			pParent = pCur;//记录双亲
	
			pCur = pCur->_pright;
		}
		else
		{
			pParent = pCur;
			pCur = pCur->_pleft;
		}
	}
	if (NULL == pCur)
		return;

	//删除
	if (NULL == pCur->_pleft)//只右有孩子||叶子
	{
		if (pCur == *pRoot)//无双亲
		{
			*pRoot = pCur->_pright;
		}
		else
		{
			if (pParent->_pleft == pCur)//待删除节点是双亲的左
			{
				pParent->_pleft = pCur->_pright;
			}
			else//待删除节点是双亲的右
				pParent->_pright = pCur->_pright;
		}
	}
	else if (NULL == pCur->_pright)//只有左孩子||叶子
	{
		if (pCur == *pRoot)
		{
			*pRoot = pCur->_pleft;
		}
		else
		{
			if (pParent->_pleft == pCur)
			{
				pParent->_pleft = pCur->_pleft;
			}
			else
			{
				pParent->_pright = pCur->_pleft;
			}
		}
	}
	else//左右孩子均存在
	{
		//4:左右孩子均存在       》》找代替节点      1:左子树代替——最大元素
		//                                           2:右子树代替——最小元素                       
		//                       》》将代替节点中的的数据交给待删除的节点
		//                       》》连接(待删除节点为其双亲的左或右孩子)

		BSTNode* pDel = pCur->_pright;                //寻找右子树的最小结点
		while (pDel->_pleft)
		{
			pParent = pDel;
			pDel = pDel->_pleft;
		}
		pCur->_data = pDel->_data;

		if (pDel == pParent->_pleft)//待删除节点可能含有右子树(已经找到最左)
		{
			pParent->_pleft = pDel->_pright;
		}
		else
		{
			pParent->_pright = pDel->_pright;
			pCur = pDel;
		}
	}
			free(pCur);
			pCur = NULL;
}

// 在二叉搜索树中查找值为data的结点 
BSTNode* FindBSTree(BSTNode* pRoot, DataType data)
{
	assert(pRoot);
	BSTNode* pCur = pRoot;
	while (pCur)
	{
		if (data == pCur->_data)
			return pCur;
		else if (data > pCur->_data)
			pCur = pCur->_pright;
		else
			pCur = pCur->_pleft;
	}
	return NULL;
}

// 中序遍历二叉搜索树 
void InOrder(BSTNode* pRoot)
{
	if (pRoot)
	{
		InOrder(pRoot->_pleft);
		printf("%d->",pRoot->_data);
		InOrder(pRoot->_pright);
	}
}

// 销毁二叉搜索树 
void DestroyBSTree(BSTNode** pRoot)
{
	assert(pRoot);
	if (*pRoot)
	{
		DestroyBSTree(&(*pRoot)->_pleft);
		DestroyBSTree(&(*pRoot)->_pright);
		free(*pRoot);
		*pRoot = NULL;
	}

}
递归


BSTNode* _FindBSTree(BSTNode* pRoot, DataType data)
{
	if (pRoot == NULL)
	{
		return NULL;
	}
	else
	{
		if (data == pRoot->_data)
		{
			return pRoot;
		}
		else if (data > pRoot->_data)
		{
			return _FindBSTree(pRoot->_pleft,data);
		}
		else
		{
			return _FindBSTree(pRoot->_pright,data);
		}
	}
}
int _InsertBSTree(BSTNode** pRoot, DataType data)
{
	assert(pRoot);
	if (NULL == *pRoot)
	{
		*pRoot = BuyNode(data);
	}
	else
	{
		if (data > (*pRoot)->_data)
		{
			_InsertBSTree(&(*pRoot)->_pright, data);
		}
		else if (data < (*pRoot)->_pleft)
		{
			_InsertBSTree(&(*pRoot)->_pright, data);
		}
		else
		{
			return 0;
		}
	}
}
int _DeleteBSTree(BSTNode** pRoot, DataType data)
{
	assert(pRoot);
	if (NULL == *pRoot)
	{
		return 0;
	}
	else
	{
		if (data > (*pRoot)->_data)
		{
			_DeleteBSTree(&(*pRoot)->_pright,data);
		}
		else if (data < (*pRoot)->_data)
		{
			_DeleteBSTree(&(*pRoot)->_pleft,data);
		}
		else
		{
			//只有右孩子||叶子节点
			BSTNode* pDel = *pRoot;
			if (NULL == pDel->_pleft)
			{
				*pRoot = pDel->_pright;
				free(pDel);
			}
			else if(NULL == pDel->_pright)//只有左子树||叶子
			{
				*pRoot = pDel->_pleft;
				free(pDel);
			}
			else//左右子树
			{
				pDel = (*pRoot)->_pright;
				while (pDel->_pleft)
				{
					pDel->_pleft;
				}
				(*pRoot)->_data = pDel->_data;
				_DeleteBSTree(&(*pRoot)->_pright,pDel->_data);

			}
		}
	}
}

test

#include"BinarySearchTree.h"

test()
{
	int a[] = {5,4,6,9,0,2,1,8,7,3};
	int i = 0;
	BSTNode* pRoot;
	InitBSTree(&pRoot);
	for (;i < sizeof(a) / sizeof(a[0]);i++)
	{
		InsertBSTree(&pRoot,a[i]);
	}

	printf("InOrder: ");
	InOrder(pRoot);
	printf("\n");
	
	DeleteBSTree(&pRoot, 5);
	printf("InOrder: ");
	InOrder(pRoot);
	printf("\n");

	DeleteBSTree(&pRoot, 7);
	printf("InOrder: ");
	InOrder(pRoot);
	printf("\n");
}

int main()
{
	test();
	system("pause");
	return 0;
}

二叉搜索树性能分析:

二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多

  

最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:

 

最差情况下,二叉搜索树退化为单支树,其平均比较次数为:

AVL树

 

一棵AVL树或者是空树,或者是具有以下性质的二叉搜索树:  
它的左右子树都是AVL树  

左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)  

如果一棵二叉搜索树是高度平衡的,它就是AVL树。如果它有n个结

点,其高度可保持在O(lgn),平均搜索时间复杂度O(lg(n)) 

 

红黑树:

 

红黑树是一棵二叉搜索树,它在每个结点上增加了一个存储位来表示结点的颜色,

可以是red或者black,通过对任何一条从根节点到叶子结点简单路径上的颜色来约束,

 

红黑树保证最长路径不超过最短路径的两倍,

因而近似平衡,而且在实际应用中发现红黑树性能确实比AVL树性能高  

红黑树性质:

 1. 每个结点不是红色就是黑色  

 2. 根节点是黑色的 

 3. 如果一个节点是红色的,则它的两个孩子结点是黑色的  

 

  4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均包含相同数目的黑色结点  

  5. 每个叶子结点都是黑色的(此处的叶子结点指的是空结点)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值