二查排序树的基本操作(插入,删除,找前驱与后继)

// Binary-Search-Tree.cpp : Defines the entry point for the console application.
//最近要面试,想自己写写这类算法的代码,加深印象

#include "stdafx.h"
//参考算法导论的伪代码编写
//有错误的地方,恳请大家批评指正,thx;
typedef struct Node
{
	int val;
	Node* left;
	Node* right;
	Node* parent;
	Node(int value) : val(value) , left(NULL), right(NULL),parent(NULL)
	{

	}
}Node;

//查找二叉搜索树中最小的元素
int FindMinValue(Node* head)
{
	if(head == NULL)
		return -1;
	Node* p = head;
	while(p->left)
		p = p->left;
	return p->val;
}

//查找二叉搜索树的最大元素
int FindMaxValue(Node* head)
{
	if(head == NULL)
		return -1;
	Node* p = head;
	while(p->right)
		p = p->right;
	return p->val;
}

//找当前节点的后继结点
/*
1、若当前节点有右子树,那么后继结点就是右子树最左的结点
2、若当前节点没有右子树, 那么后继结点:从当前节点往上延伸,找到某个结点p,p不是其父结点的右孩子。如果找不到结点p,则其没有后继结点
*/
Node* FindSucceed(Node* curNode)
{
	if(curNode->right)
	{
		Node* p = curNode->right;
		while(p->left)
			p = p->left;
		return p;
	}
	else
	{
		Node* cur = curNode;
		Node* parent = curNode->parent;
		while(parent && parent->right == cur)
		{
			cur = parent;
			parent = cur->parent;
		}
		/*if(parent == NULL)
			return NULL;
		else
			return parent;*/
		return parent;
	}
}

//找当前节点的前驱结点
/*
1、如果当前节点有左子树,那么前驱结点就是其左子树最右的结点
2、如果当前节点没有左子树,则前驱结点:从当前节点往上延伸,找到结点p,p不是其父结点的左孩子。如果找不到结点p,则该节点没有前驱结点;
*/
Node* FindPioneer(Node* curNode)
{
	if(curNode->left)
	{
		Node* p = curNode->left;
		while(p->right)
			p = p->right;
		return p;
	}
	else
	{
		Node* cur = curNode;
		Node* parent = cur->parent;
		while(parent && parent->left == cur)
		{
			cur = parent;
			parent = cur->parent;
		}
		return parent;
	}
}

//二叉树中插入结点
void InsertNode(Node* head, Node* node)
{
	if(node == NULL)
		return;
	Node* parent = NULL;
	Node* curNode = head;
	while(curNode)
	{
		parent = curNode;
		if(curNode->val > node->val)
			curNode = curNode->left;
		else
			curNode = curNode->right;
	}
	node->parent = parent;
	if(parent == NULL)
		node = head;
	else if(parent->val < node->val)
		parent->right = node;
	else
		parent->left = node;
}

//二叉树中删除结点
/*
分三种情况讨论
1、如果删除结点没有左孩子也没有右孩子,则可以直接删除改结点,并让其父结点孩子指针为NULL;
2、如果删除结点只有一个孩子结点,则也可以直接删除该节点,并让其父结点的孩子指针指向删除结点的孩子;
3、如果删除结点有两个孩子结点,则先找到该节点的后继结点,后继结点的元素值取代删除结点的元素值,再删除后继结点,并让后继结点的父节点的孩子指针指向后继结点的孩子;
*/
void DeleteNode(Node* head, Node* node)
{
	Node* y, *x;
	if(node->left==NULL || node->right==NULL)
		y = node;
	else
		y = FindSucceed(node);
	if(y->left)
		x = y->left;
	else
		x = y->right;
	if(x)
	{
		x->parent = y->parent;
	}
	if(y->parent == NULL)
		head = x;
	else if(y == y->parent->left)
		y->parent->left = x;
	else
		y->parent->right = x;
	if(y != node)
	{
		node->val  = y->val;
		delete y;
	}
}

int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值