算法之路——二叉查找树

  二叉查找树是很简单的数据结构,不过却很有用。因为它是篇要写的红黑树的基础。所以还是简单的谈谈,并且把实现代码贴一下。

  二叉排序树(Binary Sort Tree)又称二叉查找树。 它或者是一棵空树;或者是具有下列性质的二叉树: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树。

  具体的实现的算法就不多说了,直接贴代码:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define MAXSIZE 1000
typedef int ElemType;
//二叉搜索树的节点
typedef struct BSNode
{
ElemType data;
struct BSNode * p;
struct BSNode * left;
struct BSNode * right;
}BSNode, * PBSNode;
//二叉搜索树
typedef struct BSTree
{
PBSNode root;
}BSTree,* PBSTree;

int createBSTree (PBSTree tree, ElemType d[], int n);
PBSNode deleteBSTree (PBSTree tree, PBSNode t);
int inOrderWalk (PBSNode p);
PBSNode insertBSTree (PBSTree tree, ElemType d);
int isEmpty (PBSTree tree);
PBSNode maximum (PBSNode t);
PBSNode minimum (PBSNode t);
PBSNode next (PBSNode t);
PBSNode precursor (PBSNode t);
PBSNode search (PBSNode t, ElemType d);
int walkNext (PBSTree tree);
int main ()
{
ElemType d[MAXSIZE];
int i;
int n;
BSTree tree;
PBSNode result; //search的结果

tree.root = NULL; //初始化,这步是必要的。变量的出事值是不确定的。
srand(time(NULL));

puts("请输入数据的个数:");
scanf("%d",&n);
printf("随机生成的%d个数据是:\n",n);
for (i = 0; i < n; i++)
{
d[i] = rand()%1000;
printf("%d ",d[i]);
}
puts("");
puts("建树开始");
createBSTree(&tree, d, n);

puts("树的内容为:");
walkNext(&tree); //测试遍历功能
putchar('\n');

//测试后继和前驱功能
if (result = next(tree.root))
printf("数据%d的后继是%d\n",tree.root->data,result->data);
else
printf("数据%d没有后继\n",tree.root->data);

if (result = precursor(tree.root))
printf("数据%d的前驱是%d\n",tree.root->data,result->data);
else
printf("数据%d没有前驱\n",tree.root->data);

//测试查询
result = search (tree.root, d[1]);
if (result != NULL)
printf("找到数据%d\n",result->data);
else
printf("没有这个数据!\n");

result = deleteBSTree (&tree, tree.root); //测试删除
if (result != NULL)
{
printf("删除节点%d后,树是:\n",result->data);
free(result);
}
else
puts("没有删除节点,因为要删除的节点不存在");
walkNext(&tree);
puts("");
return 0;
}


PBSNode insertBSTree (PBSTree tree, ElemType d)
{//插入元素
//!!!记得插入的元素的初始化,p指向为父母节点,left和right复制为NULL。
PBSNode t = NULL;
PBSNode p = NULL;
int flag = 0; //用来表示插入在左边的树还是右边的树
t = tree->root;

if (tree->root == NULL)
{
tree->root = (PBSNode)malloc(sizeof(BSNode));
tree->root->data = d;
tree->root->p = tree->root->left =tree->root->right = NULL;

return tree->root;
}

while (t != NULL)
{
p = t;
if (d < t->data) //小于
{
flag = 0;
t = t->left;
}
else
{
if (d > t->data) //大于
{
flag = 1;
t = t->right;
}
else //等于,这里用随机化的方法,插入与t的data相等的元素。用flag表示,如果flag == 0 插在left,如果flag == 1插入right
{
if ( (flag=rand()%2) == 0)
t = t->left;
else
t = t->right;
}
}
}

t = (PBSNode)malloc(sizeof(BSNode));
t->data = d;
t->p = p;
t->left = t->right = NULL;

if (!flag)
p->left = t;
else
p->right = t;

return t;
}//insertBSTree

PBSNode next (PBSNode t)
{//给出t的后继的节点。如果没有后继,就返回NULL
PBSNode p; //指示父节点
if (t->right == NULL)
{
p = t->p;
while (p !=NULL && p->right == t)
{
t = p;
p = t->p;
}
return p; //如果是最后一个元素,p的值为NULL
}
else
return minimum(t->right);
}//next

PBSNode precursor (PBSNode t)
{//返回节点t前驱,如果没有前驱,就返回NULL
PBSNode p;
if (t->left == NULL)
{
p = t->p;
while (p != NULL && p->left == t)
{
t = p;
p = t->p;
}
return p;
}
else
return maximum(t->left);
}//precusor


PBSNode deleteBSTree (PBSTree tree, PBSNode t)
{//删除数据。要求给处数据节点的指针
PBSNode c = NULL; //c指向要取代被删除节点的子节点
PBSNode d = NULL;
ElemType tmp;
if (t == NULL)
return NULL;

//d指向真正要删除的元素的下标。如果t的left和right都有值,则转化为删除t的后继节点,并把后继节点的内容复制给t指向的节点。
//而其他情况则直接删除t指向的节点
if (t->left != NULL && t->right != NULL)
{
d = next(t);
//因为实际操作要删除的是d指向的节点,所以先交换data
tmp = d->data;
d->data = t->data;
t->data = tmp;
}
else
d = t;

//确定c的指向
if (d->left == NULL)
c = d->right;
else
c = d->left;

//将c的父亲指针设为d的父亲指针
if (c != NULL) //c有可能是空的指针
c->p = d->p;
if (d->p != NULL)
{
if (d->p->left == d)
d->p->left = c;
else
d->p->right = c;
}
else
tree->root = c;

return d;
}
int createBSTree (PBSTree tree, ElemType d[], int n)
{//用元素的插入建树
int index = -1;
int tmp = -1;

srand(time(NULL));

while (n--)
{
index =(int) rand()%(n+1);//此时共有n+1个数据
tmp = d[index];
d[index] = d[n];
d[n] = tmp;
insertBSTree(tree, d[n]);
printf("插入%d\t",d[n]);
}
puts("");
return 0;
}//createBSTree

int inOrderWalk (PBSNode p)
{//中序遍历数组
if (p == NULL)
return 0;
inOrderWalk (p->left);
printf("%d ",p->data);
inOrderWalk (p->right);
return 0;
}
PBSNode search (PBSNode t, ElemType d)
{//在节点t和t的子树中查找d,找到了返回树中该节点的指针
while (t != NULL &&t->data !=d)
{
if (d < t->data)
t = t->left;
else
t = t->right;
}
return t;
}
PBSNode minimum (PBSNode t)
{//返回最小值,如果t是NULL返回NULL

if (t == NULL)
return NULL;
while (t->left != NULL)
t = t->left;
return t;
}//minimum

PBSNode maximum (PBSNode t)
{//返回最大值,如果t是NULL返回NULL
if (t == NULL)
return NULL;
while (t->right != NULL)
t = t->right;
return t;
}//maximum


int isEmpty (PBSTree tree)
{//检查树是否为空
return tree->root == NULL;
}//isEmpty

int walkNext (PBSTree tree)
{//遍历二叉搜索树。先找到最小的元素,再通过用next()求后继来遍历树
PBSNode t;
t = minimum(tree->root);
while (t != NULL)
{
printf("%d\t",t->data);
t = next(t);
}
return 0;
}//walkNext



原文地址:https://www.cnblogs.com/svking/p/BSTree.html