Linux与数据结构 2019-3-23上午

1.将一个BST转换成一个有序双向链表

1.1 考虑

  • 1.我们需要改变原本BST的结构,因此我们使用 p_left 作为双向链表的指向前的指针,使用 p_right 作为双向链表的指向后的指针;
  • 2.将一个BST转换为一个有序的双向链表其实就是将BST的中序遍历中的printf处的代码进行修改,改为给双向链表添加节点;
  • 使用递归的形式进行转换
void BSTToList(BinaryTree* p_tree, BinaryTree** pp_head, BinaryTree** pp_tail)
{
	if(p_tree == NULL)return;

	BSTToList(P_tree->p_left);

	if(*pp_head == NULL)
	{
		*pp_head = p_tree;
	}
	else
	{
		*pp_tail->p_right = p_tree;
		p_tree->p_left = *pp_tail;
	}
	*pp_tail = p_tree;

	BSTToList(P_tree->p_right);
}
  • 不使用递归的形式完成
void BSTToList(BinaryTree* p_tree, BinaryTree** pp_head, BinaryTree** pp_tail)
{
	if(p_tree == NULL)return;

	// 申请辅助栈
	Stack* p_stack = NULL;
	s_Init(&p_stack);

	while(1)
	{
		while(p_tree)
		{
			s_Push(p_stack, p_tree);
			p_tree = p_tree->p_left;
		}
		p_tree = s_Pop(s_stack);
		if(p_tree == NULL)break;

		// ==========向双向链表中添加节点=========
		if(*pp_head == NULL)
		{
			*pp_head = p_tree;
		}
		else
		{
			*pp_tail->p_right = p_tree;
			p_tree->p_left = *pp_tail;
		}
		*pp_tail = p_tree;
		// ==========向双向链表中添加节点=========

		p_tree = p_tree->p-right;

	}
}

2.旋转一颗AVL

2.1 首先考虑一颗类似于下面的AVL

=添加图片==

  • 当新加的节点导致AVL树不平衡,那么就需要旋转来将其变平衡;

  • 在左子树的左子树上添加节点导致的不平衡需要右旋;

  • 在右子树的右子树上添加节点导致的不平衡需要左旋;

  • 在左子树的右子树上添加节点导致的不平衡需要左右旋;

  • 在右子树的右子树上添加节点导致的不平衡需要右左旋;

  • 1.右旋

void RightRotate(BinaryTree** pp_tree)
{
	if(*pp_tree == NULL)return;

	BinaryTree* p_node = *pp_tree;
	BinaryTree* p_flag = p_node->p_left;

	// 三个孩子的关系
	p_node->p_left = p_flag->p_right;
	p_flag->p_right = p_node;

	// 支点(顶点A)的父亲存在(也就是说A不是根节点)
	if(p_node->p_father != NULL)
	{
		// 顶点是它父亲节点的左节点
		if(p_node == p_node->p_father->p_left)
		{
			p_node->p_father->p_left = p_flag;
		}
		// 顶点是它父亲节点的右节点
		else
		{
			p_node->p_father->p_right = p_flag;
		}
	}
	// 顶点A就是根节点
	else
	{
		*p_tree = p_flag;
	}

	// 三个父亲的关系
	if(p_node->p_left != NULL)
	{
		p_node->p_left->p_father = p_node;
	}

	p_flag->p_father = p_node->p_father;
	p_node->p_father = p_flag;
}
  • 2.左旋
void LeftRotate(BinaryTree** pp_tree)
{
	if(*pp_tree == NULL)return;

	BinaryTree* p_node = *pp_tree;
	BinaryTree* p_flag = p_node->p_right;

	// 三个孩子的关系
	p_node->p_right = p_flag->p_left;
	p_flag->p_left = p_node;

	// 支点(顶点A)的父亲存在(也就是说A不是根节点)
	if(p_node->p_father != NULL)
	{
		// 顶点是它父亲节点的左节点
		if(p_node == p_node->p_father->p_left)
		{
			p_node->p_father->p_left = p_flag;
		}
		// 顶点是它父亲节点的右节点
		else
		{
			p_node->p_father->p_right = p_flag;
		}
	}
	// 顶点A就是根节点
	else
	{
		*p_tree = p_flag;
	}

	// 三个父亲的关系
	if(p_node->p_right != NULL)
	{
		p_node->p_right->p_father = p_node;
	}

	p_flag->p_father = p_node->p_father;
	p_node->p_father = p_flag;
}

猜你喜欢

转载自blog.csdn.net/weixin_42896619/article/details/88942024