线索二叉树、平衡二叉树

1、线索二叉树

规律:在有n个节点的链式二叉树中必定存在n+1个指针域

正因为链式二叉树中有很多的空指针,可以让这些指针这向下一个节点,这样在遍历时可以不用递归,二使用循环,可以提高遍历速度。

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

//	线索二叉树
typedef struct TreeNode
{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
	bool rclue;//为真时右子树是线索
}TreeNode;

TreeNode* create_node(int data)
{
	TreeNode* node = malloc(sizeof(TreeNode));
	node->data = data;
	node->left = NULL;
	node->right = NULL;
	node->rclue = false;
	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_node(data));	
}

void ldr_show(TreeNode* root)
{
	if(NULL == root) return;
	ldr_show(root->left);
	printf("%d ",root->data);
	ldr_show(root->right);
}

//	表示上一个节点
TreeNode* prev = NULL;

//	按照中序遍历,并创建线索
void create_clue(TreeNode* root)
{
	if(NULL  == root) return;

	create_clue(root->left);

	if(NULL != prev && NULL == prev->right)
	{
		prev->right = root;
		prev->rclue = true;
	}
	prev = root;

	create_clue(root->right);
}

//	按照线索进行遍历
void clue_show(TreeNode* node)
{
	while(node)
	{
		while(node->left)
			node = node->left;
		printf("%d ",node->data);
		while(node->rclue)
		{
			node = node->right;
			printf("%d ",node->data);
		}
		node = node->right;
	}
}

int main(int argc,const char* argv[])
{
	TreeNode* root = NULL;
	for(int i=0;i<10;i++)
	{
		int data = rand()%100;
		printf("%d ",data);
		insert_tree(&root,data);
	}
	printf("\n");
	ldr_show(root);
	printf("\n");
	create_clue(root);
	clue_show(root);
}


2、平衡二叉树

平衡二叉树:
前提是有序的二叉树,它的左右子树的高度差不超过1,它的所有子树也要满足这个要求。
如果一棵有序二叉树呈现单支状(接近单支),它的效率接近链表,因此只有达到平衡时它的效率才高。
由于节点的位置受值的影响,因此只能进行调整,而不能强行修改。

二叉树不平衡的基础原因:
        x                                    y
       / \                                 /   \
      y   t1     以y为轴向右旋转           z     x
     / \                                 / \   / \
    z  t2                               t3 t4 t2 t1
   / \
  t3 t4

       x                                     y
      / \                                  /   \
     t1  y       以y为轴向左旋转           x     z
        / \                              / \   / \
       t2  z                            t1 t2 t3 t4
          / \
         t3 t4
    
       x                 x                      z
      / \               / \                   /   \
     y  t1             z  t1                 y     x
    / \               / \                   / \   / \
   t2  z             y   t4                t2 t3 t4 t1
      / \           / \
     t3 t4         t2  t3
  以z为轴向左旋转   以z为轴向右旋转          达到平衡

     x                   x                      z
    / \                 / \                   /   \
   t1  y               t1  z                 x     y
      / \                 / \               / \   / \ 
     z   t2              t3  y             t1 t3 t4  t2
    / \                     / \
   t3  t4                  t4  t2   
以z为轴向右旋转     以z为轴向左旋转     

注:简单理解位置调整就是将二叉树中节点的大小进行整理排序,整理好的二叉树中的数据顺序没有变,但是更加的便于操作

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// 平衡二叉树
typedef struct TreeNode
{
	int data;
	struct TreeNode* left;
	struct TreeNode* right;
}TreeNode;

TreeNode* create_node(int data)
{
	TreeNode* node = malloc(sizeof(TreeNode));
	node->data = data;
	node->left = NULL;
	node->right = NULL;
	return node;
}

//	高度
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;
}

//	检查左右子树是否平衡(平衡因子)是否高度差大于1
int is_balance(TreeNode* root)
{
	return high_tree(root->left) - high_tree(root->right);	
}

//	左旋转
TreeNode* left_rotate(TreeNode* x)
{
	TreeNode* y = x->right;
	TreeNode* t2 = y->left;
	
	y->left = x;
	x->right = t2;

	return y;
}
//	右旋转
TreeNode* right_rotate(TreeNode* x)
{
	TreeNode* y = x->left;
	TreeNode* t2 = y->right;

	y->right = x;
	x->left = t2;
	
	return y;
}

//	自动平衡处理函数
TreeNode* auto_balance(TreeNode* x)
{
	if(NULL == x) return NULL;
	int lh = high_tree(x->left);
	int rh = high_tree(x->right);
	if(lh - rh > 1)
	{
		if(is_balance(x->left) >= 0)
		{
			//y 右旋转
			x = right_rotate(x);
		}
		else
		{
			//z 左旋转
			x->left = left_rotate(x->left);
			//z 右旋转
			x = right_rotate(x);
		}
	}
	if(rh - lh > 1)
	{
		if(is_balance(x->right) <= 0)
		{
			//y 左旋转	
			x = left_rotate(x);
		}
		else
		{
			//z 右旋转
			x->right = right_rotate(x->right);
			//z 左旋转
			x = left_rotate(x);
		}
	}
	return x;
}

//	插入
TreeNode* insert_tree(TreeNode* root,int data)
{
	if(NULL == root)
		return create_node(data);
	if(data < root->data)
		root->left = insert_tree(root->left,data);
	else
		root->right = insert_tree(root->right,data);

	// 平衡处理
	root = auto_balance(root);
	return root;
}

//中序
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);
}


/*
	删除节点
	1、待删除的节点是叶子节点,直接删除
	2、待删除的节点左或右子树为空,则使用非空子节点替换
	3、待删除的节点左右子树非空,则根据左右子树的高度,选择最大子节点(左)或者最小子节点(右)替换

*/

TreeNode* min_tree(TreeNode* root)
{
	TreeNode* min = root;
	while(min->left) min = min->left;
	return min;
}


TreeNode* max_tree(TreeNode* root)
{
	TreeNode* max = root;
	while(max->right) max = max->right;
	return max;
}

TreeNode* del_tree(TreeNode* root,int data)
{
	if(NULL == root) return NULL;

	if(data == root->data)
	{
		if(NULL == root->left && NULL == root->right)
		{
			free(root);
			return NULL;
		}
		if(NULL == root->left)
		{
			TreeNode* temp = root->right;
			free(root);
			return temp;
		}
		if(NULL == root->right)
		{
			TreeNode* temp = root->left;
			free(root);
			return temp;
		}
		
		int lh = high_tree(root->left);
		int rh = high_tree(root->right);
		if(lh > rh)
		{
			TreeNode* node = max_tree(root->left);
			root->data = node->data;
			root->left = del_tree(root->left,root->data);
		}
		else
		{
			TreeNode* node = min_tree(root->right);
			root->data = node->data;
			root->right = del_tree(root->right,root->data);
		}
		return root;
	}
	if(data < root->data)
		root->left = del_tree(root->left,data);
	else
		root->right = del_tree(root->right,data);
	
	root = auto_balance(root);
	return root;
}

int main(int argc,const char* argv[])
{
	TreeNode* root = NULL;
	for(int i=0;i<10;i++)
	{
		root = insert_tree(root,i);	
	}
	root = del_tree(root,0);
	root = del_tree(root,2);
	ldr_show(root);
	printf("\n");
	dlr_show(root);
	printf("\n%d\n",high_tree(root));
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值