二叉搜索树(BST)的基本操作

二叉搜索树(Binary Search Tree)是一种有如下特征的二叉树:

a,若它的左子树不为空,则左子树上所有结点的值均小于对应根结点的值;

b,若它的右子树不为空,则右子树上所有结点的值均大于对应根结点的值;

c,左子树和右子树分别构成一个二叉搜索树。

二叉树搜索树的查找、插入、删除等操作的复杂度为O (logN)。

结点结构定义为:

typedef struct node 
{
	int data;
	struct	node *left;
	struct  node *right;
}Node;

创建结点函数定义为:

Node *new_node(int data)
{
	Node *node = (Node *)malloc(sizeof(Node));
	if(node == NULL)
	{
		errno = ERR_MAL_MEMORY;		
		print_error("new_node()");
		return NULL;	
	}
	
	node->data = data;	
	node->left = NULL;
	node->right = NULL;

	return node;
}

1 查找

根据根结点与左右结点的相对位置,二叉树的查找分前序、中序和后序三种情况。一般的,中序查找能够得到一组从小到大的排序数据。

若结点值等于搜索值,返回该结点;若结点值大于搜索值,根据BST的构造原则,搜索该结点的左子树,反之,搜索右子树。

中序遍历如下:

a,递归方式

Node* search_node(Node *root, int data)
{
	Node *node = root;
	if(node == NULL)
		return NULL;
	if(node->data == data)
	{
		printf("Find out!\nValue = %d, Mem = %p\n", data, &(node->data));
		return node;
	}
	else
	{
		if(node->data > data)
			return search_node(node->left, data);
		else
			return search_node(node->right, data);
	}
}

b,非递归方式

Node *search_node_nonrecursive(Node *root, int data)
{
	Node *node = root;
	while(node)
	{
		if(node->data == data)
		{
			printf("Find out!\nValue = %d, Mem = %p\n", data, &(node->data));
			return node;
		}
		else
		{
			if(node->data > data)
				node = node->left;
			else
				node = node->right;
		}

	}
	
	printf("\nCannot find %d.\n", data);
	return NULL;
}


2,插入

将结点插入BST里时,只需将该结点插入到符合规则的合适位置,即修改相对应的根结点指针,再将两个子树赋值为NULL。其他的结点不用更改。

根据BST的构造原理,先搜索结点的左子树找到合适的位置,若不满足,再搜索右子树找到合适的位置,最后创建新结点。

a,递归方式

Node *insert_node(Node *root, int data)
{
	Node *node = root;
	if(node == NULL)
		return new_node(data);
	else
	{
		if(node->data > data)
			node->left = insert_node(node->left, data);
		else
		{
			node->right = insert_node(node->right, data);
		}
	return node;
	}
}
b,非递归方式

Node *insert_node_nonrecursive(Node *root, int data)
{
	Node *node = root;
	Node *pnode = NULL;	

	if(node == NULL)
		return new_node(data);

	while(node)
	{		
		pnode = node;
		if(node->data > data)
		{
			node = node->left;
			if(node == NULL)
				pnode->left = new_node(data);
		}		
		else
		{
			node = node->right;
			if(node == NULL)
				pnode->right = new_node(data);
		}
	}
	
	return root;


}

3 ,删除

删除结点操作根据待删结点的子树分为三种情况,即无子树,含有单子树和含有双子树。在进行相关的删除操作之前,通过查找定位待删除的结点。

若无法定位待删除的结点,返回原树根结点。记待删除结点为child,其父结点为parent。

a,无子树

将父结点对应的子树置NULL;若该结点为跟结点,说明该树只有一个结点,即根结点,将根结点置为NULL;

b,单子树

将该结点的单一子树连接至结点父结点对应的子树,释放结点。

c,双子树

由于待删除的结点有双子树,因此必须在该结点的所有子树中选取一个结点来代替该结点的位置。选取替代结点有两种选择,即选取该结点左子树的最右端

的结点或者选取该结点右子树的最左端。一般取前者方式。在定位该结点后,操作和单子树相似。

删除代码如下:

Node *delete_node(Node *root, int data)
{
	Node *tree = root;
	Node *parent, *child;
	parent = NULL;
	child = NULL;

	while(tree)
	{
		if(tree->data == data)
		{
			child = tree;
			break;
		}

		else if(tree->data > data)
		{
			parent = tree;
			tree = tree->left;
		}
		else
		{
			parent = tree;
			tree = tree->right;
		}
	}
	
	if(!child)
	{
		printf("cannot find target node.\n");
		return root;
	}

	// child != NULL
	if((child->left == NULL) && (child->right == NULL)) // leaf node
	{
		if(parent == NULL) // root node
		{
			root == NULL;
	//		return root;
		}
		else if(child == parent->left)
		{
			parent->left = NULL;
	//		return root;
		}
		else
		{
			parent->right = NULL;
	//		return root;
		}
	}

	else if(!(child->left && child->right))  // has one child node
	{
		if(child->left)
		{
			if(parent == NULL)
			{
				root = child->left;
		//		return root;
			}
			else
			{
				parent->left = child->left;
		//		return root;			
			}
		}
		if(child->right)
		{
			if(parent == NULL)
			{
				root = child->right;
		//		return root;
			}
			else
			{
				parent->right = child->right;
		//		return root;			
			}
		}
	}
	else  // has two children nodes
	// find the max node of the deleted note, according to the rightmost of deleted node's left tree 
	{
		Node *pMax = child->left;
		Node *pMaxParent = NULL;
		while(pMax->right)
		{
			pMaxParent = pMax;
			pMax = pMax->right; // stored the right child value
		}

		if(pMax == child->left) // deleted note has one generation, as pMaxParent=NULL
		{
			pMax->right = child->right;
		}
		else // deleted note has more than one generations, as pMaxParent=NULL
		{
		 	pMaxParent->right = pMax->left;
			pMax->left = child->left;
			pMax->right = child->right;
		}

		if(parent == NULL)
		{
			root = pMax;
		}
		else if(parent->left == child)
			parent->left = pMax;
		else
			parent->right = pMax;
	}

	free(child);

	return root;
	
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值