数据结构
二 叉 排序 树( Binary Sort Tree) 又称 二 叉 查找 树( Binary Search Tree)。 其 定义 为: 二 叉 排序 树 或者是 空 树, 或者是 满足 如下 性 质的 二 叉 树。
(1) 若 它的 左 子 树 非 空, 则 左 子 树上 所有 节点 的 值 均 小于 根 节点 的 值。
(2) 若 它的 右 子 树 非 空, 则 右 子 树上 所有 节点 的 值 均 大于 根 节点 的 值。
(3) 左、 右 子 树 本身 又 各 是一 棵 二 叉 排序 树。 上述 性质 简称 二 叉 排序 树 性质( BST 性质), 故 二 叉 排序 树 实际上 是 满足 BST 性 质的 二 叉 树。
下图 就是 一个 简单 的 二 叉 排序 树。
首先 我们 需要 定义 节点 类 以及 二 叉 排序 树 类。 对于 节点 类 来说, 显然 每个 节点 有 向下 的 两个 指针, 而且 每个 节点 都 只有 一个 父 节点。 对于 二 叉 排序 树 类 来说, 只需 要 有数 的 根 节点, 就可以 进行 操作 了。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
#include "stack.h"
st_trNode * createTreeNode(int data){
st_trNode * p = NULL;
p = (st_trNode * ) malloc (sizeof(st_trNode));
if(NULL == p){
printf("createTreeNode alloc failed \n");
return NULL;
}
p->data = data;
p->tag = 0;
p->left = NULL;
p->right = NULL;
p->parent = NULL;
return p;
}
int createTree(st_tree ** ptree){
st_tree * tree = NULL;
tree = (st_tree * ) malloc (sizeof(st_tree));
if(NULL == tree){
printf("createTree alloc failed \n");
return ALLOC_ERR;
}
tree->root = NULL;
*ptree = tree;
return SUCCESS;
}
int insertBSTNode(st_trNode ** proot, st_trNode * node){
if(NULL == proot || NULL == node){
printf("insertBSTNode param error\n");
return PARAM_ERR;
}
st_trNode * root = *proot;
st_trNode * left = NULL, * right = NULL, * p = NULL;;
/* BST的首个节点 */
if(NULL == root){
root = node;
#ifdef DEBUG
printf("1.1 root = %d\n", root->data);
#endif
goto out;
}
/*递归结束条件:叶子节点*/
if(NULL == root->left && NULL == root->right){
#ifdef DEBUG
printf("1.6\n");
#endif
if(node->data < root->data) {
root->left = node;
node->parent = root;
#ifdef DEBUG
printf("1.2 left = %d, parent = %d \n", root->left->data, node->parent->data);
#endif
} else {
root->right = node;
node->parent = root;
#ifdef DEBUG
printf("1.3 right = %d, parent = %d \n", root->right->data, node->parent->data);
#endif
}
goto out;
}
left= root->left;
right = root->right;
#ifdef DEBUG
printf("1.7\n");
#endif
/*向左子树插入*/
if(node->data < root->data){
if(NULL == left){
#ifdef DEBUG
printf("1.4.1 root = %d \n", root->data);
#endif
root->left = node;
node->parent = root;
} else{
#ifdef DEBUG
printf("1.4.2 root = %d, left = %d \n", root->data, left->data);
#endif
insertBSTNode(&left, node);
/*左子树根可能发生变化*/
root->left = left;
left->parent = root;
}
} else { /*向右子树插入*/
if(NULL == right){
#ifdef DEBUG
printf("1.5.1 root = %d \n", root->data);
#endif
root->right = node;
node->parent = root;
} else {
#ifdef DEBUG
printf("1.5.2 root = %d, right = %d \n", root->data, right->data);
#endif
insertBSTNode(&right, node);
/*右子树根可能发生变化*/
root->right = right;
right->parent = root;
}
}
out:
* proot = root;
return SUCCESS;
}
int TraverseTreePreOrder(st_trNode * root){
/*递归结束条件*/
if(NULL == root){
return SUCCESS;
}
printf(" %d ", root->data);
/*左子树*/
if(NULL != root->left)
TraverseTreePreOrder(root->left);
/*右子树*/
if(NULL != root->right)
TraverseTreePreOrder(root->right);
return SUCCESS;
}
/*
* 对于 BST 来说,中序打印出来的是升序的
*/
int TraverseTreeInOrder(st_trNode * root){
/*递归结束条件*/
if(NULL == root){
return SUCCESS;
}
/*左子树*/
if(NULL != root->left)
TraverseTreeInOrder(root->left);
printf(" %d ", root->data);
/*右子树*/
if(NULL != root->right)
TraverseTreeInOrder(root->right);
return SUCCESS;
}
/*
* 对于 BST 来说,中序打印出来的是升序的
*/
int TraverseTreePostOrder(st_trNode * root){
/*递归结束条件*/
if(NULL == root){
return SUCCESS;
}
/*左子树*/
if(NULL != root->left)
TraverseTreePostOrder(root->left);
/*右子树*/
if(NULL != root->right)
TraverseTreePostOrder(root->right);
printf(" %d ", root->data);
return SUCCESS;
}
int dumpTree(st_tree * tree){
/*递归结束条件*/
if(NULL == tree){
return SUCCESS;
}
#if 1
printf("========= Dump Tree PreOder: %p ===========\n\t", tree);
TraverseTreePreOrder(tree->root);
printf("\n===================================\n");
printf("========= Dump Tree PreOder UnRec: %p ===========\n\t", tree);
TraverseTreePreOrderUnrec(tree->root);
printf("\n===================================\n");
#endif
#if 0
printf("========= Dump Tree InOder: %p ===========\n\t", tree);
TraverseTreeInOrder(tree->root);
printf("\n===================================\n");
printf("========= Dump Tree InOderUnrec: %p ===========\n\t", tree);
TraverseTreeInOrderUnrec(tree->root);
printf("\n===================================\n");
#endif
#if 0
printf("========= Dump Tree PostOrder: %p ===========\n\t", tree);
TraverseTreePostOrder(tree->root);
printf("\n===================================\n");
printf("========= Dump Tree PostOrder unRec: %p ===========\n\t", tree);
TraverseTreePostOrderUnrec(tree->root);
printf("\n===================================\n");
#endif
return SUCCESS;
}
st_trNode * SearchBSTreeNode(st_trNode * root, int data){
if(NULL == root){
return NULL;
}
st_trNode * node = NULL;
st_trNode * left = root->left, * right = root->right;
if(data == root->data){
return root;
}
if(NULL == left && NULL == right){
return NULL;
}
if(data < root->data){
if(NULL == left){
return NULL;
} else {
node = SearchBSTreeNode(root->left, data);
}
} else {
if(NULL == right){
return NULL;
} else {
node = SearchBSTreeNode(root->right, data);
}
}
return node;
}
st_trNode * getMostLeftNode(st_trNode * root){
if(NULL == root){
return root;
}
st_trNode * p = NULL;
if(NULL == root->left){
return root;
}
p = root->left;
while(NULL != p->left){
p = p->left;
}
return p;
}
int removeBSTreeNode(st_trNode ** proot, int data){
if(NULL == proot){
printf("removeBSTreeNode param error\n");
return PARAM_ERR;
}
st_trNode * root = *proot;
st_trNode * node = NULL;
st_trNode * left = NULL, * right = NULL, * parent = NULL;
st_trNode * mostsubLeft = NULL; /*右子树的最左子节点*/
int atLeft = 0, atRight = 0;
/* 1. 找data对应的节点 */
node = SearchBSTreeNode(root, data);
if(NULL == node){
printf("removeBSTreeNode can not find %d \n", data);
return PARAM_ERR;
}
left = node->left;
right = node->right;
parent = node->parent;
if(NULL != right){
mostsubLeft = getMostLeftNode(right);
}
/* 非根节点 */
if(NULL != parent){
/*1. 摘下node和它的子树*/
if(node->data < parent->data){
parent->left = NULL;
node->parent = NULL;
atLeft = 1;
} else {
parent->right = NULL;
node->parent = NULL;
atRight = 1;
}
/*2. 挂子树*/
/*node 是叶子节点,什么也不用做 */
if(NULL == left && NULL == right){
}
/*非叶子节点*/
/*有左子没右子*/
if(NULL != left && NULL == right){
if(1 == atLeft){
parent->left = left;
left->parent = parent;
} else if(1 == atRight) {
parent->right = left;
left->parent = parent;
}
}
/*没左子有右子*/
if(NULL == left && NULL != right){
if(1 == atLeft){
parent->left = right;
right->parent = parent;
} else if(1 == atRight) {
parent->right = right;
right->parent = parent;
}
}
/*有左子有右子, 左子挂在右子的最左边节点的左边, 右子树根节点继承原来节点位置*/
if(NULL != left && NULL != right){
mostsubLeft->left = left;
left->parent = mostsubLeft;
if(1 == atLeft){
parent->left = right;
right->parent = parent;
} else if(1 == atRight) {
parent->right = right;
right->parent = parent;
}
}
} else { /* 根节点 */
/*node 是叶子节点,什么也不用做 */
if(NULL == left && NULL == right){
root = NULL;
}
/*有左子没右子*/
if(NULL != left && NULL == right){
root = left;
}
/*没左子有右子*/
if(NULL == left && NULL != right){
root = right;
}
/*没左子有右子*/
if(NULL == left && NULL != right){
if(1 == atLeft){
parent->left = right;
right->parent = parent;
} else if(1 == atRight) {
parent->right = right;
right->parent = parent;
}
}
/*有左子有右子, 左子挂在右子的最左边节点的左边, 右子树根节点继承原来节点位置*/
if(NULL != left && NULL != right){
mostsubLeft->left = left;
left->parent = mostsubLeft;
/*更新根节点*/
root = right;
}
*proot = root;
}
free(node);
node = NULL;
return SUCCESS;
}
void testBSTree(void){
printf("\n************ testBSTree ************ \n");
st_trNode * p = NULL;
st_trNode * root = NULL;
st_trNode * mostLeft = NULL;
gBSTree = NULL;
createTree(&gBSTree);
root = gBSTree->root;
printf("insert 5\n");
p = createTreeNode(5);
insertBSTNode(&root, p);
printf("insert 3\n");
p = createTreeNode(3);
insertBSTNode(&root, p);
printf("insert 7\n");
p = createTreeNode(7);
insertBSTNode(&root, p);
printf("insert 2\n");
p = createTreeNode(2);
insertBSTNode(&root, p);
printf("insert 4\n");
p = createTreeNode(4);
insertBSTNode(&root, p);
printf("insert 6\n");
p = createTreeNode(6);
insertBSTNode(&root, p);
printf("insert 8\n");
p = createTreeNode(8);
insertBSTNode(&root, p);
printf("insert 1\n");
p = createTreeNode(1);
insertBSTNode(&root, p);
gBSTree->root = root;
dumpTree(gBSTree);
p = NULL;
p = SearchBSTreeNode(gBSTree->root, 5);
if(NULL != p){
printf("node[%p] = %d\n", p, p->data);
} else {
printf("Cannot find this node\n");
}
p = SearchBSTreeNode(gBSTree->root, 10);
if(NULL != p){
printf("node[%p] = %d\n", p, p->data);
} else {
printf("Cannot find this node\n");
}
p = SearchBSTreeNode(gBSTree->root, 8);
if(NULL != p){
printf("node[%p] = %d\n", p, p->data);
} else {
printf("Cannot find this node\n");
}
mostLeft = getMostLeftNode(gBSTree->root);
if(NULL != mostLeft){
printf("mostLeft[%p] = %d\n", mostLeft, mostLeft->data);
} else {
printf("Null Tree\n");
}
mostLeft = getMostLeftNode(gBSTree->root->right);
if(NULL != mostLeft){
printf("mostLeft[%p] = %d\n", mostLeft, mostLeft->data);
} else {
printf("Null Tree\n");
}
/*删除在最后测试*/
root = gBSTree->root;
//removeBSTreeNode(&root, 3);
//removeBSTreeNode(&root, 1);
//removeBSTreeNode(&root, 4);
//removeBSTreeNode(&root, 7);
//removeBSTreeNode(&root, 8); /*删除右子树*/
removeBSTreeNode(&root, 5); /*删除根节点*/
gBSTree->root = root;
dumpTree(gBSTree);
return;
}
代码编译
gcc main.c stack.c list.c tree.c -g -o a.exe -DDEBUG
调试输出
************ testBSTree ************
insert 5
1.1 root = 5
insert 3
1.6
1.2 left = 3, parent = 5
insert 7
1.7
1.5.1 root = 5
insert 2
1.7
1.4.2 root = 5, left = 3
1.6
1.2 left = 2, parent = 3
insert 4
1.7
1.4.2 root = 5, left = 3
1.7
1.5.1 root = 3
insert 6
1.7
1.5.2 root = 5, right = 7
1.6
1.2 left = 6, parent = 7
insert 8
1.7
1.5.2 root = 5, right = 7
1.7
1.5.1 root = 7
insert 1
1.7
1.4.2 root = 5, left = 3
1.7
1.4.2 root = 3, left = 2
1.6
1.2 left = 1, parent = 2
========= Dump Tree PreOder: 0x18ba010 ===========
5 3 2 1 4 7 6 8
===================================
========= Dump Tree PreOder UnRec: 0x18ba010 ===========
5 3 2 1 4 7 6 8
===================================
node[0x18ba030] = 5
Cannot find this node
node[0x18ba150] = 8
mostLeft[0x18ba180] = 1
mostLeft[0x18ba120] = 6
========= Dump Tree PreOder: 0x18ba010 ===========
7 6 3 2 1 4 8
===================================
========= Dump Tree PreOder UnRec: 0x18ba010 ===========
7 6 3 2 1 4 8
===================================