当前位置:   article > 正文

数据结构与算法详解——二叉查找树篇(附c++实现代码)_二叉树查找结点算法

二叉树查找结点算法

二叉树相关概念和术语

  二叉树的递归定义为:二叉树是一棵空树,或者是一棵由一个根节点和两棵互不相交的,分别称作根的左子树和右子树组成的非空树;左子树和右子树又同样都是二叉树。

  • 度:一个节点拥有子树的数目称为结点的度,叶子结点的度为0。
  • 叶子结点:也称为终端结点,没有子树的结点或者度为零的结点。
  • 结点的层次:从根结点开始,假设根结点为第1层,根节点的子结点为第2层,依此类推,如果某一个结点位于第L层,则其子结点位于第L+1层。
  • 二叉树结点的深度:指从根节点到该结点的最长简单路径边的条数。
  • 二叉树结点的高度:指从该节点到叶子结点的最长简单路径边的条数。

在这里插入图片描述
  结点A的度为2,结点C的度为1,叶子结点为GHIJKL,度都为0。
  结点的高度,深度,层数如图(注意高度和深度有的地方从0开始计数,有的地方从1开始计数)

二叉树特殊类型

在这里插入图片描述
  斜树不多赘述,一般是退化成链表的形式时导致性能下降的情形。
  完全二叉树:深度为k,有n个节点的二叉树当且仅当其每一个节点都与深度为k的满二叉树中编号从1到n的节点一一对应时,称为完全二叉树(叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部)。
  满二叉树:如果一棵二叉树只有度为0的节点和度为2的节点,并且度为0的节点在同一层上。满二叉树是完全二叉树,完全二叉树不一定是满二叉树。

二叉树的存储

链式存储

template <typename T>
struct treeNode {
   
	T data;
	treeNode<T>* left;
	treeNode<T>* right;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

  结点的定义:存储的数据,左子树指针,右子树指针。

顺序存储

  我们把结点存储在数组中,父节点存储在下标为i的位置,那么左子树存储在2*i的位置,右子树存储在2*i+1的位置。举个例子,假设根结点存储在下标为i=1的位置,那么根结点的左子树存储在2*i=2的位置,根结点的右子树存储在2*i+1=3的位置,以此类推。
在这里插入图片描述
  上图是一颗完全二叉树,使用顺序存储存储率就比较高,或者说空间利用率比较高。假设上图没有结点F,那么下标为6的位置就置空,不存储数据。

二叉树的遍历

  • 前序遍历是指,对于树中的任意节点来说,先打印这个节点,然后再打印它的左子树,最后打印它的右子树。
  • 中序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它本身,最后打印它的右子树。
  • 后序遍历是指,对于树中的任意节点来说,先打印它的左子树,然后再打印它的右子树,最后打印这个节点本身。

  以上面顺序存储中的完全二叉树为例子,

  • 前序遍历:ABDHIECFG
  • 中序遍历:HDIBEAFCG
  • 后序遍历:HIDEBFGCA

  递归实现

void preOrder(Node* root) {
   
  if (root == null) return;	//递归结束条件
  std::cout<<root->data<<std::endl;
  preOrder(root->left);
  preOrder(root->right);
}
 
void inOrder(Node* root) {
   
  if (root == null) return; //递归结束条件
  inOrder(root->left);
  std::cout<<root->data<<std::endl;
  inOrder(root->right);
}
 
void postOrder(Node* root) {
   
  if (root == null) return; //递归结束条件
  postOrder(root->left);
  postOrder(root->right);
   std::cout<<root->data<<std::endl;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

二叉查找树

  二叉查找树又叫二叉搜索树,二叉排序树。
  对于树中任意一个结点,左子树中的每一个结点的值都小于这个结点的值,右子树中的每一个结点的值都大于这个结点的值。下图就是一个二叉查找树的例子,可以看到根结点的左子树中每一个结点都小于12,根结点右子树中每一个结点都大于12。
在这里插入图片描述

查找

  假设我们要查找的值为value,我们从根结点开始,比较结点的值和value的大小:

  • 如果结点的值等于value,返回
  • 如果结点的值比value小,那么在左子树递归查找
  • 如果结点的值比value大,那么在右子树递归查找
template<typename T>
treeNode<T>* binarySearchTree<T>::find(T data) {
   
	treeNode<T>* n = root;
	while (n != nullptr) {
   
		if (data > n->data)n = n->right;
		else if (data < n->data)n = n->left;
		else return n;
	}
	return nullptr;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

  这里使用了非递归的写法,逻辑应该是比较清晰了。

插入

  插入就是查找到一个能插入的位置,所以和上面查找的过程很类似。
  假设我们要插入的值为value,我们从根结点开始,比较结点的值和value的大小:

  • 如果结点的值比value小,那么就看结点的右子树是否为空,如果为空就将value插入到结点的右子树,如果不为空就在右子树递归插入
  • 如果结点的值比value大,那么就看结点的左子树是否为空,如果为空就将value插入到结点的左子树,如果不为空就在左子树递归插入
template<typename T>
void binarySearchTree<T>::insert(T data) {
   
	
  • 1
  • 2
  • 3
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/245881
推荐阅读
相关标签
  

闽ICP备14008679号