查找->静态查找表->次优查找(静态树表)
文字描算
之前分析顺序查找和折半查找的算法性能都是在“等概率”的前提下进行的,但是如果有序表中各记录的查找概率不等呢?换句话说,概率不等的情况下,描述查找过程的判定树为何类二叉树,其查找性能最佳?
如果只考虑查找成功的情况,则使查找性能达最佳的判定树是其带权内路径长度之和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页,考核员工表和全员考 ...
随机推荐
- 【30集iCore3_ADP出厂源代码(ARM部分)讲解视频】30-11层驱动之FSMC
视频简介:该视频介绍iCore3应用开发平台中FSMC通信的配置方法及ARM与FPGA通信的方法. 源视频包下载地址:链接:http://pan.baidu.com/s/1slbHOCH 密码:n06 ...
- c++ 一个h文件里面定义一个主类,然后定义多个子类
最近遇到一个函数,在调用的时候出现问题,记录下实现过程. #ifndef MLS_DEFORMATION_H #define MLS_DEFORMATION_H #include <vector ...
- Android studio 怎么使用单元测试(不需要device)
关于单元测试的使用,写代码过程中有时候需要检测下代码逻辑的可行性与正确性,又不想通过设备运行,那么就可以通过单元测试跑下代码~ 1.首先建立一个Android studio的Android项目: 2. ...
- js操作DOM在父元素中的结尾添加子节点注意
impressionHtml=`<img src=${value} alt=""/>`; document.getElementById("wrapper&q ...
- 原生App切图的那些事儿
如何切图? 了解iphone界面的尺寸 最小的分辨率是320x480,我们把这个尺寸定为基准界面尺寸(baseline),基准尺寸所用的图标定为1倍图(1x). 在实际设计过程中,为了降低设计成本,一 ...
- python 迭代器模式
迭代器模式 迭代器模式(Iterator Pattern)是 Java 和 .Net 编程环境中非常常用的设计模式.这种模式用于顺序访问集合对象的元素,不需要知道集合对象的底层表示. 迭代器模式属于行 ...
- akka cluster singleton
cluster singleton 需要注意的一点是 ClusterSingletonProxy 必须和 ClusterSingletonManager 一起工作 尝试过通过 path 来获得 sin ...
- Linux下常用的文件传输方式介绍与比较
参考链接:http://mingxinglai.com/cn/2014/03/copy-file-in-linux/ 本文介绍了linux之间传输文件的几种方式,并通过具体实验测试了几种文件传输方式之 ...
- mysql无法生成log文件
做服务器主从配置时,发现/var/log/mysql下面一直没有log文件,明明配置文件/etc/mysql/mysql.conf.d/mysqld.cnf也开启log了. general_log_f ...
- js给原型增加新属性和方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...