如何在二叉树中定位结点的位置?
指路法定位结点:根据生活中的经历:左拐、右拐、左拐、、、
大致思路:
通过根结点与目标结点的相对位置进行定位,这种方法可以避开二叉树递归的性质“线性定位”
C描述:利用bit位进行指路
#define BT_LEFT 0
#define BT_RIGHT 1
typedef unsigned long BT_pos;
二叉树的操作:
创建树--b
tree_create
销毁树--b
tree_destroy
清空树--b
tree_clear
插入结点--b
tree_insert
删除结点--b
tree_delete
获取结点--b
tree_get
获取根结点--b
tree_root
获取树的结点数--b
tree_count
获取树的度--b
tree_degree
•插入结点:
/*参数说明
tree:待插入结点的二叉树
node:待插入的结点
pos: 进行“指路”的bit位
count:需要指路的次数
flag:考虑待插入的结点不在叶结点,而是替代二叉树中原有的一个结点进行插入操作,
此标志 用于标示被替换的结点与其子树应在插入结点的左边还是右边。
*/
int btree_insert(btree* tree, btree_node* node, bt_pos pos, int count, int flag)
{
head_node* btree_head_node = (head_node*)tree;
int ret = (btree_head_node != NULL) && (node != NULL) && ((flag == BT_LEFT) || (flag == BT_RIGHT));
int bit = 0;
if( ret )
{
btree_node* parent = NULL;
btree_node* current = btree_head_node->root;
node->left = NULL;
node->right = NULL;
while( (count > 0) && (current != NULL) )
{
bit = pos & 1;
pos = pos >> 1;
/*记录待插入结点的父结点的位置*/
parent = current;
if(bit == BT_LEFT)
{
current = current->left;
}
else if(bit == BT_RIGHT)
{
current = current->right;
}
count--;
}
if(flag = BT_LEFT)
{
node->left = current;
}
else if(flag = BT_RIGHT)
{
node->right = current;
}
if(parent != NULL)
{
/*由最后一步的指路判断插入结点在父结点的左边还是右边*/
if(bit == BT_LEFT)
{
parent->left = node;
}
else if(bit == BT_RIGHT)
{
parent->right = node;
}
}
else
{
/*此种情况为插入结点为根结点的情况*/
btree_head_node->root = node;
}
btree_head_node->count++;
}
return ret;
}
•打印函数:
要求体现二叉树的形状,左结点存在而右结点不存在的情况下,相应的也打印出右结点的格式。
实现代码:
/*参数说明:
node:打印的结点
p_func:打印函数
format :打印格式
div:格式字符
*/
static void recursive_display(btree_node *node, btree_printf* p_func, int format, char div)
{
int i = 0;
if((node != NULL) && (p_func != NULL))
{
for(i=0; i<format; i++)
{
printf("%c", div);
}
p_func(node);
printf("\n");
if((node->left != NULL) || (node->right != NULL))
{
recursive_display(node->left, p_func, format+2, div);
recursive_display(node->right, p_func, format+2, div);
}
}
else
{
for(i=0; i<format; i++)
{
printf("%c", div);
}
printf("\n");
}
}
void btree_display(btree* tree, btree_printf* p_func, char div)
{
head_node* btree_head_node = (head_node*)tree;
if(btree_head_node != NULL)
{
recursive_display(btree_head_node->root, p_func, 0, div);
}
}
•删除结点:
丢弃结点的子树的结点数
实现代码:
/*统计结点数量*/
static int recursive_count(btree_node* node)
{
int ret = 0;
if(node != NULL)
{
ret = recursive_count(node->left) + recursive_count(node->right) + 1;
}
return ret;
}
btree_node* btree_delete(btree* tree, bt_pos pos, int count)
{
head_node* btree_head_node = (head_node*)tree;
int bit = 0;
btree_node* ret = NULL;
if(btree_head_node != NULL)
{
btree_node* parent = NULL;
btree_node* current = btree_head_node->root;
while((count > 0) && (current != NULL))
{
bit = (pos & 1);
pos = (pos >> 1);
parent = current;
if(bit == BT_LEFT)
{
current = current->left;
}
else if(bit == BT_RIGHT)
{
current = current->right;
}
count--;
}
if(parent != NULL)
{
if(bit == BT_LEFT)
{
parent->left = NULL;
}
else if(bit == BT_RIGHT)
{
parent->right = NULL;
}
}
else
{
btree_head_node->root = NULL;
}
ret = current;
/*对删除结点后的二叉树结点数量进行统计,
把删除结点的子树上的结点数量也去掉*/
btree_head_node->count = btree_head_node->count - recursive_count(current);
}
return ret;
}
/*返回节点数量*/
int btree_count(btree* tree)
{
head_node* btree_head_node = (head_node*) tree;
int ret = 0;
if(btree_head_node != NULL)
{
ret = btree_head_node->count;
}
return ret;
}
•树的高度:
实现代码:
static int recursive_height(btree_node* node)
{
int ret = 0;
if(node != NULL)
{
int lh = recursive_height(node->left);
int rh = recursive_height(node->right);
ret = ((lh > rh) ? lh : rh) + 1;
}
return ret;
}
int btree_height(btree* tree)
{
head_node* btree_head_node = (head_node*) tree;
int ret = 0;
if(btree_head_node != NULL)
{
ret = recursive_height(btree_head_node->root);
}
return ret;
}
•树的度:
考虑到二叉树的性质,度最大为2,想办法利用此特点提高遍历二叉树的效率
在代码中可以这样描述:
若根结点的左孩子存在,度加1,若右孩子也存在,度再加1。直接返回即可,不用再遍历其他子树。
若左右孩子都不存在,则可以判断此树只有根结点,度为0.也直接返回即可。
若左右孩子只存在一个,则开始递归遍历。
实现代码:
static int recursive_degree(btree_node* node)
{
int ret = 0;
if(node != NULL)
{
if(node->left != NULL)
{
ret++;
}
if(node->right != NULL)
{
ret++;
}
if(ret == 1)
{
int ld = recursive_degree(node->left);
int rd = recursive_degree(node->right);
if(ret < ld)
{
ret = ld;
}
if(ret < rd)
{
ret = rd;
}
}
}
return ret;
}
int btree_degree(btree* tree)
{
head_node* btree_head_node = (head_node*)tree;
int ret = 0;
if(btree_head_node != NULL)
{
ret = recursive_degree(btree_head_node->root);
}
return ret;
}