#define ElementType int
struct BinaryTreeNode
{
ElementType data;
struct BinaryTreeNode *left; //树的左孩子
struct BinaryTreeNode *right; //树的右孩子
struct BinaryTreeNode *parent; //树的双亲
};
typedef struct BinaryTreeNode BTNode;
1.树:元素之间具有分层类似的结构,由于结构特征,常采用递归方式定义。
树的定义:除根结点外,每个结点有一个前驱结点,除叶子外,每个结点都有至少一个后驱结点。
基本术语:
结点:树中的元素,
路径:从根结点到叶子是一条路径,每棵树有多条路径。
双亲:每个结点的前驱称为该结点的双亲,根结点没有双亲。
孩子:每个结点的子节点,即它的后驱称为该结点的孩子,叶子没有孩子。
兄弟:有相同双亲的结点互为兄弟。
后裔:一个结点的所以子数都为该结点的后裔。
祖先:从根到该结点路径上的所以结点都是该结点的祖先,双亲也是它的祖先之一。
结点的度:结点拥有的后驱数(子节点数)
叶子:度为0的结点,没有后驱的节点,也可以说所有分支的最后一个结点都是叶子。
分支结点:度不为0的结点(不是叶子都是分支结点)
树的度:树中结点的最大的度,即为树的度。也可以说是树的最大分支数。
结点层次:根结点为1,其余为双亲层次加一,即本身为第几层。
树的高度:一棵树的最大层次。
int GetTreeHeight(BTNode* node)
{
if(node==NULL)
return 0;
int leftHeight=GetTreeHeight(node->left);
int rightHeight=GetTreeHeight(node->right);
return (leftHeight>rightHeight? leftHeight:rightHeight)+1;
}
无序树:任意子树之间的次序不重要,可以交换位置。
有序树:树中结点从左到右有次序的。
森林:是树的集合,0个或多个不相交的树组成森林。
2、二叉树
定义:结点的有限次数(可以为空)或是由一个根与两个互不相交的子树,称为该树的左子树与右子树
ps:树中可以有多颗子树,而二叉树最多只能有两个子树。
性质:二叉树最多可以有2n-1个节点,当n=0时,该树为空二叉树。
高度:包含n个元素的二叉树的高度至少为[log2(n+1)],并且,平衡二叉树的最大检索次数也为[log2(n+1)]。
叶子:叶子的个数一定比度为2的结点多1。
路径(边):路径(边)为n-1条。
满二叉树:高为n的二叉树恰为2n-1个结点的树
完全二叉树:只有最下两层结点的度可以小于二,且最小层集中在左边。
完全二叉树高度[log2(n+1)]
- 遍历算法
先序遍历:先访问根,再遍历左子树,最后遍历右子树
void PrevPrint(BTNode *node)
{
if(node!=NULL)
{
printf("%d ",node->data);
PrevPrint(node->left);
PrevPrint(node->right);
}
}
中序遍历:先遍历左子树,再访问根,最后遍历右子树
void MidPrint(BTNode *node)
{
if(node!=NULL)
{
MidPrint(node->left);
printf("%d ",node->data);
MidPrint(node->right);
}
}
后序遍历:先遍历左子树,再遍历右子树,最后访问根
void PostPrint(BTNode *node)
{
if(node!=NULL)
{
PostPrint(node->left);
PostPrint(node->right);
printf("%d ",node->data);
}
}
- 平衡二叉树(AVL)(红黑树)
定义:左右子树的高度差不超过1。
左左插入:(在左子树的左边插入):右旋
BTNode* RotateRight(BTNode* node)
{
BTNode *t=node->left;
node->left=t->right;
t->right=node;
return t;
}
右右插入:(在右子树的右边插入):左旋
BTNode* RotateLeft(BTNode* node)
{
BTNode *t=node->right;
node->right=t->left;
t->left=node;
return t;
}
左右插入:(在左子树的右边插入)左右旋(先左旋再右旋)
BTNode* RotateLeftRight(BTNode* node)
{
node->left=RotateLeft(node->left);
return RotateRight(node);
}
右左插入:(在右子树的左边插入)右左旋(先右旋再左旋)
BTNode* RotateRightLeft(BTNode* node)
{
node->right=RotateRight(node->right);
return RotateLeft(node);
}
树的删除:
void DeleteElement(LBTree *tree, ElementType element)
{
BTNode *targetNode=SearchNode(tree->root,element);
if(targetNode==NULL)
return ;
if(targetNode->left==NULL&&targetNode->right==NULL)
{//如果左右子树都为空,判断本身为双亲的那边的子树,然后将指向待删结点的指针指向空
if(targetNode->parent->left==targetNode)
targetNode->parent->left=NULL;
else
targetNode->parent->right=NULL;
free(targetNode);
}
else if(targetNode->right==NULL)
{//如果右子树为空,判断本身为双亲的那边的子树,将待删结点的左子树指向待删结点的指针指向它的双亲,最后放掉内存
targetNode->left->parent=targetNode->parent;
if(targetNode->parent->left==targetNode)
targetNode->parent->left=targetNode->left;
else
targetNode->parent->right=targetNode->left;
free(targetNode);
}
else if(targetNode->left==NULL)
{//如果左子树为空,判断本身为双亲的那边的子树,将待删结点的右子树指向待删结点的指针指向它的双亲,最后放掉内存
targetNode->right->parent=targetNode->parent;
if(targetNode->parent->right==targetNode)
targetNode->parent->right=targetNode->right;
else
targetNode->parent->left=targetNode->right;
free(targetNode);
}
else if(targetNode->left!=NULL&&targetNode->right!=NULL)
{//如果左右子树都不为空,则找右子树的最小值
BTNode *MinNode=targetNode->right;
//不断向带删结点右子树的左子树遍历,直到个左子树指向空
while(MinNode->left!=NULL)
{
MinNode=MinNode->left;
}
//将右子树的最小值和待删结点的值替换
targetNode->data=MinNode->data;
if(MinNode->parent!=targetNode)
{//如果最小值的双亲不是待删结点,则指向最小值的指针指向最小值的右孩子
MinNode->parent->left=MinNode->right;
}
else
{
//如果最小值双亲为待删结点,即待删结点的右子树没有左孩子
直接将待删结点右孩子的指针指向最小值的右孩子
targetNode->right=MinNode->right;
}
free(MinNode);
}
}