二叉排序树(Binary Sort Tree)又称二叉查找树。
它是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
vs2008运行正确,如有误,请各位大牛指正!
实现代码如下:
二叉排序树是一种动态树表。
vs2008运行正确,如有误,请各位大牛指正!
实现代码如下:
// MyBiSortTree.cpp : 定义控制台应用程序的入口点。
// 二叉查找树的各种操作
//实现功能:建树,查找,插入,删除,求最大值最小值,求双亲结点
// ,获取中序遍历的前驱结点后继结点,用栈实现非递归的先序中序后序遍历算法,
#include "stdafx.h"
#include<iostream>
using namespace std;
int a[100];//存放结点数据的数组
const int STACK_MAXSIZE = 30;
//二叉排序树的结点类型
class BSNode
{
public:
BSNode(){};
BSNode(int item):data(item), m_lchild(NULL), m_rchild(NULL){}
int data;//数据域
BSNode *m_lchild;//左孩子
BSNode *m_rchild;//右孩子
};
//二叉排序树类型
class BSTree
{
public://定义接口
BSTree();
//建树:创建一棵结点个数为n的二叉排序树
void CreateTree();
//查找:在以root为根的树上查找值为item的结点,返回给Node,找到返回true,否则为false
bool FindNode(int item);
//插入:在以root为根的树上插入值为item的结点
void InsertNode(int item);
//删除:在以root为根的树上插入值为item的结点
void DeleteNode(int item);
//求最大值:返回以root为根的树中结点的最小值,结点返回给minNode
int MinNode();
//求最小值:返回以root为根的树中结点的最大值,结点返回给maxNode
int MaxNode();
//求双亲结点:返回值为item的结点的双亲结点
BSNode *GetParent(int item);
//获取中序遍历的前驱结点
BSNode *GetInOrderPre(int item);
//获取中序遍历的后继结点
BSNode *GetInOrderPost(int item);
//用栈实现非递归的先序遍历
void PreOrderVisit();
//用栈实现非递归的中序遍历
void InOrderVisit();
//用栈实现非递归的后序遍历
void PostOrderVisit();
private:
BSNode *root; //树的根结点
//建树:创建一棵结点个数为n的二叉排序树
void Create(BSNode *&root,int *a, int n);
//查找:在以root为根的树上查找值为item的结点,返回给Node,找到返回true,否则为false
bool Find(BSNode *&root, BSNode *&Node, int item);
//插入:在以root为根的树上插入值为item的结点
void Insert(BSNode *&root, int item);
//删除:在以root为根的树上插入值为item的结点
void Delete(BSNode *&root, int item);
//求最大值:返回以root为根的树中结点的最小值,结点返回给minNode
int Min(BSNode *root, BSNode *&minNode);
//求最小值:返回以root为根的树中结点的最大值,结点返回给maxNode
int Max(BSNode *root, BSNode *&maxNode);
//求双亲结点:返回值为item的结点的双亲结点
BSNode *getParent(BSNode *root, int item);
//获取中序遍历的前驱结点
BSNode *getInOrderPre(BSNode *root, int item);
//获取中序遍历的后继结点
BSNode *getInOrderPost(BSNode *root, int item);
//用栈实现非递归的先序遍历
void PreOrder(BSNode *root);
//用栈实现非递归的中序遍历
void InOrder(BSNode *root);
//用栈实现非递归的后序遍历
void PostOrder(BSNode *root);
};
BSTree::BSTree()
{
root = NULL;
}
//建树:创建一棵结点个数为n的二叉排序树
void BSTree::CreateTree()
{
int n = 0;
Create(root, a, n);
}
//建树:创建一棵结点个数为n的二叉排序树
void BSTree::Create(BSNode *&root,int *a, int n) //待续,要利用插入算法
{
cout << "请输入树的结点个数:" ;
cin >> n;
cout << endl << "请依次输入结点的数值:" << endl;
BSNode *newNode = NULL;
for (int i=0; i<n; i++)
{
cin >> a[i];
InsertNode(a[i]);
}
}
//查找:在以root为根的树上查找值为item的结点,返回给Node,找到返回true,否则为false
bool BSTree::FindNode(int item)
{
BSNode *Node = NULL;
return Find(root, Node, item);
}
//查找:在以root为根的树上查找值为item的结点,返回给Node,找到返回true,否则为false
bool BSTree::Find(BSNode *&root, BSNode *&findNode, int item)
{
if (root == NULL)//树空
{
findNode = NULL;//没有找到结点
return false;
}
else
{
if (root->data == item)
{
findNode = root; //找到结点
return true;
}
else if (root->data > item)//数值小于根结点的数值,则在左子树中递归查找
{
return Find(root->m_lchild, findNode, item);
}
else //数值大于根结点的数值,则在右子树中递归查找
{
return Find(root->m_rchild, findNode, item);
}
}
}
//插入:在以root为根的树上插入值为item的结点
void BSTree::InsertNode(int item)
{
Insert(root, item);
}
//插入:在以root为根的树上插入值为item的结点
//根为空,则直接插入;根不空,则在插入之前先要查找该数值的结点是否存在
void BSTree::Insert(BSNode *&root, int item)
{
BSNode *newNode = NULL;
if (root == NULL)//树为空,则先建立根结点
{
newNode = new BSNode(item);
root = newNode;
cout << item << "已被插入二叉排序树中!" << endl;
}
else
{
if (FindNode(item))//如果找到该数值的结点,直接返回
{
cout << "数值" << item << "已经存在!" << endl;
return;
}
if (item > root->data)//当前数值比根结点大,则插入树的右子树
{
Insert(root->m_rchild, item);
}
else
{
Insert(root->m_lchild, item);
}
}
}
//删除:在以root为根的树上删除值为item的结点
void BSTree::DeleteNode(int item)
{
Delete(root, item);
}
//删除:在以root为根的树上删除值为item的结点
void BSTree::Delete(BSNode *&root, int item)
{
BSNode *pNode = NULL;
if (root == NULL)
{
cout << "树空!" << endl;
return;
}
if (Find(root, pNode, item))
{
BSNode *pParent = NULL;
//情况一:叶子结点
if (pNode->m_lchild == NULL && pNode->m_rchild == NULL)//被删除结点是叶子结点
{
if (pNode == root)//且是根结点
{
root = NULL;
}
else//且不是根结点
{
pParent = GetParent(item);
if (pParent->m_lchild == pNode)//为其父亲结点的左孩子
{
pParent->m_lchild = NULL;
}
else//为其父亲结点的右孩子
{
pParent->m_rchild = NULL;
}
}
}
//情况二:只有一个孩子结点
else if (pNode->m_rchild != NULL && pNode->m_lchild == NULL)//被删除结点有右孩子,无左孩子
{
if (pNode == root)//且是根结点
{
root = pNode->m_rchild;
}
else//且不是根结点
{
pParent = GetParent(item);//找到给结点的父亲节点
if (pParent->m_lchild == pNode)
{
pParent->m_lchild = pNode->m_rchild;
}
else
{
pParent->m_rchild = pNode->m_rchild;
}
}
}
else if (pNode->m_lchild != NULL && pNode->m_rchild == NULL)//被删结点有左孩子,无右孩子
{
if (pNode == root)//且是根结点
{
root = pNode->m_lchild;
}
else//且不是根结点
{
pParent = GetParent(item);//找到给结点的父亲节点
if (pParent->m_lchild == pNode)
{
pParent->m_lchild = pNode->m_lchild;
}
else
{
pParent->m_rchild = pNode->m_lchild;
}
}
}
//情况三:有两个孩子结点
else if (pNode->m_lchild != NULL && pNode->m_rchild != NULL)//被删结点有左孩子和右孩子
{
//解法一:找到该结点的前驱结点(右孩子必为空)
BSNode *maxNode = NULL;
int max = Max(pNode->m_lchild, maxNode);//找到以该结点左孩子为根的子树上最大的结点,即为其前驱结点
BSNode *father = GetParent(max);
pNode->data = max;//将前驱结点的值赋给该结点
if (father != pNode)
{
father->m_rchild = maxNode->m_lchild;
}
else
{
father->m_lchild = maxNode->m_lchild;
}
//解法二:找到该结点的后继结点(左子树必为空)
//BSNode *minNode = NULL;
//int min = Min(pNode->m_rchild, minNode);//找到以该结点右孩子为根的子树上最小的结点,即为其后继结点
//BSNode *father = GetParent(min);
//pNode->data = min;//将后继结点的值赋给该结点
// if (father != pNode)
// {
// father->m_lchild = minNode->m_rchild;
// }
//else
//{
// father->m_rchild = minNode->m_rchild;
//}
//解法三:让该结点的左子树为其父亲结点的左子树(或右子树,取决于该结点是父亲结点的左子树还是右子树),
// 其右子树为其前驱结点(以该结点左孩子为根的子树中最大值结点)的右子树
// BSNode *Father = GetParent(item);
//if (Father == NULL)//该结点是根结点
//{
// root = pNode->m_lchild;
// BSNode *maxNode = NULL;
// int max = Max(pNode->m_lchild, maxNode);
// maxNode->m_rchild = pNode->m_rchild;
//}
//else//该结点不是根结点
//{
// if (Father->m_lchild == pNode)
// {
// Father->m_lchild = pNode->m_lchild;
// }
// else
// {
// Father->m_rchild = pNode->m_lchild;
// }
// //BSNode *maxNode = GetInOrderPre(item);
// BSNode *maxNode = NULL;
// int max = Max(pNode->m_lchild, maxNode);
// maxNode->m_rchild = pNode->m_rchild;
//}
}
if (root == NULL)
{
cout << "删除结点后,二叉排序树为空!" << endl;
}
else
{
cout << "结点" << item << "删除成功!" << endl;
}
}
else
{
cout << "数值为" << item << "的结点不存在!" << endl;
}
}
//求最小值:返回以root为根的树中结点的最小值,结点返回给minNode
int BSTree::MinNode()
{
BSNode *minNode;
return Min(root, minNode);
}
//求最小值:返回以root为根的树中结点的最小值,结点返回给minNode
int BSTree::Min(BSNode *root, BSNode *&minNode)
{
int min = 0;
BSNode *p = root;
if (p == NULL)
{
cout << "树空!" <<endl;
return -1;//结果为-1表示树空,最小值不存在
}
else
{
while(p->m_lchild)
{
p = p->m_lchild;
}
minNode = p;
return minNode->data;
}
return min;
}
//求最大值:返回以root为根的树中结点的最大值,结点返回给maxNode
int BSTree::MaxNode()
{
BSNode *maxNode = NULL;
return Max(root, maxNode);
}
//求最大值:返回以root为根的树中结点的最大值,结点返回给maxNode
int BSTree::Max(BSNode *root, BSNode *&maxNode)
{
int max = 0;
BSNode *p = root;
if (p == NULL)
{
cout << "树空!" <<endl;
return -1;//结果为-1表示树空,最大值不存在
}
else
{
while(p->m_rchild)
{
p = p->m_rchild;
}
maxNode = p;
return maxNode->data;
}
return max;
}
//求双亲结点:返回值为item的结点的双亲结点
BSNode *BSTree::GetParent(int item)
{
return getParent(root, item);
}
//求双亲结点:返回值为item的结点的双亲结点
BSNode *BSTree::getParent(BSNode *root, int item)
{
BSNode *pParent = NULL;//指向双亲结点的指针
BSNode *pNode = NULL;
if (Find(root, pNode, item))//找到值为item的结点
{
if ((root == NULL) || (root == pNode))//树空,或该结点为根结点,则不存在双亲结点
{
pParent = NULL;
}
else//树不空且该结点不是根结点
{
if (root->m_lchild == pNode || root->m_rchild == pNode)
{
pParent = root;
}
else if (root->data > item)
{
pParent = getParent(root->m_lchild, item);
}
else
{
pParent = getParent(root->m_rchild, item);
}
}
return pParent;
}
else
{
cout << "不存在值为" << item << "的结点!";
return pParent;
}
}
//获取中序遍历的前驱结点
BSNode *BSTree::GetInOrderPre(int item)
{
return getInOrderPre(root, item);
}
//获取中序遍历的前驱结点
//思想:先找到对应的结点,如果该结点的左孩子不空,找到以它的左孩子为根的子树中的最大值结点
// 否则如果该结点的左孩子空,找到第一个有右孩子的祖先结点
BSNode *BSTree::getInOrderPre(BSNode *root, int item)
{
BSNode *pPre = NULL;//指向该结点的前驱结点的指针
BSNode *pNode = NULL;
if (Find(root, pNode, item))//找到对应的结点
{
if (pNode->m_lchild != NULL)//该结点的左孩子不空
{
BSNode *maxNode = NULL;
int max = Max(pNode->m_lchild, maxNode);//找到以它的左孩子为根的子树中的最大值结点
pPre = maxNode;
}
else//该结点的左孩子为空
{
//找到第一个有右孩子的祖先结点
BSNode *pParent = GetParent(item);
;
while(pParent->m_rchild == NULL)//右孩子为空
{
pParent = GetParent(pParent->data);
}
pPre = pParent;
}
return pPre;
}
else
{
cout << "数值为" << item << "的结点不存在!";
return pNode;
}
}
//获取中序遍历的后继结点
//思想:先找到对应的结点,如果右孩子节点非空,则找到右子树的最小值节点
//否则如果右孩子节点为空,则找到第一个有左孩子节点的其祖辈节点
BSNode *BSTree::GetInOrderPost(int item)
{
return getInOrderPost(root, item);
}
//获取中序遍历的后继结点
BSNode *BSTree::getInOrderPost(BSNode *root, int item)
{
BSNode *pPost = NULL;//指向后继结点的指针
BSNode *pNode = NULL;
if (Find(root, pNode, item))
{
if (pNode->m_rchild != NULL)//该结点的右孩子不空
{
//找到以其右孩子为根的子树中最小值的结点
BSNode *minNode = NULL;
int mint = Min(pNode->m_rchild, minNode);
pPost = minNode;
}
else//该结点的右孩子为空
{
//找到第一个有左孩子的祖先结点
BSNode *pParent = GetParent(item);
while(pParent->m_lchild == NULL)
{
pParent = GetParent(pParent->data);
}
pPost = pParent;
}
return pPost;
}
else
{
cout << "数值为" << item << "的结点不存在!" << endl;
return pPost;
}
}
//用栈实现非递归的先序遍历
void BSTree::PreOrderVisit()
{
PreOrder(root);
}
//用栈实现非递归的先序遍历
void BSTree::PreOrder(BSNode *root)
{
//定义栈
BSNode* stack[STACK_MAXSIZE];
int top = 0;//top为0表示栈空,指向栈顶的下一个位置
BSNode *p = root;
cout << "二叉树的先序遍历:";
while(p || (top != 0))//指针不空或栈不空
{
if (p)
{
stack[top++] = p;//入栈
cout << p->data << " ";//访问该结点
p = p->m_lchild;
}
else
{
p = stack[--top];//出栈
p = p->m_rchild;
}
}
cout << endl;
}
//用栈实现非递归的中序遍历
void BSTree::InOrderVisit()
{
InOrder(root);
}
//用栈实现非递归的中序遍历
void BSTree::InOrder(BSNode *root)
{
//定义栈
BSNode* stack[STACK_MAXSIZE];
int top = 0;//top为0表示栈空,指向栈顶的下一个位置
BSNode *p = root;
cout << "二叉树的中序遍历:";
while(p || (top != 0))//指针不空或栈不空
{
if (p)
{
stack[top++] = p;//入栈
p = p->m_lchild;
}
else
{
p = stack[--top];//出栈
cout << p->data << " ";//访问该结点
p = p->m_rchild;
}
}
cout << endl;
}
//用栈实现非递归的后序遍历,后序遍历较为复杂,需要用到两个栈
void BSTree::PostOrderVisit()
{
PostOrder(root);
}
//用栈实现非递归的后序遍历,后序遍历较为复杂,需要用到两个栈
void BSTree::PostOrder(BSNode *root)
{
//定义栈
BSNode* stack1[STACK_MAXSIZE];
BSNode* stack2[STACK_MAXSIZE];
int top1 = 0;//top为0表示栈空,指向栈顶的下一个位置
int top2 = 0;
BSNode *p = root;
cout << "二叉树的后序遍历:";
while(p || (top1 != 0))//指针不空或栈不空
{
if (p)
{
stack1[top1++] = p;//入栈1
stack2[top2++] = p;//入栈2
p = p->m_rchild;//注意此处是指向右孩子
}
else
{
p = stack1[--top1];//栈1的栈顶元素出栈,栈2元素不出栈
p = p->m_lchild;
}
}
while(top2 != 0)
{
p = stack2[--top2];//栈2栈顶元素出栈
cout << p->data << " ";//访问该结点
}
cout << endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
BSTree tree;
tree.CreateTree();
tree.PreOrderVisit();
tree.InOrderVisit();
tree.PostOrderVisit();
int item = 0;
cout << "请输入要查找的结点值:";
cin >> item;
cout << item << "存在返回1,否则返回0.结果是:" << tree.FindNode(item) << endl;
cout << item << "的双亲是:" ;
if (tree.GetParent(item))
{
cout << tree.GetParent(item)->data << endl;
}
else
{
cout << "该结点为根结点,不存在双亲!" << endl;
}
cout << item << "中序遍历序列中前驱结点值是:" << tree.GetInOrderPre(item)->data << endl;
cout << item << "中序遍历序列中后继结点值是:" << tree.GetInOrderPost(item)->data << endl;
tree.InsertNode(100);
tree.InsertNode(48);
tree.DeleteNode(50);
tree.DeleteNode(45);
tree.DeleteNode(55);
tree.InOrderVisit();
cout << "二叉排序树中,最大值为:" << tree.MaxNode() << endl;
cout << "二叉排序树中,最小值为:" << tree.MinNode() << endl;
system("pause");
return 0;
}