查找->静态查找表->次优查找(静态树表)
文字描算
之前分析顺序查找和折半查找的算法性能都是在“等概率”的前提下进行的,但是如果有序表中各记录的查找概率不等呢?换句话说,概率不等的情况下,描述查找过程的判定树为何类二叉树,其查找性能最佳?
如果只考虑查找成功的情况,则使查找性能达最佳的判定树是其带权内路径长度之和PH值取最小的二叉树。

其中n为二叉树上结点的个数(即有序表的长度);hi为第i个结点在二叉树上的层次数;结点的权wi=cpi(i=1,2,…,n),其中pi为结点的查找概率,c为某个常量。称PH值取最小的二叉树为静态最优查找树。由于构造静态最优查找树代价较高,在此介绍一种构造近似最优查找树的有效算法。该算法的过程描述如下:
已知一个按关键字有序的记录序列
,其中
, 与每个记录相应的权值为

首先在记录序列中取第i(l<=i && i<=h)个记录构造根结点
,使得
取最小值,然后分别对子序列
和
构造两棵次优查找树,并分别设为根结点
的左子树和右子树。

示意图

算法分析
从次优查找树的结构特定可知,其查找过程类似于折半查找。查找过程和二叉排序树算法类型,待二叉排序树会讲。由于查找过程是走了一条从根到待查记录所在节点(或叶子结点)的一条路径,进行过比较的关键字个数不超过树的深度,因此,次优查找树的平均查找长度和logn成正比。可见,在记录的查找概率不等时,可用次优查找树表示静态查找表,故又称为静态树表。
另外,大量实验表明,次优查找树和最优查找树的查找性能之差仅仅为1%-2%,很少查过3%,而且构造次优查找树的算法的时间复杂度为nlogn。
代码实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define DEBUG
#define EQ(a, b) ((a)==(b))
#define LT(a, b) ((a)< (b))
#define LQ(a, b) ((a)<=(b))
#define MAX_SIZE 50 typedef char KeyType;
//数据元素类型
typedef struct{
//关键字
KeyType key;
//权值
int weight;
}ElemType;
//静态查找表
typedef struct{
//数据元素存储空间基址,0号单元留空
ElemType *elem;
//表长度
int length;
}SSTable;
//二叉链表, 次优查找树采用二叉链表的存储结构
typedef struct{
ElemType data;
struct BiTNode *lchild;
struct BiTNode *rchild;
}BiTNode, *BiTree; //由有序表R[low,...,high]及累计权值表sw(其中sw[0]==0)递归构造次优查找树T
BiTNode* SecondOptimal(ElemType R[], int sw[], int low, int high)
{
int i = low, j = ;
int min = abs(sw[high]-sw[low]);
int dw = sw[high]+sw[low-];
//选择最小的<>Pi值
for(j=low+; j<=high; ++j){
if(abs(dw-sw[j]-sw[j-])<min){
i = j;
min = abs(dw-sw[j]-sw[j-]);
}
}
#ifdef DEBUG
printf("i=%d, low=%d, high=%d\n", i, low, high);
#endif
//生成结点
BiTNode* T = (BiTNode*)malloc(sizeof(BiTNode));
T->data = R[i];
T->lchild = T->rchild = NULL;
if(i==low){
//左子树空
T->lchild = NULL;
}else{
//构造左子树
T->lchild = SecondOptimal(R, sw, low, i-);
}
if(i==high){
//右子树空
T->rchild = NULL;
}else{
//构造右子树
T->rchild = SecondOptimal(R, sw, i+, high);
}
return T;
} //按照由有序表ST中各数据元素的weight域求累计权值表sw
void FindSW(int sw[], SSTable ST)
{
int i = ;
sw[] = ;
for(i=; i<=ST.length; i++){
sw[i] = sw[i-]+ST.elem[i].weight;
}
#ifdef DEBUG
printf("SW : ");
for(i=; i<=ST.length; i++){
printf("[%d]=%-3d ", i, sw[i]);
}
printf("\n");
#endif
return ;
} //由有序表ST构造一棵次优查找树. ST的数据元素含有权域weight
BiTree CreateSOSTree(SSTable ST)
{
if(ST.length == )
return NULL;
else{
int sw[MAX_SIZE+] = {};
//按照由有序表ST中各数据元素的weight域求累计权值表sw
FindSW(sw, ST);
//由有序表ST.elem[low,...,high]及累计权值表sw(其中sw[0]==0)递归构造次优查找树并返回
return (BiTree)SecondOptimal(ST.elem, sw, , ST.length);
}
} //顺序打印有序表ST中的数据元素。
void print(SSTable SS){
printf("data: ");
int i = ;
for(i=; i<=SS.length; i++){
printf("[%d]=%c,%d ", i, SS.elem[i].key, SS.elem[i].weight);
}
printf("\n");
} int PreOrderTraverse(BiTree T); //先序遍历
int InOrderTraverse(BiTree T); //中序遍历
int PostOrderTraverse(BiTree T);//后序遍历 int main(int argc, char *argv[])
{ KeyType key;
int weight;
int i = ;
char tmp[] = {};
#ifdef DEBUG
ElemType arr[MAX_SIZE+] = {{'',},{'A',}, {'B',}, {'C',}, {'D',}, {'E',},{'F',},{'G',},{'H',},{'I',},};
i = ;
#else
ElemType arr[MAX_SIZE+];
while(){
printf("输入 关键字,权值('0,0'是结束):");
memset(tmp, , sizeof(tmp));
scanf("%s", tmp);
sscanf(tmp, "%c,%d", &key, &weight);
if(key == '' && weight ==){
break;
}else{
arr[i].key = key;
arr[i].weight = weight;
i+=;
}
}
#endif
SSTable SS;
SS.elem = arr;
SS.length = i-;
#ifdef DEBUG
print(SS);
#endif
BiTree T = CreateSOSTree(SS);
printf("先序遍历:");
PreOrderTraverse(T);
printf("\n"); printf("中序遍历:");
InOrderTraverse(T);
printf("\n"); printf("后序遍历:");
PostOrderTraverse(T);
printf("\n");
return ;
} int PreOrderTraverse(BiTree T){
if(T){
printf("%c,%d ", ((BiTNode*)T)->data.key, ((BiTNode*)T)->data.weight);
PreOrderTraverse((BiTree)T->lchild);
PreOrderTraverse((BiTree)T->rchild);
}
return ;
} int InOrderTraverse(BiTree T){
if(T){
InOrderTraverse((BiTree)T->lchild);
printf("%c,%d ", ((BiTNode*)T)->data.key, ((BiTNode*)T)->data.weight);
InOrderTraverse((BiTree)T->rchild);
}
return ;
} int PostOrderTraverse(BiTree T){
if(T){
PostOrderTraverse((BiTree)T->lchild);
PostOrderTraverse((BiTree)T->rchild);
printf("%c,%d ", ((BiTNode*)T)->data.key, ((BiTNode*)T)->data.weight);
}
return ;
}
次优查找(静态树表)
运行

