SeOpiamal静态树表的查找

静态树表的查找

9.1.3 静态树表的查找

上一小节对有序表的查找性能的讨论是在“等概率”的前提下进行的,即当有序表中各记录的查找概率相等时,按图9.2所示判定树描述的查找过程来进行折半查找,其性能最优。如果有序表中各记录的查找概率不等,情况又如何呢?

先看一个具体例子。假设有序表中含5个记录,并且已知各记录的查找概率不等,分别为p1=0.1,p2=0.2,p3=0.1,p4=0.4和p5=0.2。则对此有序表进行折半查找,查找成功时的平均查找长度为

5

∑PiCi = 0.1* 2+0.2* 3+0.1*1+0.4* 2+0.2* 3 = 2.3

i=1

但是,如果在查找时令给定值先和第4个记录的关键字进行比较,比较不相等时再继续在左子序列或右子序列中进行折半查找,则查找成功时的平均查找长度为

5

∑PiCi=0.1* 3+0.2* 2+0.1* 3+0.4*1+0.2* 2=1.8 i=1

这就说明,当有序表中各记录的查找概率不等时,按所示判定树进行折半查找,其性能未必是最优的。那末此时应如何进行查找呢? 换句话说,描述查找过程的判定树为何类二叉树时,其查找性能最佳?

如果只考虑查找成功的情况,则使查找性能达最佳的判定树是其带权内路径长度之和PH 值 n

PH=∑wihi (9-7)

i=1

取最小值的二叉树。其中:n 为二叉树上结点的个数(即有序表的长度) ;hi 为第i 个结点在二叉树上的层次数;结点的权wi=cpi(i=1,2,…,n) ,其中pi 为结点的查找概率,c 为某个常量。称PH 值取最小的二叉树为静态最优查找树(Static Optimal Search Tree)。由于构造静态最优查找树花费的时间代价较高,因此在此介绍一种构造近似最优查找树的有效算法。

已知一个按关键字有序的记录序列

(rl, rl+1, …, rh) (9-8)

其中 rl.key

wl, wl+1, …, wh (9-9) 现构造一棵二叉树,使这棵二叉树的带权内路径长度PH 值在所有具有同样权值的二叉树中近似为最小,称这类二叉树为次优查找树(Nearly Optimal Search Tree)。 构造次优查找树的方法是:

首先在式(9-8)所示的记录序列中取第i(l≤i ≤h) 个记录构造根结点ri ,使得 h i-1

△Pi=|∑wj-∑wj| (9-10)

j=i+1 j=l

取最小值(△Pi=Min{△Pj}),然后分别对子序列{rl,rl+1, …ri-1}和{ri+1,.., rh} 两棵次优查找树,并分别设为根结点ri 的左子树和右子树。 //构造次优查找树SeOpiamal.CPP 2010.11.29 #include

#include #include #include typedef struct treenode { struct treenode *lchild,*rchild; char data; int weight; }BiTNode,*BiTree;

void SecondOptimal(BiTree &T,char R[],int sw[],int low,int high)

{ //由有序表R[low....high]及其累积权值表sw(其中sw[0]==0)递归构造次优查找树T int i=low;

int min=fabs(sw[high]-sw[low]); //给min 赋比较基数 int dw=sw[high]+sw[low-1];

for(int j=low+1;j

min=fabs(dw-sw[j]-sw[j-1]); } }

T=(BiTree)malloc(sizeof(BiTNode)); T->data=R[i]; //生成节点

if(i==low) T->lchild=NULL; //左子树为空

else SecondOptimal(T->lchild,R,sw,low,i-1); //构造左子树 if(i==high) T->rchild=NULL; //右子树为空

else SecondOptimal(T->rchild,R,sw,i+1,high); //构造右子树 }//SecondOptimal

void pre_order(BiTree &T)//前序遍历二叉树 { if(T!=NULL)

{ coutdatalchild); pre_order(T->rchild); } }

