在排序中,之前利用大小根堆的方式,保持最小值或者最大值在堆顶端
二叉排序树是保持这棵树一直是有序的
二叉排序树的建立,不同于堆操作只需要对非叶子节点进行处理,保持其大于左右孩子,或者是小于左右孩子,而是需要对每一个点都进行处理,因为他是相对而言更加
严谨的操作
查找一个数据:对于大根堆操作,如果当前值小于根节点,那么这个值在左右分支出现都是由可能得,但是对于BST,如果小那么肯定在左分支,如果大,那么肯定在右分支
删除一个元素:对于堆,一般都是由于排序会删除堆顶元素,那么删除之后由最后一个元素补上,然后再检验其情况
对于二叉树,如果删除的元素只有一个孩子,那么由这个孩子代替,如果有两个孩子,那么在右分支中找到最小的元素代替
#include <iostream>
#include <stack>
using namespace std;
//二叉排序树,完成创建节点,插入节点,删除节点,查找节点,中序遍历的功能
//节点类定义
class Node{
public:
int data;//数据
Node *parent;//父节点
Node *left;//左子节点
Node *right;//右子节点
public:
Node():data(-1),parent(NULL),left(NULL),right(NULL){}
Node(int num):data(num),parent(NULL),left(NULL),right(NULL){}
};
//二叉排序树类定义
class Tree{
public:
Tree(int num[],int len);//插入num数组的前len个数据
void InsertNode1(int data);//插入节点,非递归方法
void InsertNode(int data);//插入节点,递归方法
Node* SearchNode(int data);//查找节点,递归方法
void DeleteNode(int data);//删除节点及其子树,递归方法
void InOrderTree();//中序遍历,递归方法
void InOrderTreeUnRec();
private:
void InsertNode(Node *current,int data);//递归插入方法
Node *SearchNode(Node *current,int data);//递归查找方法
void DeleteNode(Node *current);//递归删除方法
void InOrderTree(Node *root);//中序遍历,递归方法
private:
Node *root;//二叉排序树的根节点
};
//构造函数中创建二叉排序树
//首先生成根节点,然后循环调用插入节点函数使二叉排序树进行插入操作
Tree::Tree(int num[], int len){
root=new Node(num[0]);//建立root节点
//把数组中的其他数据插入到二叉排序树中
for (int i=1;i<len;i++){
//InsertNode(num[i]);
InsertNode1(num[i]);
}
}
//插入节点操作
//插入数据为参数data的节点,非递归方法
void Tree::InsertNode1(int data){
Node *p,*par;
Node *newNode=new Node(data);//创建节点
p=par=root;
while (p!=NULL){//查找插入在哪个节点下面
par=p;//保存节点
if (data>p->data){ //如果data大于当前节点的data
p=p->right;//下一步到右子节点
}
else if (data<p->data){//如果data小于当前节点的data
p=p->left;//下一步到左子节点
}
else if (data==p->data){//不能插入重复数据
delete newNode;
return;
}
}
newNode->parent=par;
if (par->data>newNode->data){ //把新节点插入在目标节点的正确位置
par->left=newNode;
}
else
par->right=newNode;
}
//插入节点操作
//插入数据为参数data的节点,递归方法,内部调用了private成员函数InsertNode()
void Tree::InsertNode(int data){
if (root!=NULL){
InsertNode(root,data);//调用递归插入方法
}
}
//递归插入方法
void Tree::InsertNode(Node *current, int data){
if (data<current->data){//如果data小于当前节点数据,在当前节点的左子树插入
if (current->left==NULL){//如果左子节点不存在,则插入到左节点
current->left=new Node(data);
current->left->parent=current;
}
else
InsertNode(current->left,data);//对左节点进行递归调用
}
else if (data>current->data){//如果data大于当前节点数据,则当前节点的右边子树插入
if (current->right==NULL){//如果右子树不存在,则插入到右节点
current->right=new Node(data);
current->right->parent=current;
}
else
InsertNode(current->right,data);//对右节点进行递归调用
}
return; //data等于当前节点数据时,不插入
}
//递归查找方法
Node* Tree::SearchNode(Node *current, int data){
if (data<current->data){//如果data小于当前节点数据,递归搜索其左子树
if (current->left==NULL){//如果不存在左子树,返回NULL
return NULL;
}
return SearchNode(current->left,data);
}
else if (data>current->data){//如果data大于当前节点数据,递归搜索其右子树
if (current->right==NULL){//如果不存在右子树,返回NULL
return NULL;
}
return SearchNode(current->right,data);
}
return current;//如果相等返回current
}
//查找节点
Node* Tree::SearchNode(int data){
if (root==NULL){
return NULL;
}
return SearchNode(root,data);
}
//删除数据为data的节点及其子树
void Tree::DeleteNode(int data){
Node *current=NULL;
current=SearchNode(data);//查找节点
if (current!=NULL){
DeleteNode(current);//删除节点及其子树
}
}
//删除current节点及其子树的所有节点
void Tree::DeleteNode(Node *current){
if (current->left!=NULL){ //删左子树
DeleteNode(current->left);
}
if (current->right!=NULL){//删右子树
DeleteNode(current->right);
}
if (current->parent==NULL){//如果current是根节点,把root置空
delete current;
root=NULL;
return;
}
//将current父亲节点的相应指针置空
if (current->parent->data>current->data){ //current为其父节点的左子节点
current->parent->left=NULL;
}
else{//current为其父节点的右子节点
current->parent->right=NULL;
}
//最后删除此节点
delete current;
}
//中序遍历,递归方法
void Tree::InOrderTree(Node *current){
if (current!=NULL){
InOrderTree(current->left);//遍历左子树
cout<<current->data<<" ";//打印节点数据
InOrderTree(current->right);//遍历右子树
}
}
//中序遍历
void Tree::InOrderTree(){
if (root==NULL){
cout<<"The Tree Is Empty!"<<endl;
getchar();
return;
}
InOrderTree(root);
}
//中序遍历,非递归方法
/*可以用栈来临时存储节点
先将根节点存入栈中,遍历左子树
遍历完左子树返回时,栈顶元素应为根节点,此时出栈,并打印节点数据
在中序遍历右子树
*/
void Tree::InOrderTreeUnRec(){
stack<Node *>s;
Node *p=root;
while (p!=NULL ||!s.empty()){
while (p!=NULL){//遍历左子树
s.push(p);//把遍历的节点全部压栈
p=p->left;
}
if (!s.empty()){
p=s.top();//得到栈顶内容
s.pop();//出栈
cout<<p->data<<" ";//打印
p=p->right;//指向右子节点,下一次循环时就会中序遍历右子树
}
}
}
int main()
{
/* 测试程序*/
int num[5]={1,2,6,4};
Tree t(num,4);
Node *p=NULL;
t.InOrderTree();
cout<<endl;
t.InOrderTreeUnRec();
cout<<endl;
//t.InsertNode1(7);
t.InsertNode(0);
t.InOrderTree();
cout<<endl;
t.InOrderTreeUnRec();
cout<<endl;
p=t.SearchNode(4);
if (p!=NULL){
cout<<p->data<<endl;
}
else
cout<<"Not Find!"<<endl;
t.DeleteNode(2);
t.InOrderTree();
cout<<endl;
t.InOrderTreeUnRec();
system("pause");
return 0;
}
还有用C写的比较简单的程序
/*二叉排序树*/
#include <stdio.h>
#include <crtdbg.h>
#define _CRTDBG_MAP_ALLOC
typedef struct Node{
public:
int data;//<数据
Node *left;//<左子节点
Node *right;//<右子节点
}Node;
void NodeInit(Node *N,int val)
{
N->data = val;
N->left = NULL;
N->right = NULL;
}
void buildPoint(int val,Node * root)
{
if (val < root->data)
{
if (root->left != NULL)
{
buildPoint(val,root->left);
}
else
{
root->left = new Node;
NodeInit(root->left,val);
}
}
if (val >= root->data)
{
if (root->right != NULL)
{
buildPoint(val,root->right);
}
else
{
root->right = new Node;
NodeInit(root->right,val);
}
}
}
void buildBST(int *a, int size,Node * root) //<建立二叉排序树,每一个节点都需要
{
int i = 0;
NodeInit(root,a[0]);
for (i = 1; i < size; i++)
{
buildPoint(a[i],root);
}
}
void scanBST(Node * root) //<类似于中序遍历
{
if (root == NULL)
{
return;
}
if (root->left)
{
scanBST(root->left);
}
printf("%d ",root->data);
if (root->right)
{
scanBST(root->right);
}
}
void destoryPoint(Node *root) //<删除内存
{
Node *left = root->left;
Node *right = root->right;
if (left)
{
destoryPoint(left);
}
delete root;
root = NULL;
if (right)
{
destoryPoint(right);
}
}
int main(int argc, char *argv[])
{
int a[]={0,16,20,3,11,17,8,32,33,232,4,36,0};
int size = sizeof(a)/sizeof(int);
Node * root = new Node;
buildBST(a,size,root);
scanBST(root);
destoryPoint(root); //<如果没有这个,会产生相应的内存泄露
_CrtDumpMemoryLeaks();
return 0;
}