二叉树: 二叉树是每个节点最多有两个子树的树结构。二叉树可以是空集;根可以有空的左子树或右子树;或者左、右子树皆为空。
满二叉树: 高度为h,并且由2{h} –1个结点的二叉树,被称为满二叉树。
完全二叉树: 一棵二叉树中,只有最下面两层结点的度可以小于2,并且最下一层的叶结点集中在靠左的若干位置上。这样的二叉树称为完全二叉树。一棵满二叉树必定是一棵完全二叉树,而完全二叉树未必是满二叉树。
二叉查找树: 二叉排序树又称二叉查找树,亦称二叉搜索树
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
- (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- (3)左、右子树也分别为二叉排序树;
- (4)没有键值相等的节点。
B树:B树是一种多路搜索树(并不是二叉的),主要用于提升硬盘上数据的存储和读取速度,可以减少访问磁盘的次数。
B+树:B+树把存储值的节点全部放在了叶子节点,使叶子节点最后形成了一个有序的链表。进一步提升了读取速度。
B*树:是B+树的变体,在B+树的非根和非叶子节点增加指向的兄弟的指针。
平衡二叉搜索树:平衡二叉搜索树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树。
二叉树遍历
- 前序遍历(根-左-右):ABDGHECKFIJ
- 中序遍历(左-根-右):GDHBEAKCIJF
- 后序便利(左-右-根): GHDEBKJIFCA
二叉排序树基本操作
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct TreeNode{
int data;
struct TreeNode *left, *right;
}Tree, *PTree;//定义树节点的结构体
//创建只有一个根结点的二叉树
PTree create(int value){
PTree pt = (PTree)malloc(sizeof(Tree));
pt->data=value;
pt->left=pt->right=NULL;
return pt;
}
//在二叉树中插入结点, 需要使用二级指针
void createBiTree(PTree *p, int value){
if(*p == NULL){
*p = (PTree)malloc(sizeof(Tree));
(*p) -> data = value;
(*p) -> left = (*p)-> right =NULL;
return;
}
if((*p)->data == value){
return;
}
else{
if((*p)->data > value){
return createBiTree(&(*p) -> left,value);
}
else{
return createBiTree(&(*p) -> right,value);
}
}
}
//前序打印
void pre_read_tree(PTree p){
if(p==NULL){return;}
else{
printf("%d\n",p->data);
pre_read_tree(p->left);
pre_read_tree(p->right);
}
}
//中序打印
void mid_read_tree(PTree p){
if(p==NULL){return;}
else{
pre_read_tree(p->left);
printf("%d\n",p->data);
pre_read_tree(p->right);
}
}
//后序打印
void rear_read_tree(PTree p){
if(p==NULL){return;}
else{
pre_read_tree(p->left);
pre_read_tree(p->right);
printf("%d\n",p->data);
}
}
//查找元素
PTree find_node(PTree tree, int value){
if(tree==NULL){
return NULL;
}
if(tree->data == value){
return tree;
}
else{
if(value<tree->data){
find_node(tree->left,value);
}
else{
find_node(tree->right,value);
}
}
}
//清空整棵树
PTree clean_tree(PTree tree){
if(tree!=NULL){
clean_tree(tree->left);
clean_tree(tree->right);
free(tree);
}
return NULL;
}
//查找二叉排序树的最大值
PTree max_BTree(PTree tree){
if(tree ==NULL){
return NULL;
}
else{
if(tree->right==NULL){
return tree;
}
else{
return max_BTree(tree->right);
}
}
}
//查找二叉排序树的最小值
PTree min_BTree(PTree tree){
if(tree ==NULL){
return NULL;
}
else{
if(tree->left==NULL){
return tree;
}
else{
return min_BTree(tree->left);
}
}
}
//判断两颗树是否相等(没有判断左右互换相等)
int compare_tree(PTree tree1, PTree tree2){
if(tree1==NULL&&tree2==NULL){
return 1;
}
if((tree1==NULL)!=(tree2==NULL)){
return 0;
}
if(tree1->data!=tree2->data){
return 0;
}
return compare_tree(tree1->left,tree2->left)&&compare_tree(tree1->right,treee2->right)
}
int main(){
PTree pt =create(0);
createBiTree(&pt,5);
createBiTree(&pt,6);
createBiTree(&pt,7);
createBiTree(&pt,4);
//pre_read_tree(pt); //前序打印
//mid_read_tree(pt); //中序打印
//rear_read_tree(pt); //后序打印
//pt = find_node(pt,4);
pt = clean_tree(pt);
pre_read_tree(pt); //前序打印
}
霍夫曼树
哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度。
哈夫曼树的构建过程:
先把序列按从小到大排列,每次取出最小的前两个作为一棵树,类推递归。 例子参考: https://jingyan.baidu.com/article/a501d80c16dfa0ec620f5e70.html
霍夫曼编码
哈夫曼编码: 研究哈夫曼树这种最优树是为了解决数据压缩或传输的最优化问题。
对于一个字符串来说,里边每个字符出现的概率是不一样的,相当于权值不一样,可以用哈夫曼树解决。具体方法是:按照权值(出现概率)不同,把所有字符按照依据哈夫曼树排列,然后把哈夫曼树上所有左分支改为0,所有右分支改为1(即权值改为0和1),之后用从根结点到叶子所经过的路径上的0和1来编码叶子上的字符。