树与二叉树
树与二叉树
目录
基本概念
树是一种非线性结构,一组数据中除了第一个节点,任意节点有且仅有一个直接前驱,有零哥=个或多个直接后驱,该组数据形成了一棵树,为一对多的数据关系。
基本术语
根
树的第一个节点,没有直接前驱。
双亲结点
某节点的直接前驱节点称为该节点的双亲节点。
孩子节点
某节点的直接后继节点称为孩子节点。
节点的层次
根节点点所在节点规定为第一层,其孩子所在层次称为第二层,以此类推。
节点的度
一个节点拥有的孩子节点的总数,称为该节点的度。
叶子
一棵树中结点的度等于0的节点,称为叶子,又叫终端节点。
树的高度
一棵树中所有节点的层次的最大值,称为这棵树的高度,又叫深度。
有序树与无序树
一棵树中,如果某个节点孩子节点之间是有序的(不可进行交换),称为有序树,否则为无序树。
二叉树
二叉树概念:
1.有序树
2.任意节点的度小于等于2(一个节点最多两个孩子)
二叉树基本特性
1.第I层上,最多有2^(i-1)个节点
2.高度为k的二叉树,最多有2^(k-1)个节点。
3.叶子数目为n0,度为2的的节点的节点数目为n2。则有n0=n2+1。
满二叉树/完美二叉树:
高度为K的树,节点总数为2^k-1.
完全二叉树:
节点标号连续(从上到下,从左到右)
平衡二叉树:
任意节点的两棵子树高度差小于一。
退化二叉树:
所有节点的度小于等于1,退化为链表。
二叉树的链式存储
typedef struct node
{
datatype data; // 用户数据 数据域
struct node *lchild; // 左孩子树指针
struct node *rchild; // 右孩子树指针
}node;
树的遍历
前序遍历(根---左---右)、中序遍历(左--根---右)、后序遍历(左---右---根)。
按层遍历:从上到下,从左到右依次访问节点
前中后序遍历都是递归算法。
BST树
基本概念
搜索二叉树/二叉排序树/二叉查找树:将数据节点按照某种规律形成的一颗二叉树
提高搜索效率:小中大的归率存储/大中小
插入节点
// 假设 BST 节点存储的数据类型是 int
node *newNode(int data)
{
// 准备好新节点,并将数据填入其中
node *new = (node *)malloc(sizeof(node));
if(new != NULL)
{
new->data = data;
new->lchild = NULL;
new->rchild = NULL;
}
return new;
}
// 将新节点new插入到一棵以 root 为根的 BST 中
// 插入节点后,返回新的 BST 的根
node *bstInsert(node *root, node *new)
{
// 若此时 BST 为空,则返回 new 使之成为二叉树的根节点
if(root == NULL)
return new;
// 若新节点比根节点小,那么新节点应该插入左子树中
// 至于插入到左子树的具体什么位置就不用管了,直接递归即可
if(new->data < root->data)
root->lchild = bstInsert(root->lchild, new);
// 若新节点比根节点大,那么新节点应该插入右子树中,直接递归即可
else if(new->data > root->data)
root->rchild = bstInsert(root->rchild, new);
// 若已存在,则不处理 数据不允许相同
else
{
printf("%d已存在\n", new->data);
free(new);
}
return root;
}
删除节点
// 将数据(以整型为例)data从二叉树中删除
// 并返回删除之后的二叉树的根
node *bstRemove(node *root, int data)
{
node *tmp = NULL;
if(root == NULL)
return NULL;
// 若data小于根节点,则递归地在左子树中删除它
if(data < root->data)
root->lchild = bstRemove(root->lchild, data);
// 若data小于根节点,则递归地在左子树中删除它
else if(data > root->data)
root->rchild = bstRemove(root->rchild, data);
//找到相同的数据
else
{
// a. 根节点若有左子树,则用左子树中最大的节点max替换根节点
// 并在左子树中递归删除max
if(root->lchild != NULL)
{
node *max;
for(max=root->lchild; max->rchild!=NULL;
max=max->rchild);
root->data = max->data;
root->lchild = bstRemove(root->lchild, max->data);
}
// b. 否则,若有右子树,则用右子树中最小的节点min替换根节点
// 并在右子树中递归删除min
else if(root->rchild != NULL)
{
for(tmp=root->rchild; tmp->lchild!=NULL;
tmp=tmp->lchild);
root->data = tmp->data;
root->rchild = bst_remove(root->rchild, tmp->data);
}
// c. 否则,直接删除节点
else
{
free(root);
return NULL;
}
}
return root;
}
遍历代码
// 前序遍历
void preOrder(node *root)
{
if(root == NULL)
return;
// 先访问根节点
printf("%d", root->data);
// 再依次使用前序算法,遍历其左、右子树
preOrder(root->lchild);
preOrder(root->rchild);
}
// 中序遍历
void inOrder(node *root)
{
if(root == NULL)
return;
// 先访问左子树
inOrder(root->lchild);
// 再访问根节点
printf("%d", root->data);
// 再访问右子树
inOrder(root->rchild);
}
// 后序遍历
void postOrder(node *root)
{
if(root == NULL)
return;
// 先依次使用后序算法,遍历其左、右子树
postOrder(root->lchild);
postOrder(root->rchild);
// 再访问根节点
printf("%d", root->data);
}