查找->静态查找表->次优查找(静态树表)的更多相关文章
- 查找->静态查找表->折半查找(有序表)
文字描述 以有序表表示静态查找表时,可用折半查找算法查找指定元素. 折半查找过程是以处于区间中间位置记录的关键字和给定值比较,若相等,则查找成功,若不等,则缩小范围,直至新的区间中间位置记录的关键字等 ...
- 查找->静态查找表->顺序查找(顺序表)
文字描述 顺序查找的查找过程为:从表中最后一个记录开始,逐个进行记录的关键字和给定值的比较,若某个记录的关键字和给定值比较相等,则查找成功,找到所查记录:反之,若直至第一个记录,其关键字和给定值比较都 ...
- 查找->静态查找表->分块查找(索引顺序表)
文字描述 分块查找又称为索引顺序查找,是顺序查找的一种改进方法.在此查找算法中,除表本身外, 还需要建立一个”索引表”.索引表中包括两项内容:关键字项(其值为该字表内的最大关键字)和指针项(指示该子表 ...
- Python 树表查找_千树万树梨花开,忽如一夜春风来(二叉排序树、平衡二叉树)
什么是树表查询? 借助具有特殊性质的树数据结构进行关键字查找. 本文所涉及到的特殊结构性质的树包括: 二叉排序树. 平衡二叉树. 使用上述树结构存储数据时,因其本身对结点之间的关系以及顺序有特殊要求, ...
- 【ZZ】详解哈希表的查找
详解哈希表的查找 https://mp.weixin.qq.com/s/j2j9gS62L-mmOH4p89OTKQ 详解哈希表的查找 2018-03-01 算法与数据结构 来自:静默虚空 http: ...
- 【知识强化】第六章 查找 6.4 散列(Hash)表
本节课我们来学习一种新的查找方式叫做散列查找.什么是散列查找呢?在学习散列查找之前,一定要介绍一个基本概念就是散列表.那么学习散列表之前我们先来回忆一下之前所学习过的所有查找方式,那么无论是顺序查找还 ...
- Excel中如何在两个工作表中查找重复数据
有时我们可能会在两种工作表中查找重复记录,当数据记录很多时,就必须通过简单的方法来实现.下面小编就与大家一起分享一下查看重复记录数据的方法,希望对大家有所帮助. 方法/步骤 为了讲解的需要,小编特 ...
- 在雇员表中查找第二高的工资SQL语句助记
"在雇员表中查找第二高的工资的员工记录"SQL语句怎么写 这个查询首先查找最高工资,然后将它从列表中排除.再查找最高工资. 非常明显,第二次返回的是 ...
- Excel-VLOOKUP函数跨表匹配查找①
问题场景 对表中的员工进行测评总结,从所有员工考核明细表中匹配这些参与测评的员工的得分和相关信息: 场景一 从所有员工明细表中匹配需要参与测评的员工相关信息. 建了两个sheet页,考核员工表和全员考 ...
随机推荐
- Node入门教程(11)第九章:Node 的网络模块
net网络模块 net模块是node对TCP或者IPC开发的封装,包括了客户端和服务器端相关API.对于阅读本文,请您有一定的网络编程的基础.您需要已经了解了: ip协议,会配置ip地址 了解dns解 ...
- SoapUI5.0创建WebService接口模拟服务端(转)
转载自:https://blog.csdn.net/a19881029/article/details/26348627 使用SoapUI创建WebService接口模拟服务端需要接口描述文件 Mat ...
- yum只下载软件不安装的两种方法
1 通过yum自带一个工具:yumdownloader rpm -qa |grep yum-utils yum -y install yum-utils* rpm -ql yum-utils 安装好后 ...
- Brainfuck解析器(Python)
global cs global ip global ss #global sp global ds global bp global tab global out cs='++++++++++[&g ...
- 关于ECMP 等价路由
1.ECMP简介 Equal-CostMultipathRouting,等价多路径.即存在多条到达同一个目的地址的相同开销的路径.当设备支持等价路由时,发往该目的 IP 或者目的网段的三层转发流量就可 ...
- Go语言_iota用法
一.介绍 iota,特殊常量,可以认为是一个可以被编译器修改的常量. 在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1. io ...
- Redhat6.5——解决yum功能不能正常使用
以前或多或少接触过linux服务器,由于是服务器上的,很多东西也没去玩过.要想多研究,还是得自己弄一个linux系统.由于正常工作,还是接触windows更多,双系统显然没有那么方便,所以决定弄个虚拟 ...
- .net core 开发接口前端调用时提示错误 405
解决方法: 在StartUp.cs文件中Configure(IApplicationBuilder app, IHostingEnvironment env)方法中添加如下代码: //跨域 app.U ...
- android 手机 多分辨率适配
近来在做android屏幕适配这方面的工作, 今天总算有点眉目. 小记一下 基础知识就不科普了, 网上一大堆. 作为一个刚接触这方面人, 最先进入我脑子的, 是从小到大的各种屏, 小到手表, 大到街 ...
- DevExpress MemoEdit定位到末尾
1: /// <summary> 2: /// 追加文本到MemoEdit中 3: /// </summary> 4: /// <param name="mem ...