数据结构中的几棵树——二叉树、二叉查找树、AVL、多路查找树


  本篇总结一下数据结构中的几种树形结构,包括二叉树、线索二叉树、二叉查找树、平衡二叉树(AVL)、多路查找树(B树)、B+树。

1.二叉树

  • 定义:二叉树(Binary Tree)是n(大于等于0)个结点的有限集合,该集合或为空,或由一个根结点和两棵互不相交的、分别称为根结点的左子树和右子树组成。
  • 特点
    • 每个结点最多两棵子树,所以二叉树中不存在度大于2的结点。 最多两棵子树意味着1棵子树或没有都是可以的。
    • 即使一棵树只有一棵子树,也要区分它是左子树还是右子树。
  • 二叉树的五种基本形态:
    • 空二叉树、只有一个根结点、根结点只有左子树、根结点只有右子树、根结点既有左子树又有右子树
  • 特殊二叉树
    • 斜树:所有结点只有左子树或者右子树。据此,线性表可以理解为一种特殊的数。
    • 满二叉树:所有分支结点都存在左子树和右子树,并且所有叶子都在同一层上,这样的数称为满二叉树。它有以下特点:叶子只能出现在最下层;非叶子结点度一定是2;同样深度的树,满二叉树结点个数最多,叶子数最多。
    • 完全二叉树:需要和满二叉树区别。具有以下特点:叶子只能出现在最下面两层;最下层叶子一定集中在左部连续位置;倒数第二层,如果有叶子,一定集中在右连续位置;如果结点度为1,则有左孩子,没右孩子;同样结点数的二叉树,完全二叉树的深度最小。
  • 存储结构:顺序存储;二叉链表存储。
  • 二叉树遍历:前序遍历、中序遍历、后序遍历、层次遍历
/*递归实现二叉树的前序遍历算法*/
void PreOrderTraverse(BiTree T){
	if(T==NULL)
		return;
	printf("%c",T.data);
	PreOrderTraverse(T.lchild);
	PreOrderTraverse(T.Rchild);
}
/*递归实现二叉树的中序遍历算法*/
void InOrderTraverse(BiTree T){
	if(T==NULL)
		return;
	PreOrderTraverse(T.lchild);
	printf("%c",T.data);
	PreOrderTraverse(T.Rchild);
}
/*递归实现二叉树的后序遍历算法*/
void PostOrderTraverse(BiTree T){
	if(T==NULL)
		return;
	PreOrderTraverse(T.lchild);
	PreOrderTraverse(T.Rchild);
	printf("%c",T.data);
}
/*非递归实现二叉树的前序遍历算法*/
void PreOrderTraverse(BiTree T){
	stack<BiTree> nodeBuffer;
	nodeBuffer.push(T);
	while(!nodeBuffer.empty()){
		BiTree node = nodeBuffer.pop();
		if(node == NULL)
			continue;
		printf("%c",node.data);
		nodeBuffer.push(node.Rchild);
		nodeBuffer.push(node.Lchild);
	}	
}
/*非递归实现二叉树的中序遍历算法*/
void InOrderTraverse(BiTree T){
	if(T==NULL)
		return;
	stack<BiTree> nodeBuffer;
	BiTree node = T;
	while(node != NULL || !nodeBuffer.empty){
		while(node != NULL){
			nodeBuffer.push(node);
			node = node.Lchils;
		}
		node = nodeBuffer.pop();
		print("%c",node.data);
		node = node.Rchild;
	}
}
/*非递归实现二叉树的后序遍历算法*/
void PostOrderTraverse(BiTree T){
	stack<BiTree> nodeBuffer;
	vector<char> result;
	nodeBuffer.push(T);
	while(!nodeBuffer.empty()){
		BiTree node = nodeBuffer.pop();
		if(node == NULL)
			continue;
		result.push_back(node.data);
		nodeBuffer.push(node.Lchild);
		nodeBuffer.push(node.Rchild);
	}	
	reverse(result.begin(),result.end());
	printf(result);
}
/*实现二叉树的层次遍历算法*/

2.二叉搜索树(BST)

  • 二叉搜索树,又称二叉排序树,若不为空树,则具有以下性质:
    • 若其左子树不为空,则左子树上所有结点的值均小于它的根结点的值。
    • 若其右子树不为空,则右子树上所有结点的值均大于它的根结点的值。
    • 它的左、右子树均为二叉搜索树。
        构造一棵二叉搜索树的目的,并不是为了排序,而是为了提高查找和插入删除关键字的速度。一般使用平衡二叉搜索树进行查找的算法,其时间复杂度为O(logN) 。
