二叉查找树(二叉排序树)学习笔记

本文转载自:http://blog.csdn.net/qq_37887537/article/details/75647670


在学习数据结构的时候,除了基本的之外的,还有许多树像是二叉搜索树,2-3树,红黑树等等。

也曾经学习过二叉树,以及前序排列中序排列后序排列等等,但是一直无缘使用它!

排序有快速排序,归并排序,查找有二分法,甚至直接遍历查找,二叉树的使用很少。那二叉树究竟是干什么的呢?

进行了一番粗浅的研究,我们学习的经典二叉树,仅仅当他是一种数据结构是不行的,他还是一种编程思想,例如解决背包问题(后面进行学习),在考试和面试中使用较多。

而实际场景使用上,用的最多的是二叉平衡树,有种特殊的二叉平衡树就是红黑树,Java集合中的TreeSet和TreeMap,C++STL中的set、map以及Linux虚拟内存的管理,都是通过红黑树去实现的,还有哈弗曼树编码方面的应用,以及B-Tree,B+-Tree在文件系统中的应用。当然二叉查找树可以用来查找和排序啦(知乎网友)。


那么二叉树有什么优点?

大家看到最多的是这么说的,二叉排序树是一种比较有用的折中方案:

数组的搜索比较方便,可以直接使用下标,但删除或者插入就比较麻烦了,而链表与之相反,删除和插入都比较简单,但是查找很慢,这自然也与这两种数据结构的存储方式有关,数组是取一段相连的空间,而链表是每创建一个节点便取一个节点所需的空间,只是使用指针进行连接,空间上并不是连续的。而二叉树就既有链表的好处,又有数组的优点。


二叉树的分类,了解一下

满二叉树:从高到低,除了叶节点外,所以节点左右节点都存在。

完全二叉树:比满二叉树少几个叶节点,从左向右放子节点。

平衡二叉树:空树或者它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树也都是平衡树。

二叉搜索树:空树或者二叉树的所有节点比他的左子节点大,比他的右子节点小。

红黑树:不仅是具有二叉搜索树的属性,还具有平衡树的属性,有序且子树差不超过1,颜色规则:根节点和特殊节点(即叶节点下面两个虚无的节点和未填写的节点)是黑的,红节点的左右子节点是黑的,最重要的是对于每个节点,从该节点到子孙叶节点的所有路径包含相同数目的黑节点。


今天就学习一下最简单的二叉排序树

二叉排序树又叫二叉查找树或者二叉搜索树,它首先是一个二叉树,而且必须满足下面的条件:

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

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

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


这种特殊的结构二叉树,采用中序遍历左根右)即可获得一个有序数组。

在网上找到的一个基础图形:

前序遍历(根-左-右):ABDGHECKFIJ
中序遍历(左-根-右):GDHBEAKCIJF
后序便利(左-右-根):GHDEBKJIFCA

二叉搜索树的数据关系:G<D<H<B<E<A<K<C<I<J<F

实现方法也比较干净利落 

void PreOrderTraverse(BiTree root)	// 先序遍历
{
	if(root){
		printf("%d",root->value);
		PreOrderTraverse(root->lchild);
		PreorderTraverse(root->rchild);
	}
}

void InOrderTraverse(BiTree root)	// 中序遍历
{
	if(root){
		InOrderTraverse(root->lchild);
		printf("%d",root->value);
		InOrderTraverse(root->rchild);
	}
}

void PostOrderTraverse(BiTree root)	// 后序遍历
{
	if(root){
		PostOrderTraverse(root->lchild);
		PostOrderTraverse(root->rchild);
		printf("%d",root->value);
	}
}

接着就是关于创建一个二叉搜索树的过程,这里没有将相同的数字屏蔽掉:

#include <iostream>
using namespace std;

// BST的节点
typedef struct node{
	node( int element, node *lt, node *rt)
	 : key{ element }, lChild{ lt }, rChild{ rt } { }
	int key;
	struct node *lChild;
	struct node *rChild;
}Node, *BST;

// 在给定的BST中插入节点,其数据域为element,使之称为新的BST
bool BSTInsert(BST &p, int element){
	if(p==nullptr){
		p = new Node(element,nullptr,nullptr);
		return true;
	}
	
//	if(element == p->key)	// BST中不能有相等的值,不注释掉会屏蔽掉相同的树
//		return false;
	
	// 递归
	if(element < p->key)
		return BSTInsert(p->lChild, element);
	else
		return BSTInsert(p->rChild, element);
}

// 先序遍历(根-左-右)
void preOrderTraverse(BST T){
	if(T){
		cout << T->key << ends;
		preOrderTraverse(T->lChild);
		preOrderTraverse(T->rChild);
	}
}
// 中序遍历(左-根-右)
void inOrderTraverse(BST T){
	if(T){
		inOrderTraverse(T->lChild);
		cout << T->key << ends;
		inOrderTraverse(T->rChild);
	}
}
// 后序遍历(左-右-根)
void postOrderTraverse(BST T){
	if(T){
		postOrderTraverse(T->lChild);
		postOrderTraverse(T->rChild);
		cout << T->key << ends;
	}
}

int main(){
	int a[13] = {4,5,2,1,0,12,3,7,6,8,5,4,7};
	int n = 13;
	BST T = nullptr;
	int i;
	for(i=0;i<n;++i){
		BSTInsert(T, a[i]);
	}
	inOrderTraverse(T);
	
	cout << endl;
	
	BSTInsert(T,11);
	inOrderTraverse(T);
	cout << endl;
	
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值