二叉树(tree)

目录

一、二叉树的遍历

二、二叉树程序

1.创建结构体

2.插入结点

 2.找到某个结点,并返回结点中的数据

3.左偏 遍历输出

4.平衡二叉树

5.遍历

1)先序遍历

2)中序遍历

3)后序遍历

4)按层遍历

6.删除结点



一、二叉树的遍历

1.先序遍历        (根结点---左结点---右结点)

        A-B-D-E-G-C-F-F-I

2.中序遍历        (左节点---根结点---右节点)

        D-B-G-E-A-C-H-F-I

3.后续遍历        (左结点---右节点---根结点)

        D-G-E-B-H-I-F-C-A

二、二叉树程序

1.创建结构体

struct score_st
{
	int id;
	char name[NAMESIZE];
	int math;
};
struct node_st
{
	struct score_st data;
	struct node_st *l,*r;
};

2.插入结点

int insert(struct node_st **root, struct score_st *data)
{
	struct node_st *node;

	if(*root == NULL)     //当root指向的指针为空
	{
		node = malloc(sizeof(*node));    //创建一个结点
		if(node == NULL)
			return -1;
		node->data = *data;            //将要插入的数据赋值给node
		node->l = node->r = NULL;       //结点的做指针和右指针设为NULL
		*root = node;                  //将结点的地址保存到root指向的指针中
		return 0;
	}

	if(data->id <=  (*root)->data.id)    //当树不为空时,比较id的值,id小的在树的左侧
		return insert(&(*root)->l,data);
	return insert(&(*root)->r,data);    //id大的在树的右侧
}

 2.找到某个结点,并返回结点中的数据

struct score_st *find(struct node_st *root, int id)
{
	if(root == NULL)    
		return NULL;
	if(root->data.id == id)      //如果要找的id和结点中的id相等,返回数据
		return &root->data;

	if(id < root->data.id)        //如果要找的id小于结点中的id,再递归调用找左结点
		return find(root->l,id);
	return find(root->r,id);        //如果要找的id大于结点中的id,再递归调用找右结点
}

3.左偏 遍历输出

static void draw_(struct node_st *root,int level)
{
    int i;
    if(root == NULL)    //root为NULL直接结束函数
        return ;    
    draw_(root->r,level+1);    //递归调用draw,指向右子树,level+1    
    for(i = 0 ; i < level; i++)    //输出level个空格
        printf("    ");
    print_s(&root->data);
    draw_(root->l,level+1);    递归调用draw,指向左子树,level+1

}
void draw(struct node_st *root)
{
    draw_(root,0);

}

4.平衡二叉树

static int get_num(struct node_st *root)    //返回树的结点个数
{
	if(root == NULL)
		return 0;
	return get_num(root->l) + 1 + get_num(root->r);//递归调用返回结点个数
}
static struct node_st *find_min(struct node_st *root)
{
	if(root->l == NULL)   //如果root的左结点为NULL,将root返回
		return root;        
	return find_min(root->l);    //递归调用查找左结点,当左结点为NULL,将这个结点返回
}

static void turn_left(struct node_st **root)
{
	struct node_st *cur = *root;    //定义一个指针,指向*root指向的位置
	*root = cur->r;    //*root指向cur的右结点
	cur->r = NULL;       //cur的右结点赋值为NULL
	find_min(*root)->l = cur;    //找到最小的结点,将cur插入到最小结点的左结点

//	draw(tree);
}

static struct node_st *find_max(struct node_st *root)
{
	if(root->r == NULL)    //如果root的左结点为NULL,将root返回
		return root;
	return find_max(root->r);    //递归调用查找右结点,当右结点为NULL,将这个结点返回
}  

static void turn_right(struct node_st **root)
{
	struct node_st *cur = *root;    //定义一个指针,指向*root指向的位置

	*root = cur->l;    //*root指向cur的左结点
	cur->l = NULL;    //cur的左结点赋值为NULL
	find_max(*root)->r = cur;    //找到最大的结点,将cur插入到最大结点的右结点

//	draw(tree);
}

void balance(struct node_st **root)
{
	int sub;
	if(*root == NULL)
		return ;
	while(1)
	{
		sub = get_num((*root)->l) - get_num((*root)->r);    //得到根结点左子树和右子树的结点差值
		if(sub >= -1 && sub <= 1)    //两边的结点数差值如果是-1 0 1时结束循环
			break;
		if(sub < -1)                //如果差值小于-1,向左旋
			turn_left(root);
		else                        //如果差值大于1,向右旋
			turn_right(root);
	}

	balance(&(*root)->l);        //递归调用,平衡左子树
	balance(&(*root)->r);        //递归调用,平衡右子树

}

5.遍历

1)先序遍历

void travel(struct node_st *root) 
{
    if(root == NULL)
        return ;
    print_s(&root->data);
    travel(root->l);
    travel(root->r);
    
}

2)中序遍历

void travel(struct node_st *root) 
{
    if(root == NULL)
        return ;
    travel(root->l);
    print_s(&root->data);
    travel(root->r);
    
}

3)后序遍历

void travel(struct node_st *root) 
{
    if(root == NULL)
        return ;
    travel(root->l);
    travel(root->r);
    print_s(&root->data);
}

4)按层遍历

void travel(struct node_st *root)
{   
    QUEUE *qu;    
    struct node_st *cur;
    qu = queue_create(sizeof(struct node_st *));    //创建队列
    queue_en(qu, &root);        //根结点入队
    while(1)
    {   
        if(queue_de(qu, &cur) != 0)    //如果删除回显不成功,则结束循环
            break;
        print_s(&cur->data);        //输出回显指针指向的数据
        if(cur->l != NULL)            //指针左结点不为NULL,则入队
            queue_en(qu,&cur->l);    
        if(cur->r != NULL)            //指针右结点不为NULL,则入队
            queue_en(qu,&cur->r);
    }   
    queue_destroy(qu);
}

6.删除结点

void delete(struct node_st **root, int id)
{
	struct node_st **node = root;
	struct node_st *cur;

	while( (*node) != NULL &&  (*node)->data.id != id )//查找要删除的结点
	{
		if( id < (*node)->data.id )    //如果想要删除的id小于结点中的id,让指针指向结点的左结点
			node = &(*node)->l;
		else
			node = &(*node)->r;     //如果想要删除的id小于结点中的id,让指针指向结点的左结点
	}
	
	if(*node == NULL)    //没找到直接返回
		return ;
	
	cur = *node;    

	if(cur->l == NULL)    //如果找到的结点的左子树为NULL,则直接将*node指向cur的右结点
		*node = cur->r;
	else
	{
		*node = cur->l;    //不为NULL,则直接将*node指向cur的左结点
		find_max(cur->l)->r = cur->r;    //将找到的结点的右子树插入到*node的右子树的最后面
	}
	free(cur);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RLC214

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值