/*二叉树的结点结构定义*/
typedef struct BiTNode{
	int data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
/*查找二叉搜索树中是否存在key*/
bool SearchBST(BiTree T, int key){
	if(!T)
		return false;
	else if(key == T->data)
		return true;
	else if(key < T->data)
		return SearchBST(T->lchild, key);
	else
		return SearchBST(T->rchild, key);
}

二叉搜索树的插入、删除操作

3.平衡二叉树(AVL树)

  • 定义:平衡二叉树是一种高度平衡的二叉排序树,所谓高度平衡,指的是每个结点的左子树和右子树的高度差至多为1.
  • 我们将二叉树上左子树深度减去右子树深度的值称为平衡因子BF(Balance Factor),那么平衡二叉树上所有结点的平衡因子只可能是-1,0,1。只要二叉树的平衡因子绝对值大于1 ,那么它就不是平衡的。

平衡二叉树的实现原理和实现算法

4.多路查找树

  我们前述的树形结构,每个结点可以有多个孩子,但自身只能存储一个元素,二叉树限制更多,结点最多只有两个孩子。这种情况,对于元素非常多的情况来说,要么是数的度非常大,要么是树的高度非常高,甚至两者都比较大才能满足要求。想象一种情景,需要在磁盘上级是个文件中找到一个文本文件,为了降低对设备的访问次数,我们就需要新的数据结构来处理这样的问题。为此,引入了多路查找树。
  多路查找树,其每一个结点的孩子数可以多于两个,且每一个结点处可以存储多个元素。由于它是查找树,所有元素之间存在某种特定的排序关系。在此,每个结点可以存储多少个元素,以及它的孩子数是多少非常关键。下面了解B树的四种形式:2-3树、2-3-4树、B树、B+树。

4.1 2-3树

  2-3树的每个结点都具有两个孩子(称为2结点)或者三个孩子(称为3结点)。

  • 一个2结点包含一个元素和两个孩子(或者没有孩子)。与二叉排序树相似,左子树包含的元素小于该元素,右子树包含的元素大于该元素。不过,与二叉树不同的是,2结点要么没有孩子,要么有两个孩子,不能只有一个。
  • 一个3结点包含一小一大两个元素和三个孩子(或者没有孩子)。一个3结点要么没有孩子,要么有三个孩子。若有三个孩子,左子树包含的元素小于较小元素;右子树包含的元素大于较大元素;中间子树包含的元素的大小界于两个元素之间。
  • 2-3树中所有叶子杰店都位于同一层。如图所示:
    在这里插入图片描述
      2-3树的复杂性在于结点的cherub和删除,因为要求每个结点必须为2结点或者3结点,且所有叶子位于同一层,所以在发生结构变化时,其调整过程比较复杂。
    2-3树的插入实现、删除实现

4.2 2-3-4树

  2-3-4树是在2-3树的基础上,扩展了4结点,一个4结点包含三个元素和四个孩子(或者没有孩子),要么没有孩子,要么有4个还在。若有4个孩子,左子树包含的元素小于最小元素;第二子树包含的元素大于最小元素,小于第二元素;第三子树包含的元素大于第二元素,小于最大元素;右子树包含的元素大于最大元素。
2-3-4树的构建

4.3 B树

  B树(B-Tree)是一种平衡的多路查找树,2-3树和2-3-4树都是B树的特例。结点最大的孩子数目称为B树的阶。所以2-3树的阶是3,2-3-4树的阶是4。
  一个阶为m的B树的性质:

  • 如果根结点不是叶子,那么至少有两个子树。
  • 每一个非根节点都有k-1个元素和k个孩子,k<=m。
  • 所有叶子结点位于同一层。
      在B树上查找的过程是一个顺指针查找结点和在节点中查找关键字的交替过程。所有结点都保存元素和指针,除了叶子结点的指针为空。
    在这里插入图片描述

4.4 B+树

  B+树是应文件系统所需而出现的一种树,是B树的变形。在B树中,每个元素只在该树中出现一次,有可能出现在叶子结点,也有可能出现在分支结点。而在B+ 树中,出现在分支结点中的元素还会在其子结点中再次出现。另外,每个叶子结点都会保存一个指向后一子结点的指针。
在这里插入图片描述
 &emsp一棵m阶的B+树与B树的区别在于:

  • 有n棵子树的结点中包含n个关键字。而B树有n个关键字的结点(非叶子)有n+1个子树。
  • 所有的叶子结点包含全部关键字的信息,及指向这些关键字记录的指针、叶子结点本身依照关键字大小从小到大顺序连接。
  • 所有分支结点可以看成是索引,结点中仅含有其子树中的最大或最小关键字。

  每一次随机查找都只能从根结点出发,分支结点中找到的关键字,只用做索引,不提供实际记录的访问,访问需要到达包含此关键字的终端节点。如若需要从小到大遍历所有关键字,则可以从叶子结点最左端的指针出发,不经过分支结点。这一点比B树方便很多。B+树适用于带有范围的查找。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值