二叉搜索树基本功能实现

/*二叉搜索树中的节点类
 *Node.h
 */
# ifndef _NODE_
#define _NODE_
class Node
{
private:
	int value;/*节点中存放的元素值*/
	Node *parentNode;/*所指向的父节点指针*/
	Node *leftChildNode;/*左孩子节点指针*/
	Node *rightChildNode;/*右孩子节点指针*/
public:
	Node(int v);/*初始化函数*/
	Node* getParentNode();/*返回父节点指针*/
	Node* getLeftChildNode();/*返回左孩子节点指针*/
	Node* getRightChildNode();/*返回右孩子节点指针*/
	int getValue();/*返回节点元素值*/
	void setParentNode(Node *p);/*设定父节点指针*/
	void setLeftChildNode(Node *left);/*设定左孩子节点*/
	void setRightChildNode(Node *right);/*设定右孩子结点*/
	void setValue(int v);/*设定节点元素值*/
};
#endif
/*
 *Node.cpp
 */
#include "Node.h"
#include <cstdio>	//NULL

/*初始化函数*/
Node::Node(int r)
{
	setValue(r);
	setParentNode(NULL);
	setLeftChildNode(NULL);
	setRightChildNode(NULL);
}
/*返回父节点指针*/
Node* Node::getParentNode()
{
	return parentNode;
}
/*返回右孩子节点指针*/
Node* Node::getRightChildNode()
{
	return rightChildNode;
}
/*返回左孩子节点指针*/
Node* Node::getLeftChildNode()
{
	return leftChildNode;
}
/*返回节点元素值*/
int Node::getValue()
{
	return value;
}
/*设定左孩子节点*/
void Node::setLeftChildNode(Node *left)
{
	leftChildNode = left;
}
/*设定父节点指针*/
void Node::setParentNode(Node *parent)
{
	parentNode = parent;
}
/*设定右孩子结点*/
void Node::setRightChildNode(Node *right)
{
	rightChildNode = right;
}
/*设定节点元素值*/
void Node::setValue(int v)
{
	value = v;
}
/*二叉搜索树类:
 *BinarySearchTree.h
 */
#ifndef _BINARYSEARCHTREE_
#define _BINARYSEARCHTREE_
#define MAXLENGTH 100 //二叉搜索树的最大节点总数
#include "Node.h"
class BinarySearchTree
{
private:
	Node *rootNode;/*根节点指针*/
public:
	BinarySearchTree();/*构造函数初始化*/
	void setRootNode(Node *root);/*设置根节点*/
	void treeInsert(int v);/*向搜索数中添加节点*/
	void levelTreeWalk(Node *start);/*层次遍历*/
	void inorderTreeWalk(Node *start);/*中序遍历*/
	void preorderTreeWalk(Node *start);/*先序遍历*/
	void postorderTreeWalk(Node *start);/*后序遍历*/
	void transplant(Node *u,Node *v);/*将节点v替换到u的位置,并且相应子树进行转换*/
	bool deleteNode(Node *point);/*从搜索树中删除节点point*/
	bool max(int x,int y);/*比较两个整型元素值大小,x<y返回false*/
	int getNodeNumber(Node *start);/*得到以start为根的树的节点总数*/
	int getTreeHeight();/*计算二叉搜索树的高度*/
	int getNodeHeight(Node *start);/*计算节点start的高度*/
	Node* getRootNode();/*得到根节点指针*/
	Node* getMinimum(Node *start);/*得到以start节点为根的搜索数中的具有最小元素值的节点*/
	Node* treeMax(Node *start);//递归版本的得到具有最大元素值的节点
	Node* getMaximum(Node *start);/*得到以start为根节点的搜索数中的具有最大元素值的节点*/
	Node* getTreeSuccessor(Node *start);/*得到节点start的后继节点*/
	Node* getTreePredessor(Node *start);/*得到start的前驱节点*/
	Node* treeSearch2(Node *start,int k);/*迭代版本*/
	Node* treeSearch1(Node *start,int k);/*搜索数的查找,如果k存在于搜索树中,
							               (从树根开始查找,)则返回给节点,否则返回null*/
};
#endif
/*
 *BinarySearchTree.cpp
 */
#include "BinarySearchTree.h"
#include <cstdio>
#include <iostream>
using namespace std;

/*构造函数初始化*/
BinarySearchTree::BinarySearchTree()
{
	setRootNode(NULL);
}
/*得到根节点指针*/
Node* BinarySearchTree::getRootNode()
{
	return rootNode;
}
/*设置根节点*/
void BinarySearchTree::setRootNode(Node *root)
{
	rootNode = root;
}