int seach_tree(BiTree &T,char key)//查找二叉树中是否存在某元素 { if(T==NULL) return 0; else

{ if(T->data==key) return 1;

else

{ if(seach_tree(T->lchild,key)||seach_tree(T->rchild,key)) return 1; //如果左右子树有一个搜索到,就返回1 else return 0; //如果左右子树都没有搜索到,返回0 } }

}

void main()

{ BiTree root=NULL;

int low=1,high=10; char *R;

int *weight,*sw;

R=(char *)malloc(high*sizeof(char)); //分配R 数组空间 for(int i=low;i

for(i=low-1;i

weight=(int *)malloc(high*sizeof(int)); //分配权数组空间 weight[0]=0; weight[1]=1; weight[2]=1; weight[3]=2; weight[4]=5; weight[5]=3; weight[6]=4; weight[7]=4; weight[8]=3; weight[9]=5;

cout

sw=(int *)malloc(high*sizeof(int));

sw[0]=0;

for(i=low;i

SecondOptimal(root,R,sw,low,high-1);//创建次优查找二叉树 cout

cout>ch;

//查找二叉树中是否存在某元素

if(seach_tree(root,ch)==1) cout

运行程序结果如下:

构造次优查找树的点R[]:

? A B C D E F G H I 构造次优查找树的点的权值weight[]: 0 1 1 2 5 3 4 4 3 5 构造次优查找树的点累积权值sw[]: 0 1 2 4 9 12 16 20 23 28 前序遍历序列是:

F D B A C E H G I

输入要查找的元素! F yes!

例9-1 已知9个关键字的有序表及其相应权值为:

关键字 A B C D E F G H I 权值 1 1 2 5 3 4 4 3 5

则按算法9.3构造次优二叉查找树的过程中累计权SW 和△P 的值如图9.4(a )所示,构造所得次优二叉查找树如图9.4(b)所示。

(a)

(b)

图9.4 构造次优二叉查找树示图 (a)累计权值和△P 值; (b) 次优查找树

由于在构造次优查找树的过程中,没有考察单个关键字的相应权值,则有可能出现被选为根的关键字的权值比与它相邻的关键字的权值小。此时应作适当调整:选取邻近的权值较大的关键字作次优查找树的根结点。

大量的实验研究表明,次优查找树和最优查找树的查找性能之差仅为1%~2%,很少超过3%,而且构造次优查找树的算法的时间复杂度为O (nlogn),因此它是构造近似最优二叉查找树的有效算法。

静态树表的查找

9.1.3 静态树表的查找

上一小节对有序表的查找性能的讨论是在“等概率”的前提下进行的,即当有序表中各记录的查找概率相等时,按图9.2所示判定树描述的查找过程来进行折半查找,其性能最优。如果有序表中各记录的查找概率不等,情况又如何呢?

先看一个具体例子。假设有序表中含5个记录,并且已知各记录的查找概率不等,分别为p1=0.1,p2=0.2,p3=0.1,p4=0.4和p5=0.2。则对此有序表进行折半查找,查找成功时的平均查找长度为

5

∑PiCi = 0.1* 2+0.2* 3+0.1*1+0.4* 2+0.2* 3 = 2.3

i=1

但是,如果在查找时令给定值先和第4个记录的关键字进行比较,比较不相等时再继续在左子序列或右子序列中进行折半查找,则查找成功时的平均查找长度为

5

∑PiCi=0.1* 3+0.2* 2+0.1* 3+0.4*1+0.2* 2=1.8 i=1

这就说明,当有序表中各记录的查找概率不等时,按所示判定树进行折半查找,其性能未必是最优的。那末此时应如何进行查找呢? 换句话说,描述查找过程的判定树为何类二叉树时,其查找性能最佳?

如果只考虑查找成功的情况,则使查找性能达最佳的判定树是其带权内路径长度之和PH 值 n

PH=∑wihi (9-7)

i=1

取最小值的二叉树。其中:n 为二叉树上结点的个数(即有序表的长度) ;hi 为第i 个结点在二叉树上的层次数;结点的权wi=cpi(i=1,2,…,n) ,其中pi 为结点的查找概率,c 为某个常量。称PH 值取最小的二叉树为静态最优查找树(Static Optimal Search Tree)。由于构造静态最优查找树花费的时间代价较高,因此在此介绍一种构造近似最优查找树的有效算法。

已知一个按关键字有序的记录序列

(rl, rl+1, …, rh) (9-8)

其中 rl.key

wl, wl+1, …, wh (9-9) 现构造一棵二叉树,使这棵二叉树的带权内路径长度PH 值在所有具有同样权值的二叉树中近似为最小,称这类二叉树为次优查找树(Nearly Optimal Search Tree)。 构造次优查找树的方法是:

首先在式(9-8)所示的记录序列中取第i(l≤i ≤h) 个记录构造根结点ri ,使得 h i-1

△Pi=|∑wj-∑wj| (9-10)

j=i+1 j=l

取最小值(△Pi=Min{△Pj}),然后分别对子序列{rl,rl+1, …ri-1}和{ri+1,.., rh} 两棵次优查找树,并分别设为根结点ri 的左子树和右子树。 //构造次优查找树SeOpiamal.CPP 2010.11.29 #include

#include #include #include typedef struct treenode { struct treenode *lchild,*rchild; char data; int weight; }BiTNode,*BiTree;

void SecondOptimal(BiTree &T,char R[],int sw[],int low,int high)

{ //由有序表R[low....high]及其累积权值表sw(其中sw[0]==0)递归构造次优查找树T int i=low;

int min=fabs(sw[high]-sw[low]); //给min 赋比较基数 int dw=sw[high]+sw[low-1];

for(int j=low+1;j

min=fabs(dw-sw[j]-sw[j-1]); } }

T=(BiTree)malloc(sizeof(BiTNode)); T->data=R[i]; //生成节点

if(i==low) T->lchild=NULL; //左子树为空

else SecondOptimal(T->lchild,R,sw,low,i-1); //构造左子树 if(i==high) T->rchild=NULL; //右子树为空

else SecondOptimal(T->rchild,R,sw,i+1,high); //构造右子树 }//SecondOptimal

void pre_order(BiTree &T)//前序遍历二叉树 { if(T!=NULL)

{ coutdatalchild); pre_order(T->rchild); } }

int seach_tree(BiTree &T,char key)//查找二叉树中是否存在某元素 { if(T==NULL) return 0; else

{ if(T->data==key) return 1;

else

{ if(seach_tree(T->lchild,key)||seach_tree(T->rchild,key)) return 1; //如果左右子树有一个搜索到,就返回1 else return 0; //如果左右子树都没有搜索到,返回0 } }

}

void main()

{ BiTree root=NULL;

int low=1,high=10; char *R;

int *weight,*sw;

R=(char *)malloc(high*sizeof(char)); //分配R 数组空间 for(int i=low;i

for(i=low-1;i

weight=(int *)malloc(high*sizeof(int)); //分配权数组空间 weight[0]=0; weight[1]=1; weight[2]=1; weight[3]=2; weight[4]=5; weight[5]=3; weight[6]=4; weight[7]=4; weight[8]=3; weight[9]=5;

cout

sw=(int *)malloc(high*sizeof(int));

sw[0]=0;

for(i=low;i

SecondOptimal(root,R,sw,low,high-1);//创建次优查找二叉树 cout

cout>ch;

//查找二叉树中是否存在某元素

if(seach_tree(root,ch)==1) cout

运行程序结果如下:

构造次优查找树的点R[]:

? A B C D E F G H I 构造次优查找树的点的权值weight[]: 0 1 1 2 5 3 4 4 3 5 构造次优查找树的点累积权值sw[]: 0 1 2 4 9 12 16 20 23 28 前序遍历序列是:

F D B A C E H G I

输入要查找的元素! F yes!

例9-1 已知9个关键字的有序表及其相应权值为:

关键字 A B C D E F G H I 权值 1 1 2 5 3 4 4 3 5

则按算法9.3构造次优二叉查找树的过程中累计权SW 和△P 的值如图9.4(a )所示,构造所得次优二叉查找树如图9.4(b)所示。

(a)

(b)

图9.4 构造次优二叉查找树示图 (a)累计权值和△P 值; (b) 次优查找树

由于在构造次优查找树的过程中,没有考察单个关键字的相应权值,则有可能出现被选为根的关键字的权值比与它相邻的关键字的权值小。此时应作适当调整:选取邻近的权值较大的关键字作次优查找树的根结点。

大量的实验研究表明,次优查找树和最优查找树的查找性能之差仅为1%~2%,很少超过3%,而且构造次优查找树的算法的时间复杂度为O (nlogn),因此它是构造近似最优二叉查找树的有效算法。


相关文章

  • 高速铁路曲线养护办法-耿俊达
  • 高速铁路曲线养护办法 高速铁路曲线是高速铁路薄弱环节之一,加强曲线养护与维修管理,从结构到几何尺寸贯标,精益求精不断提高动车组舒适度,对行车平稳,延长曲线轨道使用寿命,具有重要意义.结合高铁250公里客专的需要,从筹备到开通,晚间养护作业的 ...查看


  • 38-域名解析操作
  • 目 录 第1章 域名解析配置.......................................................................................................... ...查看


  • 网络中路由器的应用与配置
  • 摘 要 路由器是一种连接多个网络或网段的网络设备,它能将不同网络或网段之间的数据信息进行"翻译",以使它们能够相互"读"懂对方的数据,并能够高速的选择信息传送的线路,大大提高通信速度,减轻网络系统通信 ...查看


  • 新云4伪静态TAG标签(自定义伪静态页面)
  • '-- 是否开启伪静态功能(False=否,True=是)Const IsURLRewrite = False conn.asp 开启 那么所有页面都需要伪静态 我只想伪静态tag标签页面 首先 在conn.asp增加 Const Rewr ...查看


  • 网络中路由器的应用与配置 1
  • 摘 要:利用路由器的漏洞发起攻击的事件经常发生.路由器攻击会浪费CPU周期,误导信息流量,使网络异常甚至陷于瘫痪.因此需要采取相应的安全措施来保护路由器的安全.避免口令泄露危机. 关键词:网络:路由器:漏洞:应用:配置 1 路由器的工作原理 ...查看


  • 2016年中国人民银行招聘考试计算机数据结构基础知识(二)
  • 2016年中国人民银行招聘考试计算机数据结构基础知识(二) 为了帮助考生顺利通过2016年人民银行招聘考试,融大教育•银行人为大家做出相关备考指导,更多银行招聘考试信息请关注融大网校. * 21.链栈:采用链式存储结构的栈,称为链栈. * ...查看


  • 成为电梯高手之电梯电气故障查找方法
  • 电梯电气故障查找方法 当电梯控制电路发生故障时,首先要问.看.听.闻,做到心中有数.所谓问,就是询问操作者或报告故障的人员故障发生时的现象,查询在故障发生前是否做过任何调整或更换元件的工作:所谓看,就是观察每一个零件是否正常工作,看控制电梯 ...查看


  • 电子产品的调试
  • 电子产品的调试 一. 调试的准备 (1)素质准备 对调试人员的知识能力素质准备的基本要求: 1) 明确电路调试的目的和要求达到的技术性能指标. 2) 能够掌握正确的使用方法和测试方法,熟练使用测量仪器和测试设备. 3) 掌握一定的调整和测试 ...查看


  • 软件实施 面试题(含答案)
  • 软件实施 面试题答案 ✧ 1.你熟悉的远程有哪些方法?各种方法应该怎么配置? 参考答案: (1).最简单的QQ上有,打开对话框 上边有个 "应用"图标 点击"远程协助". (2).系统自带的远程桌面服 ...查看


热门内容