您的位置:首页 > 其它

二叉搜索树(Binary Search Tree)

2017-01-18 17:13 113 查看

概述

二叉搜索树(Binary Search Tree)或者称为二叉排序树(Binary Sort Tree),它是一棵空树;或者是具有下列性质的二叉树:1.若它的左子树不空,则左子树树上的所有节点的值均小于它的根节点的值;2.或者是具有下列性质的二叉树:1.若它的右子树不空,则右子树上的所有节点的值均小于它的根节点的值;3.它的左,右子树也分别为二叉搜索书(二叉排序树)[1](注:是一个递归定义)

具体结构如图:


[1]

定义数据结构

二叉树的节点

// node of tree
typedef struct Node{
ElemType key;
struct Node *left;
struct Node *right;
struct Node *p;
}Node;
二叉搜索树:root指针指向第一个插入的元素的节点即把第一个插入的节点作为树根

// root of tree
typedef struct Tree{
struct Node *root;
} *Tree;

函数操作

1. 插入

核心思想:1.若是一棵空树,则树根指向该节点;2.若是根节点的key值大于该节点的key值,则插入根节点的左子树,否则插入根节点的右子树(注:相等的则放弃插入)。

过程如图:


              


  原始节点
插入节点值为6的节点 插入节点值为3的节点

代码

void insert(Tree tree, ElemType key) {
// allocate Node & initial
Node *node = (Node *) malloc(sizeof(Node));
if(!node) {
printf("Node allocation failed!\n");
exit(-1);
}
node->key = key;
node->left = NULL;
node->right = NULL;

// insert the node into the tree
Node *p = tree->root;
if(p == NULL) { // a emty tree
node->p = NULL;
tree->root = node;
return;
}
// find the parent of this node;
Node * cur = NULL;
while(p != NULL) {
cur = p;
if(p->key > key) {
p = p->left;
} else if(p->key < key){
p = p->right;
} else {
// the elem already existed
free(node);
node = NULL;
return;
}
}
//point to its parent
node->p = cur;
// binds node
if(cur->key > key) {
cur->left = node;
} else {
cur->right = node;
}
}

2. 寻找最小节点

核心思想:找到树根的最左子节点

// find the minimum key from this node to its sub nodes
// return the minimum node
Node * minimumFromNode(Node *node) {
Node *p = node;
if (p) {
while(p->left) {
p = p->left;
}
}
return p;
}
// find the minimum node in this tree
Node * minimumInTree(Tree t) {
return minimumFromNode(t->root);
}

3.寻找最大子节点

核心思想:寻找根节点的最右子节点

// find the maximum key from this node to its sub nodes
// return the maximum node
Node *maximumFromNode(Node *node) {
Node *p = node;
if (p) {
while(p->right) {
p = p->right;
}
}
return p;
}

// find the maxmum node in this tree
Node *maximumInTree(Tree t) {
return maximumFromNode(t->root);
}

4.寻找值为key的节点

核心思想:和插入的思想差不多,从根节点开始,key值大于根节点的key值则从根节点的右子树寻找,若小于则往根节点的左子树寻找,否则相等则直接返回该节点。

代码:

// search the tree and find whether the key is in this tree
// in this tree, return this node, else return NULL
Node* search(Tree t, ElemType key) {
Node *p = t->root;
while(p) {
if(p->key > key) {
p = p->left;
} else if(p->key < key) {
p = p->right;
} else {
return p;
}
}
return NULL;
}

5.中序遍历树

直接上代码(代码比较简介):
// tracerse all tree in order
void inOrder(Node * node) {
if(node != NULL) {
inOrder(node->left);
printf("%d ", node->key);
inOrder(node->right);
}
}
void traverseInOrder(Tree t){
inOrder(t->root);
}

6.查找某一节点的后继节点

核心思想:主要有两种情况:1.该节点有右子树;2.该节点有右子树;3.最后一个节点(即树中最大节点)

情况1:



对于有右子树的节点,可以找它的右子节点(图中为节点值为10的节点)为根节点的最小节点(图中为值为8的节点)

情况2:



对于没有右子树的节点a(图中值为9的节点),一直往上找到它的父节点或父节点以上节点b(图中为值为5的节点),一直到节点b是它节点b父亲的左孩子,则b节点的父亲(图中为值为11的节点)作为a的后继节点。

情况3:

直接后继返回NULL

代码:
// find the successor node
Node * successor(Node * node) {
// this node has a right node
if (node->right) {
return minimumFromNode(node->right);
}
// this node has no right node
Node * y = node->p;
Node * x = node;
while (y != NULL && x == y->right) {
x = y;
y = y->p;
}
return y;
}

7删除

删除节点主要有如下3种情况


    

 
 


情况1:只有左子树,没有右子树

解决:只需要删除节点z并让其左子树和其父亲相连接,最后删除y

情况2;只有右子树,而没有左子树

解决:只需要删除节点z并让其右子树和其父亲相连接,最后删除y

情况3:既有有左子树,又有右子树

解决:找到其后继节点y,并将有的子节点和y的父节点相连,并将y的值替换z的值,最后删除y

代码:

// delete the node in tree
void delete(Tree t, Node *node) {
Node *y = NULL;
// node has one sub node at most
if(node->right != NULL || node->left != NULL) {
y = node;
} else { // the node has twe sub nodes
y = successor(node);
}
// because y has one node at most
// and find its sub node
Node * x = NULL;
if(y->left != NULL) {
x = y->left;
} else {
x = y->right;
}
// binds x's parent node
if(x != NULL) {
x->p = y->p;
}

// x's parent binds x
if(y->p == NULL) { // the node, which'll be deleted, is root node
t->root = x;
} else if (y == y->p->left) {
y->p->left = x;
} else {
y->p->right = x;
}
// if node has two sub nodes, copy the successor key to the node
// and delete successor which is y
if (node != y) {
node->key = y->key;
}
// deallocate the memory
free(y);
y = NULL;
}



参考

[1]严蔚敏《数据结构(C语言版)》p227

注:若有参考遗漏的,请留言。

代码完全下载

转载请注明
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: