数据结构 二叉查找树 BST

二叉查找树:又称为 二叉排序树   二叉搜索树

首先,这几个名字都让我觉得混乱,简单地讲,二叉树的重要的应用便是查找了,因此“查找”与“搜索”二字等价,可以理解。那么又由于二叉搜索树的中序遍历是有序的,因此又叫做二叉排序树。

接下来,步入正题:[摘自维基百科]

二叉查找树Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树

  1. 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
  2. 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
  3. 任意节点的左、右子树也分别为二叉查找树。
  4. 没有键值相等的节点(no duplicate nodes)。
如下图就是一个二叉查找树。



首先定义二叉查找树的操作:由于二叉树的递归定义,下述的方法只需要递归编写即可。

1    insert插入操作(在树root中添加节点值为target的节点)

注意:传入参数为root的引用,也可将新形成的树作为返回值。

//insert node
void insert(TreeNode * &root, int target)
{
	TreeNode *node = new TreeNode(target);
	if( root == NULL ) 
	{
		root = node;
		return;
	}
	if ( target == root->val )
	{
		cout << target << " exists ..." << endl;
	}
	else if (target < root->val)
	{
		insert(root->left, target);
	}
	else
	{
		insert(root->right , target);
	}
}

2    创建二叉搜索树,根据一个已知数组的元素集合创建一个二叉搜索树。

PS:依次插入数组中的每个元素即可,如果数组有序,那么二叉搜索树将退化为一个链表。

TreeNode * convertArrayToBST(int data[], int len)
{
	if(len == 0) return NULL;
	TreeNode *root = NULL;
	for(int i = 0 ; i < len ; ++i )
	{
		insert(root, data[i]);
	}
	return root;
}

3   查找元素  并返回true/false,并设置findPtr用于标记该节点是否找到。

//findPtr 必须传引用,否则会出错(传值 VS 传址)
bool search(TreeNode *root, int target , TreeNode * & findPtr)
{
	if(root == NULL){return false;}
	cout << "search..." << root->val << endl; 
	TreeNode *temp = root;
	if(target == temp->val)
	{
		findPtr = temp;
		cout << "find " << findPtr->val << endl;
		return true;
	}
	else if (target > temp->val)
	{
		return search(temp->right , target, findPtr );
	}
	else
	{
		return search(temp->left , target ,findPtr );
	}
}

4   返回最大值或者最小值


//find min element
TreeNode *findMin(TreeNode *root)
{
	if( root == NULL) return NULL;
	if ( root->left == NULL ) return root;
	else	return findMin( root->left );
}


//find max element
TreeNode *findMax(TreeNode *root)
{
	if( root == NULL ) return NULL;
	if( root->right == NULL) return root;
	else return findMax(root->right);
}

5   将二叉搜索树转换为一个双向有序链表 (最常见的问题)

TreeNode *convert(TreeNode *root)
{
	if(root == NULL) return NULL;
	stack<TreeNode *> s;
	TreeNode *temp = root;
	TreeNode *head = NULL;
	TreeNode *pre = NULL;
	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);
			temp = temp->left;
		}
		temp = s.top();
		s.pop();
		if(head == NULL)
		{
			head = temp;
			head->left = NULL;
			pre = head;
			temp = temp->right;
			continue;
		}
		if(pre)
		{
			pre->right = temp;
			temp->left = pre;
			pre = temp;
			temp = temp->right;
		}
	}
	return head;
}

完整的代码为:
#include<iostream>
#include<stack>
using namespace std;

struct TreeNode{
	int val;
	TreeNode *left,*right;
	TreeNode(int x):val(x),left(NULL),right(NULL){}
};

TreeNode *convert(TreeNode *root)
{
	if(root == NULL) return NULL;
	stack<TreeNode *> s;
	TreeNode *temp = root;
	TreeNode *head = NULL;
	TreeNode *pre = NULL;
	while(temp || !s.empty())
	{
		while(temp)
		{
			s.push(temp);
			temp = temp->left;
		}
		temp = s.top();
		s.pop();
		if(head == NULL)
		{
			head = temp;
			head->left = NULL;
			pre = head;
			temp = temp->right;
			continue;
		}
		if(pre)
		{
			pre->right = temp;
			temp->left = pre;
			pre = temp;
			temp = temp->right;
		}
	}
	return head;
}

//insert node
void insert(TreeNode * &root, int target)
{
	TreeNode *node = new TreeNode(target);
	if( root == NULL ) 
	{
		root = node;
		return;
	}
	if ( target == root->val )
	{
		cout << target << " exists ..." << endl;
	}
	else if (target < root->val)
	{
		insert(root->left, target);
	}
	else
	{
		insert(root->right , target);
	}
}

//find min element
TreeNode *findMin(TreeNode *root)
{
	if( root == NULL) return NULL;
	if ( root->left == NULL ) return root;
	else	return findMin( root->left );
}


//find max element
TreeNode *findMax(TreeNode *root)
{
	if( root == NULL ) return NULL;
	if( root->right == NULL) return root;
	else return findMax(root->right);
}

TreeNode * convertArrayToBST(int data[], int len)
{
	if(len == 0) return NULL;
	TreeNode *root = NULL;
	for(int i = 0 ; i < len ; ++i )
	{
		insert(root, data[i]);
	}
	return root;
}

//findPtr 必须传引用,否则会出错(传值 VS 传址)
bool search(TreeNode *root, int target , TreeNode * & findPtr)
{
	if(root == NULL){return false;}
	cout << "search..." << root->val << endl; 
	TreeNode *temp = root;
	if(target == temp->val)
	{
		findPtr = temp;
		cout << "find " << findPtr->val << endl;
		return true;
	}
	else if (target > temp->val)
	{
		return search(temp->right , target, findPtr );
	}
	else
	{
		return search(temp->left , target ,findPtr );
	}
}

void InOrderTraverse2(TreeNode *root)
{
	if( root == NULL ) return;
	InOrderTraverse2(root->left);
	cout << root->val << " ";
	InOrderTraverse2(root->right);
}

void PreOrderTraverse2(TreeNode *root)
{
	if( root == NULL ) return;
	cout << root->val << " ";
	PreOrderTraverse2(root->left);
	PreOrderTraverse2(root->right);

}
void InOrderTraverse(TreeNode *root)
{
	cout << "InOrderTraverse..." << endl;
	if( root == NULL ) return;
	TreeNode *pre = NULL;
	while(root)
	{
		if(root->left == NULL)
		{
			cout << root->val << " ";
			root = root->right;
			continue;
		}
		//if left not null
		for(pre = root->left; pre->right && pre->right != root ; pre = pre->right);
		//the first visiting time
		//for循环退出的条件是pre->rigth == NULL或者是pre->right == root.
		//分别考虑for循环退出的情况。
		if(pre->right == NULL)
		{
			pre->right = root;
			root = root->left;
		}
		//the second visiting time
		//说明当前节点的左子树已经访问过了
		else
		{
			cout << root->val << " ";
			root = root->right;
			pre->right = NULL;
		}
	}
}


int main()
{
	TreeNode *node6 = new TreeNode(6);
	TreeNode *node2 = new TreeNode(2);
	TreeNode *node8 = new TreeNode(8);
	TreeNode *node1 = new TreeNode(1);
	TreeNode *node4 = new TreeNode(4);
	TreeNode *node3 = new TreeNode(3);
	node6->left = node2;
	node6->right = node8;

	node2->left = node1;
	node2->right = node4;

	node4->left = node3;
	
	TreeNode *findPtr = NULL;
	
	InOrderTraverse(node6);
	cout << endl;
	InOrderTraverse2(node6);
	cout << endl;
	PreOrderTraverse2(node6);
	cout << endl;
	cout << "find min " << findMin(node6)->val << endl;
	cout << "find max " << findMax(node6)->val << endl;
	//add node 7
	if ( search(node6,2,findPtr))
		cout << findPtr->val << endl;
	else
	{
		insert(node6,2);
		cout << "not find.." << endl;
	}

	InOrderTraverse(node6);
	cout << "InOrderTraverse iterativelly..." << endl;
	InOrderTraverse2(node6);
	cout << endl;
	PreOrderTraverse2(node6);
	cout << endl;
	cout << "find min " << findMin(node6)->val << endl;
	cout << "find max " << findMax(node6)->val << endl;
	//convert to sorted list
	TreeNode *head = convert(node6);
	cout << "head = " << head->val << endl;
	head = head->right;
	while(head && head->right)
	{
		cout << head->left->val << " " << head->val  << " " << head->right->val << endl;
		head = head->right;
	}
	cout << endl;

	//build BST
	int data[] = {1,4,3,2};
	int len = sizeof(data)/sizeof(int);
	cout << "build BST..." << endl;
	TreeNode *root = convertArrayToBST(data, len);
	InOrderTraverse(root);
	cout << "InOrderTraverse iterativelly..." << endl;
	InOrderTraverse2(root);
	cout << "PreOrderTraverse..." << endl;
	PreOrderTraverse2(root);
	cout << endl;
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值