/*向搜索数中添加节点,输入是新的节点元素值*/
void BinarySearchTree::treeInsert(int v)
{
	/*新的插入的节点*/
	Node *newInsertNode = new Node(v);
	Node *y = NULL;
	Node *x = getRootNode();//得到根节点
	/*通过while循环中元素比较得到新的节点的合适位置*/
	while(x!=NULL)
	{
		y = x;
		if(v < x->getValue())    /*二叉搜索树的性质:x.left.value<x.value;*/
			x = x->getLeftChildNode();
		else                             /*x.right.value>=x.values*/
			x = x->getRightChildNode();
	}
	//y = newInsertNode;
	if(y == NULL)//二叉搜索树为空的情况
		setRootNode(newInsertNode);
	else if(v < y->getValue())
	{
		y->setLeftChildNode(newInsertNode);
		newInsertNode->setParentNode(y);
	}
	else
	{
		y->setRightChildNode(newInsertNode);
		newInsertNode->setParentNode(y);
	}
}

/*从搜索树中删除节点point,如果删除成功,返回true,
                                       如果是空子树,返回false*/
/*1、point没有左右子孩子,直接删除point
 *2、point没有左孩子的情况,直接删除point并把右孩子放到原来point位置
        上面两种情况可以归为一类情况:没有左孩子,将右孩子放到point位置
   3、只有左孩子情况,把左孩子放到point位置,删除point
   4、左右孩子都有的情况:查找point节点的后继节点successor 
        1、如果successor为point右孩子(既然为point右孩子,则successsor没有左孩子)
		    将point左孩子作为successor左孩子,successor替换point,删除point节点
	    2、如果successor不是point的右孩子(是以point右孩子为根节点的子树最小值所在节点
		    且没有左孩子)将successor右节点sright作为successor所在子树根节点,并将point
			右孩子节点pright作为successor右节点,successor左孩子节点pleft作为successor
			左孩子节点,删除point,,,
 */
bool BinarySearchTree::deleteNode(Node *point)
{
	/*搜索树为空或point为空时进行的操作*/
	if(point == NULL || getRootNode() == NULL)
		return false;
	/*如果节点point不再搜索树中*/
	if(treeSearch1(getRootNode(),point->getValue()) == NULL)
		return false;
	/*下面的就是讨论的三种情况:*************************/
	/*1、point的左孩子节点为空*/
	if(point->getLeftChildNode() == NULL)
		transplant(point,point->getRightChildNode());
	/*2、point的右孩子节点为空*/
	else if(point->getRightChildNode() == NULL)
		transplant(point,point->getLeftChildNode());
	/*3、point的左右孩子节点均不为空*/
	else
	{
		/*得到point的后继节点*/
		Node *successor = getMinimum(point->getRightChildNode());
		/*当successor不为point的右孩子节点时进行的操作*/
		if(successor->getParentNode() != point)
		{
			transplant(successor,successor->getRightChildNode());
			successor->setRightChildNode(point->getRightChildNode());
			successor->getRightChildNode()->setParentNode(successor);
		}
		transplant(point,successor);
		successor->setLeftChildNode(point->getLeftChildNode());
		successor->getLeftChildNode()->setParentNode(successor);
	}
	delete point;
	return true;
}
/*此时u节点右节点为空,v节点左孩子为空,将u的左孩子节点放到v的左孩子节点处
   并把u的父节点作为v的父节点,即删除u节点
   此函数的作用是将u的父节点作为v的父节点,v作为u的父节点的原u位置相应子节点
 v可以为空节点,也可以不是,对于u的左孩子节点的处理,由这个函数的调用者进行
 处理
*/
void BinarySearchTree::transplant(Node *u,Node *v)
{
	if(u->getParentNode() == NULL)
		setRootNode(v);
	else if(u == u->getParentNode()->getLeftChildNode())
		u->getParentNode()->setLeftChildNode(v);
	else
		u->getParentNode()->setRightChildNode(v);
	if(v != NULL)
		v->setParentNode(u->getParentNode());
}

/*得到以start节点为根的搜索数中的具有最小元素值的节点*/
/*while迭代版本:*/
Node* BinarySearchTree::getMinimum(Node *start)
{
	Node *minNode = start;
	if(minNode == NULL)//空树的情况
		return minNode;
	while(minNode->getLeftChildNode() != NULL)
	{
		minNode = minNode->getLeftChildNode();
	}
	return minNode;
}
/*得到以start为根节点的搜索数中的具有最大元素值的节点*/
/*递归版本:*/
Node* BinarySearchTree::getMaximum(Node *start)
{
	return treeMax(start);
}
Node* BinarySearchTree::treeMax(Node *start)
{
	if(start == NULL)
		return NULL;
	else if(start->getRightChildNode() == NULL)
		return start;
	else
		return treeMax(start->getRightChildNode());
}

