1。简述:二叉寻找树是一种简单的树型数据结构的就用,ADT设计只有简单的几种操作,即
1。查找某个数值。
2。查找最小值 。
3. 查找某个值.
4. 删除某一值。
这个ADT实现还可以用于排序:当你总是查找最小值然后删除最小值时,你将得到一个从小到大的序列;反之,如果查找大值删除之,则得到一个逆序序列。
2.实现:
设计树节点为:
struct ST_TreeNode;
typedef ST_TreeNode * ST_Tree;
struct ST_TreeNode
{
Element e;
ST_Tree *left;
ST_Tree * right;
};
设left存储左子树,存储较小值,right存储右子树且存储较大值,则查找可以递归的从根节点一直往下查获,遇到较大的值就往其左子树查找,遇到较小值则往其右子树查找,直到找到相符的值或到达最底部叶子节占;插入是类似的过程,不同的是到达叶子节点时创建一个新的节点“接上”。
二叉查找树的难点在于删除操作,当在树中查找一个符合的节点,不能单纯的直接把它删除。通常的处理是:如果相符的节点左右子树有空的情况:假如左子树为空则让其右子树”接上“其父节点,否则让其左子树”接上“其父节点。
如果左右子树都不空,则令其节点元素值等于其右子树的最小节点的值,然后再递归的删除那个最小节点。
图示:
3。算法分析。
一棵树所有节点的深度称为内部路径长度,我们设内部路径长度为 D(n)则,
对于根的左右子树,有n-1个节点,所以路径长度之各应该是左右之树的路径长度之和加n-1,故有
D(n)=D(i)+D(n-i-1)+n-1
解些递推式得到 D(n)=O(nlogn)
所以所有节点的期望深度为nlogn/n=logn,于是对一个节点的插入/删除/查找时间复杂度均是O(logn)
4.源代码及测试代码。
/**ADT头文件ST_tree.h ***/
/**********************************
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*last update:Fri Jan 11 01:26:57 EST 2008
*description:
*The search assume that the left node store smaller element
* and right,bigger one;
*usage:take attention for ST_Insert(..),ST_Delete(..),
*for good habby,you should user it like
* t=ST_Delete(..);
* as the root may be change.
*
*/
#ifndef ___ST_TREE___
#define ___ST_TREE___
#include<stdlib.h>
#include<stdio.h>
#ifndef ___ST_TREE_ELEMENT___
#define ___ST_TREE_ELEMENT___
typedef int ST_Element;
#endif
struct ST_TreeNode ;
typedef struct ST_TreeNode * ST_Tree;
typedef struct ST_TreeNode * ST_Position ;
/*make the tree empty,it's equivalent to function like ST_DisposeTree*/
ST_Position ST_MakeEmpty(ST_Tree t); /*find the minimum element*/
ST_Position ST_FindMin(ST_Tree t);
/*find the maximum element*/
ST_Position ST_FindMax(ST_Tree t);
/*insert an element*/
ST_Tree ST_Insert(ST_Element e,ST_Tree t);
/*delete an element*/
ST_Tree ST_Delete(ST_Element e,ST_Tree t);
/*find an element*/
ST_Position ST_Find(ST_Element e,ST_Tree t);
/*Get a value of a node*/
ST_Element ST_Retrieve(ST_Position p);
#endif
/**********************************
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*last update:Fri Jan 11 01:26:57 EST 2008
*description:
*
*
*
*/
#include "ST_tree.h"
struct ST_TreeNode
{
ST_Element e;
ST_Tree left;
ST_Tree right;
};
static ST_Tree ST_DeleteMin(ST_Tree t)
{
if(t->left)t=t->left;
else
{
free(t);
return NULL;
}
}
/****************************************/
/*make the tree empty,it's equivalent to function like ST_DisposeTree*/
ST_Position ST_MakeEmpty(ST_Tree t)
{
if(t)
{
ST_MakeEmpty(t->left);
ST_MakeEmpty(t->right);
free(t);
}
return NULL;
}
/*find the minimum element*/
ST_Position ST_FindMin(ST_Tree t)
{
if(t)
while(t->left)t=t->left;
return (ST_Position)t;
}
/*find the maximum element*/
ST_Position ST_FindMax(ST_Tree t)
{
if(t)
while(t->right)t=t->right;
return (ST_Position)t;
}
/*insert an element*/
ST_Tree ST_Insert(ST_Element e,ST_Tree t)
{
/*insert it*/
if(t==NULL)
{
t=(struct ST_TreeNode*)malloc(sizeof(struct ST_TreeNode));
t->e=e;
t->left=t->right=NULL;
}
else
if(e>t->e)t->right=ST_Insert(e,t->right);
else
if(e<t->e)t->left=ST_Insert(e,t->left);
return t;
}
/**********************
*delete an element
*to delete it :
*first, find out the element position p
*second,swap with the minimum element of p's right tree ,assume it's p2
*next ,delete p2 in cycle
*/
ST_Tree ST_Delete(ST_Element e,ST_Tree t)
{
ST_Position p;
if(t)
{
if(e>t->e)t->right=ST_Delete(e,t->right);
else if(e<t->e) t->left=ST_Delete(e,t->left);
/*find it*/
else if(t->left&&t->right)
{
p=ST_FindMin(t->right);
t->e=p->e;
t->right=ST_DeleteMin(t->right);
}
else
{
p=t;
if(t->left==NULL)t=t->right;
else t=t->left;
free(p);
}
}
return t;
}
/*find an element*/
ST_Position ST_Find(ST_Element e,ST_Tree t)
{
if(t)
{
if(e>t->e)return ST_Find(e,t->right);
else if(e<t->e)return ST_Find(e,t->left);
else return (ST_Position)t;
}
else return NULL;
}
/*Get a value of a node*/
ST_Element ST_Retrieve(ST_Position p)
{
return p->e;
}
/***测试文件大部分内容自动生成,详细请留意本系统前面的文章**/
/**测试文件 testST_tree.c**/
/*///
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*create date:Fri Jan 11 03:45:18 EST 2008
*last update:Fri Jan 11 03:45:18 EST 2008
*description:
*
*
*//
#include "menu_c.h"
#include<stdio.h>
#include<stdlib.h>
#include"ST_tree.h"
int main()
{
int n;
ST_Tree t;
ST_Position p;
t=ST_MakeEmpty(NULL);
while(SELECT())
{
switch (SELECTION)
{
/*Insert a integer.*/
case '1':
printf("integer:>");
scanf("%d",&n);
t=ST_Insert(n,t);
break;
/*Delete an integer from the tree.*/
case '2':
printf("integer to delete:>");
scanf("%d",&n);
if(!ST_Find(n,t))printf("sorry,no integer match");
else {
t=ST_Delete(n,t);
printf("deletion done");
}
break;
/*Sort and show from small to big(will delete the tree)*/
case '3':
while(p=ST_FindMin(t))
{
printf("%d " ,ST_Retrieve(p),t);
t= ST_Delete(ST_Retrieve(p),t);
}
break;
/*Sort and show from big to small(will delete the tree)*/
case '4':
while(p=ST_FindMax(t))
{
printf("%d " ,ST_Retrieve(p));
t=ST_Delete(ST_Retrieve(p),t);
}
break;
/*show the max*/
case '5':
if(!(p=ST_FindMax(t)))printf("sorry,the tree is NULL");
else
printf("%d",ST_Retrieve(p));
break;
/*show the min*/
case '6':
if(!(p=ST_FindMin(t)))printf("sorry ,the tree is NULL");
else
printf("%d",ST_Retrieve(p));
break;
case '9':
system("less ../ST_tree.h");
break;
default:break;
}
}
return 0;
}
/**菜单menu_c.h**/
/*///
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*create date:Fri Jan 11 03:45:18 EST 2008
*last update:Fri Jan 11 03:45:18 EST 2008
*description:
*
*
*/
#include <stdio.h>
#ifndef __MENU____
#define __MENU____
#define SELECT() ((___sel=___select())!='0')
#define SELECTION ___sel
char ___sel;
char ___select();
/*
define the menu:
*/
#endif
/**菜单文件 menu_c.c**/
/*///
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*create date:Fri Jan 11 03:45:18 EST 2008
*last update:Fri Jan 11 03:45:18 EST 2008
*description:
*
*
*/
#include "menu_c.h"
char *___menu[]={
"1.Insert a integer.",
"2.Delete an integer from the tree.",
"3.Sort and show from small to big(will delete the tree)",
"4.Sort and show from big to small(will delete the tree)",
"5.show the max",
"6.show the min", "9.Print the file ST_tree.h",
"0.EXIT",
NULL
};
void ___showMenu()
{
printf("please select:/n");
char **p=___menu;
while(*p)printf("%s/n",*p++);
printf(":>");
}
char ___select()
{
char c;
___showMenu();
while((c=getchar())=='/n');
return c;
}
1。查找某个数值。
2。查找最小值 。
3. 查找某个值.
4. 删除某一值。
这个ADT实现还可以用于排序:当你总是查找最小值然后删除最小值时,你将得到一个从小到大的序列;反之,如果查找大值删除之,则得到一个逆序序列。
2.实现:
设计树节点为:
struct ST_TreeNode;
typedef ST_TreeNode * ST_Tree;
struct ST_TreeNode
{
Element e;
ST_Tree *left;
ST_Tree * right;
};
设left存储左子树,存储较小值,right存储右子树且存储较大值,则查找可以递归的从根节点一直往下查获,遇到较大的值就往其左子树查找,遇到较小值则往其右子树查找,直到找到相符的值或到达最底部叶子节占;插入是类似的过程,不同的是到达叶子节点时创建一个新的节点“接上”。
二叉查找树的难点在于删除操作,当在树中查找一个符合的节点,不能单纯的直接把它删除。通常的处理是:如果相符的节点左右子树有空的情况:假如左子树为空则让其右子树”接上“其父节点,否则让其左子树”接上“其父节点。
如果左右子树都不空,则令其节点元素值等于其右子树的最小节点的值,然后再递归的删除那个最小节点。
图示:
3。算法分析。
一棵树所有节点的深度称为内部路径长度,我们设内部路径长度为 D(n)则,
对于根的左右子树,有n-1个节点,所以路径长度之各应该是左右之树的路径长度之和加n-1,故有
D(n)=D(i)+D(n-i-1)+n-1
解些递推式得到 D(n)=O(nlogn)
所以所有节点的期望深度为nlogn/n=logn,于是对一个节点的插入/删除/查找时间复杂度均是O(logn)
4.源代码及测试代码。
/**ADT头文件ST_tree.h ***/
/**********************************
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*last update:Fri Jan 11 01:26:57 EST 2008
*description:
*The search assume that the left node store smaller element
* and right,bigger one;
*usage:take attention for ST_Insert(..),ST_Delete(..),
*for good habby,you should user it like
* t=ST_Delete(..);
* as the root may be change.
*
*/
#ifndef ___ST_TREE___
#define ___ST_TREE___
#include<stdlib.h>
#include<stdio.h>
#ifndef ___ST_TREE_ELEMENT___
#define ___ST_TREE_ELEMENT___
typedef int ST_Element;
#endif
struct ST_TreeNode ;
typedef struct ST_TreeNode * ST_Tree;
typedef struct ST_TreeNode * ST_Position ;
/*make the tree empty,it's equivalent to function like ST_DisposeTree*/
ST_Position ST_MakeEmpty(ST_Tree t); /*find the minimum element*/
ST_Position ST_FindMin(ST_Tree t);
/*find the maximum element*/
ST_Position ST_FindMax(ST_Tree t);
/*insert an element*/
ST_Tree ST_Insert(ST_Element e,ST_Tree t);
/*delete an element*/
ST_Tree ST_Delete(ST_Element e,ST_Tree t);
/*find an element*/
ST_Position ST_Find(ST_Element e,ST_Tree t);
/*Get a value of a node*/
ST_Element ST_Retrieve(ST_Position p);
#endif
/**********************************
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*last update:Fri Jan 11 01:26:57 EST 2008
*description:
*
*
*
*/
#include "ST_tree.h"
struct ST_TreeNode
{
ST_Element e;
ST_Tree left;
ST_Tree right;
};
static ST_Tree ST_DeleteMin(ST_Tree t)
{
if(t->left)t=t->left;
else
{
free(t);
return NULL;
}
}
/****************************************/
/*make the tree empty,it's equivalent to function like ST_DisposeTree*/
ST_Position ST_MakeEmpty(ST_Tree t)
{
if(t)
{
ST_MakeEmpty(t->left);
ST_MakeEmpty(t->right);
free(t);
}
return NULL;
}
/*find the minimum element*/
ST_Position ST_FindMin(ST_Tree t)
{
if(t)
while(t->left)t=t->left;
return (ST_Position)t;
}
/*find the maximum element*/
ST_Position ST_FindMax(ST_Tree t)
{
if(t)
while(t->right)t=t->right;
return (ST_Position)t;
}
/*insert an element*/
ST_Tree ST_Insert(ST_Element e,ST_Tree t)
{
/*insert it*/
if(t==NULL)
{
t=(struct ST_TreeNode*)malloc(sizeof(struct ST_TreeNode));
t->e=e;
t->left=t->right=NULL;
}
else
if(e>t->e)t->right=ST_Insert(e,t->right);
else
if(e<t->e)t->left=ST_Insert(e,t->left);
return t;
}
/**********************
*delete an element
*to delete it :
*first, find out the element position p
*second,swap with the minimum element of p's right tree ,assume it's p2
*next ,delete p2 in cycle
*/
ST_Tree ST_Delete(ST_Element e,ST_Tree t)
{
ST_Position p;
if(t)
{
if(e>t->e)t->right=ST_Delete(e,t->right);
else if(e<t->e) t->left=ST_Delete(e,t->left);
/*find it*/
else if(t->left&&t->right)
{
p=ST_FindMin(t->right);
t->e=p->e;
t->right=ST_DeleteMin(t->right);
}
else
{
p=t;
if(t->left==NULL)t=t->right;
else t=t->left;
free(p);
}
}
return t;
}
/*find an element*/
ST_Position ST_Find(ST_Element e,ST_Tree t)
{
if(t)
{
if(e>t->e)return ST_Find(e,t->right);
else if(e<t->e)return ST_Find(e,t->left);
else return (ST_Position)t;
}
else return NULL;
}
/*Get a value of a node*/
ST_Element ST_Retrieve(ST_Position p)
{
return p->e;
}
/***测试文件大部分内容自动生成,详细请留意本系统前面的文章**/
/**测试文件 testST_tree.c**/
/*///
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*create date:Fri Jan 11 03:45:18 EST 2008
*last update:Fri Jan 11 03:45:18 EST 2008
*description:
*
*
*//
#include "menu_c.h"
#include<stdio.h>
#include<stdlib.h>
#include"ST_tree.h"
int main()
{
int n;
ST_Tree t;
ST_Position p;
t=ST_MakeEmpty(NULL);
while(SELECT())
{
switch (SELECTION)
{
/*Insert a integer.*/
case '1':
printf("integer:>");
scanf("%d",&n);
t=ST_Insert(n,t);
break;
/*Delete an integer from the tree.*/
case '2':
printf("integer to delete:>");
scanf("%d",&n);
if(!ST_Find(n,t))printf("sorry,no integer match");
else {
t=ST_Delete(n,t);
printf("deletion done");
}
break;
/*Sort and show from small to big(will delete the tree)*/
case '3':
while(p=ST_FindMin(t))
{
printf("%d " ,ST_Retrieve(p),t);
t= ST_Delete(ST_Retrieve(p),t);
}
break;
/*Sort and show from big to small(will delete the tree)*/
case '4':
while(p=ST_FindMax(t))
{
printf("%d " ,ST_Retrieve(p));
t=ST_Delete(ST_Retrieve(p),t);
}
break;
/*show the max*/
case '5':
if(!(p=ST_FindMax(t)))printf("sorry,the tree is NULL");
else
printf("%d",ST_Retrieve(p));
break;
/*show the min*/
case '6':
if(!(p=ST_FindMin(t)))printf("sorry ,the tree is NULL");
else
printf("%d",ST_Retrieve(p));
break;
case '9':
system("less ../ST_tree.h");
break;
default:break;
}
}
return 0;
}
/**菜单menu_c.h**/
/*///
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*create date:Fri Jan 11 03:45:18 EST 2008
*last update:Fri Jan 11 03:45:18 EST 2008
*description:
*
*
*/
#include <stdio.h>
#ifndef __MENU____
#define __MENU____
#define SELECT() ((___sel=___select())!='0')
#define SELECTION ___sel
char ___sel;
char ___select();
/*
define the menu:
*/
#endif
/**菜单文件 menu_c.c**/
/*///
*author:Felix
*address me:qq 349871604 e-mail:lzqziliao2004@163.com
*create date:Fri Jan 11 03:45:18 EST 2008
*last update:Fri Jan 11 03:45:18 EST 2008
*description:
*
*
*/
#include "menu_c.h"
char *___menu[]={
"1.Insert a integer.",
"2.Delete an integer from the tree.",
"3.Sort and show from small to big(will delete the tree)",
"4.Sort and show from big to small(will delete the tree)",
"5.show the max",
"6.show the min", "9.Print the file ST_tree.h",
"0.EXIT",
NULL
};
void ___showMenu()
{
printf("please select:/n");
char **p=___menu;
while(*p)printf("%s/n",*p++);
printf(":>");
}
char ___select()
{
char c;
___showMenu();
while((c=getchar())=='/n');
return c;
}