树型结构:
1,树的基本概念
一种表示层次关系(一对多)的数据结构
有且只有一个特定的节点,该节点没有前驱节点,被称为根节点 root
剩余的n个互不相交的子集,其中每个子集也都是一棵树,都被称为根节点的子树
tap:树形结构具有递归性(树中有树)
2,树的表示方式
倒悬树、嵌套法、凹凸法
3,树的专业术语
节点:组成一棵树的基础元素,同时他也是一棵树
节点的度:该节点子树的数量
树的度:树中所有节点的度的最大值
树的密度:树中所有节点的数量
树的深度(高度):树的最大层次数(从1开始)
节点的层次:根节点的层次为1,它的孩子层次为2,它的孩子的孩子层次为3,以此类推
叶子节点:节点的的度为0的节点
双亲节点和孩子节点:节点的子树被称为该节点的孩子节点,该节点就是孩子节点的双亲节点
兄弟节点:具有同一个双亲节点的节点互为兄弟节点
堂兄弟:双亲节点互为兄弟节点
祖先:从根节点出发到该节点,路径上经过的所有节点都称为该节点的祖先
子孙:一个节点的子树中任意一个节点都是它的子孙
4,树的存储
树可以顺序存储、链式存储,还可以混合存储
可以根据存储的信息不同,树可以有以下存储方式:
双亲表示法: 顺序
位置 data 双亲下标
0 A -1
1 B 0
2 C 0
3 D 1
4 E 1
5 F 1
6 G 2
7 H 4
优点:方便找到双亲
缺点:查找孩子节点麻烦
孩子表示法:
顺序:
位置 data son_arr(存储子节点的数组)
0 A 1,2
1 B 3,4,5
2 C 6
3 D
4 E 7
5 F
6 G
7 H
优点:查找孩子节点方便
缺点:找双亲不方便,浪费内存
链式:
位置 data listHead(存储子节点的链表)
0 A 1->2
1 B 3->4->5
2 C 6
3 D N
4 E 7
5 F N
6 G N
7 H N
优点:查找孩子节点方便,节约内存
缺点:找双亲不方便
兄弟表示法:
链式
双亲只存储第一个子节点 数据 链式指向所有的兄弟节点
优点:可以方便找到所有的兄弟节点
缺点:找双亲麻烦
tap:普通树不常用,所以使用二叉树
二叉树:
一种常见的数据结构,比普通树处理起来要简单,而且树也比较简单转换成二叉树
定义: 节点的度最多为2的树型结构
二叉树是n个有限元素的集合,该集合或者为空、或者由一个称为根(root)的元素及两个不相交的、
被分别称为左子树和右子树的二叉树组成,是有序树。当集合为空时,称该二叉树为空二叉树。在二叉树中,
一个元素也称作一个节点。
特殊的二叉树类型:
满二叉树:每层的节点数都是2^(i-1) (i>=1)为层数
完全二叉树:叶子结点只能出现在最下层和次下层,且最下层的叶子结点集中在树的左部。需要注意的是
满二叉树肯定是完全二叉树,而完全二叉树不一定是满二叉树。
二叉树的重要性质:
性质1:二叉树的第i层上至多有2^(i-1) (i≥1)个节点
性质2:深度为h的二叉树中至多含有2^h-1个节点
性质3:若在任意一棵二叉树中,有n0个叶子节点,有n2个度为2的节点,则必有n0=n2+1 到
性质4:具有n个节点的满二叉树深为log2n+1。
性质5:若对一棵有n个节点的完全二叉树进行顺序编号(1≤i≤n),那么,对于编号为i(i≥1)的节点:
当i=1时,该节点为根,它无双亲节点
当i>1时,该节点的双亲节点的编号为i/2
若2i≤n,则有编号为2i的左节点,否则没有左节点
若2i+1≤n,则有编号为2i+1的右节点,否则没有右节点
ABCD#EF#G##H
二叉树的操作:
构建、销毁、遍历、高度、密度、插入、删除、查询、求左、求右、求根
二叉树的存储:
顺序存储:必须要按照完全二叉树的格式,把每个节点按照从上到下、从左到右顺序依次存入连续内存
如果有空位置则使用特殊数据代替存入
数据项:
存储节点内存的首地址
容量
链式存储:由一个个的链式节点组成,每个节点就是一棵树
节点数据项:
数据
左子树指针
右子树指针
二叉树的遍历:
前序遍历:根、左、右
中序遍历:左、根、右
后序遍历:左、右、根
tap:前、中、后序由根节点决定,并且左右子树的遍历顺序不会改变,通过前序+中序 或者 后续+中序 就可以还原一棵树
层序遍历:从上到下、从左到右依次遍历 配合队列
有序二叉树的各功能实现
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
//有序二叉树
typedef struct TreeNode
{
int data;
struct TreeNode* left;
struct TreeNode* right;
}TreeNode;
//创建
TreeNode* create_tree_node(int data)
{
TreeNode* node = malloc(sizeof(TreeNode));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
//加入依赖
void _insert_tree(TreeNode** root,TreeNode* node)
{
if(NULL == *root)
{
*root = node;
return;
}
if(node->data < (*root)->data)
_insert_tree(&((*root)->left),node);
else
_insert_tree(&((*root)->right),node);
}
//插入
void insert_tree(TreeNode** root,int data)
{
_insert_tree(root,create_tree_node(data));
}
//中序遍历 排序 从小到大
void ldr_show(TreeNode* root)
{
if(NULL == root) return;
ldr_show(root->left);
printf("%d ",root->data);
ldr_show(root->right);
}
void dlr_show(TreeNode* root)
{
if(NULL == root) return;
printf("%d ",root->data);
dlr_show(root->left);
dlr_show(root->right);
}
void lrd_show(TreeNode* root)
{
if(NULL == root) return;
lrd_show(root->left);
lrd_show(root->right);
printf("%d ",root->data);
}
//查找
bool query_tree(TreeNode* root,int data)
{
if(NULL == root) return false;
if(root->data == data) return true;
if(data < root->data)
query_tree(root->left,data);
else
query_tree(root->right,data);
}
//密度
int density_tree(TreeNode* root)
{
if(NULL == root) return 0;
return density_tree(root->left)+density_tree(root->right)+1;
}
//高度
int high_tree(TreeNode* root)
{
if(NULL == root) return 0;
int lh = density_tree(root->left);
int rh = density_tree(root->right);
return lh>rh?lh+1:rh+1;
}
//销毁
void destory_tree(TreeNode* root)
{
if(NULL == root) return;
destory_tree(root->left);
destory_tree(root->right);
free(root);
}
bool _access_tree(TreeNode* root,int* cnt,size_t index,int* ptr)
{
if(NULL == root) return false;
bool lfalg = _access_tree(root->left,cnt,index,ptr);
if(lfalg) return true;
if((*cnt)++ == index)
{
*ptr = root->data;
}
return _access_tree(root->right,cnt,index,ptr);
}
//按中序访问
bool access_tree(TreeNode* root,size_t index,int* ptr)
{
int cnt = 0;
return _access_tree(root,&cnt,index,ptr);
}
//按值删除
bool del_value_tree(TreeNode** root,int data)
{
if(NULL == *root) return false;
if(data == (*root)->data)
{
TreeNode* temp = *root;
*root = temp->left;
_insert_tree(root,temp->right);
free(temp);
return true;
}
if(data < (*root)->data)
return del_value_tree(&(*root)->left,data);
else
return del_value_tree(&(*root)->right,data);
}
链式二叉树的功能实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define TREE_TYPE char
#define EMPTY '#'
#define END '\0'
//设计树的节点
typedef struct TreeNode
{
TREE_TYPE data;
struct TreeNode* left;
struct TreeNode* right;
}TreeNode;
//创建树节点
TreeNode* creatr_tree_node(TREE_TYPE data)
{
TreeNode* node = malloc(sizeof(TreeNode));
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
/*
//构建二叉树 构建前序 ABC#G###DE##F##
TreeNode* create_tree(void)
{
TREE_TYPE data = 0;
scanf("%c",&data);
if(EMPTY == data) return NULL;
TreeNode* node = creatr_tree_node(data);
node->left = create_tree();
node->right = create_tree();
return node;
}*/
//构建依赖
TreeNode* _create_tree(TREE_TYPE** str)
{
if(EMPTY == **str || END == **str) return NULL;
TreeNode* node = creatr_tree_node(**str);
*str+=1;
node->left = _create_tree(str);
*str+=1;
node->right = _create_tree(str);
return node;
}
TreeNode* create_tree(TREE_TYPE* str)
{
TreeNode* node = _create_tree(&str);
return node;
}
//前序遍历
void dlr_show(TreeNode* root)
{
if(NULL == root) return;
printf("%c",root->data);
dlr_show(root->left);
dlr_show(root->right);
}
//中序遍历
void ldr_show(TreeNode* root)
{
if(NULL == root) return;
ldr_show(root->left);
printf("%c",root->data);
ldr_show(root->right);
}
//后序遍历
void lrd_show(TreeNode* root)
{
if(NULL == root) return;
lrd_show(root->left);
lrd_show(root->right);
printf("%c",root->data);
}
//树的高度
int high_tree(TreeNode* root)
{
if(NULL == root) return 0;
int lh = high_tree(root->left);
int rh = high_tree(root->right);
return lh>rh?lh+1:rh+1;
}
//树的密度
int denstity_tree(TreeNode* root)
{
if(NULL == root) return 0;
return denstity_tree(root->left)+denstity_tree(root->right)+1;
}
//求左子树
TreeNode* left_tree(TreeNode* root,TREE_TYPE data)
{
if(NULL == root) return NULL;
if(data == root->data) return root->left;
TreeNode* lnode = left_tree(root->left,data);
if(NULL != lnode) return lnode;
TreeNode* rnode = left_tree(root->right,data);
return rnode;
}
//插入
bool insert_tree(TreeNode* root,TREE_TYPE pdata,TREE_TYPE data)
{
if(NULL == root) return false;
if(root->data == pdata)
{
if(NULL == root->left)
{
return root->left = creatr_tree_node(data);
}
if(NULL == root->right)
{
return root->right = creatr_tree_node(data);
}
}
bool lfalg = insert_tree(root->left,pdata,data);
bool rfalg = insert_tree(root->right,pdata,data);
return lfalg || rfalg;
}
//删除 只删除叶子节点
bool del_tree(TreeNode** root,TREE_TYPE data)
{
if(NULL == *root) return false;
if((*root)->data == data)
{
if((*root)->left || (*root)->right) return false;
free(*root);
*root = NULL;
return true;
}
bool lfalg = del_tree(&(*root)->left,data);
bool rfalg = del_tree(&(*root)->right,data);
return lfalg || rfalg;
}
//销毁
void destory_tree(TreeNode* root)
{
if(NULL == root) return;
destory_tree(root->left);
destory_tree(root->right);
free(root);
}