/*得到以start为根的树的节点总数*/
int BinarySearchTree::getNodeNumber(Node *start)
{
	if(start == NULL)
		return 0;
	if(start->getLeftChildNode() ==NULL)
		return getNodeNumber(start->getRightChildNode()) + 1;
	if(start->getRightChildNode() == NULL)
		return getNodeNumber(start->getLeftChildNode()) + 1;
	return getNodeNumber(start->getLeftChildNode()) + 
		getNodeNumber(start->getRightChildNode()) + 1;
}
/*层次遍历*/
void BinarySearchTree::levelTreeWalk(Node *start)
{
	if(start == NULL)
	{
		cout << "这是一个空子树," << endl;
		return;
	}
	/*定义一个数组来存放层次遍历过程中的节点指针,最大为MAXLENGTH*/
	Node *B[MAXLENGTH + 1];
	B[1] = start;/*根节点放到B[1]处*/
	int nodeNumber = getNodeNumber(start);/*树中节点个数*/
	int counter = 1;//已经放到数组B中的节点个数
	int k = 1;/*在之后的每次循环中,counter之前有k个节点需要得到子节点放入数组B*/
	int m,i;//寄存器值
	while(counter < nodeNumber)
	{
		m = 0;
		/*循环得到counter之前的k个节点它们的子节点*/
		for(i = 1;i <= k;i ++)//k其实就是每一层中的节点个数
		{
			if(B[counter-k+i]->getLeftChildNode() != NULL)
			{
				m ++;
				B[counter + m] = B[counter-k+i]->getLeftChildNode();
			}
			if(B[counter-k+i]->getRightChildNode() != NULL)
			{
				m ++;
				B[counter + m] = B[counter-k+i]->getRightChildNode();
			}
		}
		k = m;
		counter = counter + k;
	}
	for(i = 1;i <= nodeNumber;i++)
		cout << B[i]->getValue() << " ";
}
/*中序遍历:<<<<左根右>>>>*/
void BinarySearchTree::inorderTreeWalk(Node *start)
{
	if(start != NULL)
	{
		inorderTreeWalk(start->getLeftChildNode());
		cout << start->getValue() << " ";
		inorderTreeWalk(start->getRightChildNode());
	}
}
/*先序遍历:<<<<根左右>>>>*/
void BinarySearchTree::preorderTreeWalk(Node *start)
{
	if(start != NULL)
	{
		cout << start->getValue() << " ";
		preorderTreeWalk(start->getLeftChildNode());
		preorderTreeWalk(start->getRightChildNode());
	}
}
/*后序遍历:<<<<左右根>>>>*/
void BinarySearchTree::postorderTreeWalk(Node *start)
{
	if(start != NULL)
	{
		preorderTreeWalk(start->getLeftChildNode());
		preorderTreeWalk(start->getRightChildNode());
		cout << start->getValue() << " ";
	}
}

/*计算二叉搜索树的高度*/
int BinarySearchTree::getTreeHeight()
{
	return getNodeHeight(getRootNode()) - 1;
}
/*计算节点start的高度*/
int BinarySearchTree::getNodeHeight(Node *start)
{
	if(start == NULL)
		return 0;
	int leftChildLength = getNodeHeight(start->getLeftChildNode());
	int rightChildLength = getNodeHeight(start->getRightChildNode());
	
	/*这两个判断语句是把递归进行到二叉树的叶子节点进行判断并把
	   叶子节点的高度(本来为0)加一*/
	if(max(leftChildLength,rightChildLength))
		return leftChildLength + 1;
	else
		return rightChildLength + 1;
}
/*比较两个整型元素值大小,x<y返回false,x>=y返回true*/
bool BinarySearchTree::max(int x,int y)
{
	if(x >= y)
		return true;
	else
		return false;
}

/*得到节点start的后继节点,如果后继节点存在,则返回,
   如果后继节点为自身,则返回null*/
Node* BinarySearchTree::getTreeSuccessor(Node *start)
{
	if(start->getRightChildNode() != NULL)
		return getMinimum(start->getRightChildNode());
	Node *y = start->getParentNode();//叶子节点的情况
	/*仍是二叉搜索树的性质决定*/
	while(y != NULL && start == y->getRightChildNode ())
	{
		start = y;
		y = y->getParentNode();
	}
	return y;
}
/*得到start的前驱节点如果前驱节点存在,则返回,如果前驱节点
   为自身,则返回null*/
Node* BinarySearchTree::getTreePredessor(Node *start)
{
	if(start->getLeftChildNode() != NULL)
		return getMaximum(start->getLeftChildNode());
	Node *y = start->getParentNode();
	while(y != NULL && start == y->getRightChildNode())
	{
		start = y;
		y = y->getParentNode();
	}
	return y;
}

/*搜索数的查找,如果k存在于搜索树中,则返回给节点,否则返回null*/
Node* BinarySearchTree::treeSearch1(Node *start,int k)
{
	Node *temp = start;
	if(temp == NULL || k == temp->getValue())
		return temp;
	if(k < start->getValue())
		return treeSearch1(temp->getLeftChildNode(),k);
	else
		return treeSearch1(temp->getRightChildNode(),k);
}
/*搜索的while迭代版本*/
Node* BinarySearchTree::treeSearch2(Node *start,int k)
{
	Node *temp = start;
	while(temp != NULL && k != temp->getValue())
	{
		if(k < temp->getValue())
			temp = temp->getLeftChildNode();
		else 
			temp = temp->getRightChildNode();
	}
	return temp;
}
		




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值