您的位置:首页 > 其它

二叉排序树

2016-02-03 23:51 211 查看
二叉查找树(英语:Binary Search Tree),也称二叉搜索树、有序二叉树(英语:ordered binary tree),排序二叉树(英语:sorted
binary tree),是指一棵空树或者具有下列性质的二叉树:

任意节点的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
若任意节点的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
任意节点的左、右子树也分别为二叉查找树;
没有键值相等的节点。

从上述定义可知,二叉排序树是记录之间满足一定次序关系的二叉树。下面介绍如何构建一棵二叉排序树,以及遍历,插入,查找,也会简单的介绍删除结点操作。

构造一棵排序二叉树,则一定要根据其定义来实现。下面给出相关代码:

#include<iostream>
using namespace std;
typedef struct bstNote {
	int data;
	struct bstNote *lchild, *rchild;
}*bstTree;

void insertNote(bstTree &bst, int _data) {
	if (bst == NULL) {
		bst = new bstNote;
		bst->data = _data;
		bst->lchild = bst->rchild = NULL;
		return;
	}
	if (bst->data == _data) {
		exit(-1);
	}
	
	else if(bst->data > _data) 
		insertNote(bst->lchild, _data);
	
	  else
		  insertNote(bst->rchild, _data);
}
void createBST(bstTree  &bst,int *arry,int length){
    bst = NULL;

	for (int i = 0; i < length; i++) {
		insertNote(bst, arry[i]);
	}
}
void preOrder(bstTree bst) {
if (bst == NULL) {
		return;
	}

		cout << bst->data << " ";
		preOrder(bst->lchild);
		preOrder(bst->rchild);
	
}
void inOrder(bstTree bst) {
	if (bst == NULL) {
		return;
	}
	inOrder(bst->lchild);
	cout << bst->data << " ";
	inOrder(bst->rchild);
}
void postOrder(bstTree bst) {
	if (bst == NULL) {
		return;
	}
	postOrder(bst->lchild);
	postOrder(bst->rchild);
	cout << bst->data << " ";
}
bstTree searchBST(bstTree bst, int key) {
	if (bst == NULL)
		return false;
	else if (bst->data == key) {
		cout << "查找成功:"<<bst->data<< endl;
		return bst;
	}
	else if(bst->data>key)
		return searchBST(bst->lchild, key); 
	else
		return searchBST(bst->rchild, key);
}
int main(){
	bstTree bst;
	int arry[] = {4,5,2,1,3,10,7,8,6,0};
	int length = sizeof(arry) / sizeof(int);
	createBST(bst, arry, length);
	cout << "PreOrder:" << endl;;
	preOrder(bst);
	cout << endl;
	cout << "InOrder:" << endl;
	inOrder(bst);
	cout << endl;
	cout << "PostOrder:" << endl;;
	postOrder(bst);
	cout << endl;
	searchBST(bst,6); 
	insertNote(bst, 9);
	preOrder(bst);
	cout << endl;
	inOrder(bst);
}
上面的代码比较简单的实现构造,遍历,查找。

但是在二叉查找树删去一个结点,分三种情况讨论:(如下参考维基百科:点击打开链接)

1.若*p结点为叶子结点,即PL(左子树)和PR(右子树)均为空树。由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针即可。

2.若*p结点只有左子树PL或右子树PR,此时只要令PL或PR直接成为其双亲结点*f的左子树(当*p是左子树)或右子树(当*p是右子树)即可,作此修改也不破坏二叉查找树的特性。

3.若*p结点的左子树和右子树均不空。在删去*p之后,为保持其它元素之间的相对位置不变,可按中序遍历保持有序进行调整,可以有两种做法:其一是令*p的左子树为*f的左/右(依*p是*f的左子树还是右子树而定)子树,*s为*p左子树的最右下的结点,而*p的右子树为*s的右子树;其二是令*p的直接前驱(in-order predecessor)或直接后继(in-order
successor)替代*p,然后再从二叉查找树中删去它的直接前驱(或直接后继),该种情况较为复杂,如下图示。



算法:

Status DeleteBST(BiTree &T, KeyType key){
  //若二叉查找树T中存在关键字等于key的数据元素时,则删除该数据元素,并返回
  //TRUE;否则返回FALSE
  if(!T) 
    return false;	//不存在关键字等于key的数据元素
  else{
    if(key == T->data.key) { 	//  找到关键字等于key的数据元素
      return Delete(T);
    }
    else if(key < T->data.key)
      return DeleteBST(T->lchild, key);
    else
      return DeleteBST(T->rchild, key);
  }
}
Status Delete(BiTree &p){
  //该节点为叶子节点,直接删除
  BiTree *q, *s;
  if (!p->rchild && !p->lchild)
  {
      delete p;
      p = NULL;
  }
  else if(!p->rchild){	//右子树空则只需重接它的左子树
    q=p->lchild;
    p->data = p->lchild->data;
    p->lchild=p->lchild->lchild;
    p->rchild=p->lchild->rchild;

    delete q;
  }
  else if(!p->lchild){	//左子树空只需重接它的右子树
    q=p->rchild;
    p->data = p->rchild->data;
    p->lchild=p->rchild->lchild;
    p->rchild=p->rchild->rchild;

    delete q;  }
  else{	//左右子树均不空
    q=p; 
    s=p->lchild;
    while(s->rchild){ 
      q=s; 
      s=s->rchild;
    }	//转左,然后向右到尽头
    p->data = s->data;	//s指向被删结点的“前驱”
    if(q!=p)	
      q->rchild = s->lchild;	//重接*q的右子树
    else 
      q->lchild = s->lchild;	//重接*q的左子树
    delete s;
  }
  return true;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: