二叉查找树:又称为 二叉排序树 二叉搜索树
首先,这几个名字都让我觉得混乱,简单地讲,二叉树的重要的应用便是查找了,因此“查找”与“搜索”二字等价,可以理解。那么又由于二叉搜索树的中序遍历是有序的,因此又叫做二叉排序树。
接下来,步入正题:[摘自维基百科]
二叉查找树(Binary Search Tree),也称有序二叉树(ordered binary tree),排序二叉树(sorted binary tree),是指一棵空树或者具有下列性质的二叉树:
- 若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
- 任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
- 任意节点的左、右子树也分别为二叉查找树。
- 没有键值相等的节点(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;
}