次优查找树的实现【严蔚敏】
来源:互联网 发布:虚拟骑行软件 编辑:程序博客网 时间:2024/05/20 13:08
考虑查找成功时的情况:查找性能最佳的判别树是带权路径之和PH的值。
最优查找树:
用数学公式来表示就是:使得的PH值最小的树为该数组的静态最优查找树。其中i为节点标号,为节点i的带权路径长度,,它等于结点i的查找路径长度c,乘以该结点被查找的概率p;h表示节点i在搜索树中的高度。通俗点来说,就是权值越大的结点,越放到靠近根结点的位置。可能查找概率大,需要的比较次数(折半查找中的次数)多,或者两者皆有。
次优二叉树:
选出一个结点,使得它左右两侧的子数组的权值累加和之差的绝对值最小。把这个结点当做根节点,递归地用刚才的左右字数组构造它的左右子树。
数学表达式:。
数学表达式:。
Status SecondOptimal(BiTree &T, ElemType R[],int sw[],int low,int high) { // 由有序表R[low..high]及其累计权值表sw(其中sw[0]==0)递归构造 // 次优查找树T。算法9.3 int i,j; double min,dw; i=low; min=fabs(sw[high]-sw[low]); dw=sw[high]+sw[low-1]; for(j=low+1;j<=high;++j) // 选择最小的△Pi值 if(fabs(dw-sw[j]-sw[j-1])<min) { i=j; min=fabs(dw-sw[j]-sw[j-1]); } if(!(T=(BiTree)malloc(sizeof(BiTNode)))) return ERROR; 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); // 构造右子树 return OK; }
void FindSW(int sw[],SSTable ST) { // 按照有序表ST中各数据元素的Weight域求累计权值表sw int i; sw[0]=0; for(i=1;i<=ST.length;i++) sw[i]=sw[i-1]+ST.elem[i].weight; }
Status CreateSOSTree(SOSTree &T,SSTable ST) { // 由有序表ST构造一棵次优查找树T。ST的数据元素含有权域weight。算法9.4 if(ST.length==0) T=NULL; else { FindSW(sw,ST); // 按照有序表ST中各数据元素的Weight域求累计权值表sw SecondOptimal(T,ST.elem,sw,1,ST.length); } return OK; }
代码完整实现:
// algo9-3.cpp 静态查找表(静态树表)的操作 #include <stdio.h> #include <malloc.h> #include <math.h> #include<iostream> //cout,cinusing namespace std; // 函数结果状态代码 #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 // #define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行 typedef int Status; // Status是函数的类型,其值是函数结果状态代码,如OK等 typedef int Boolean; // Boolean是布尔类型,其值是TRUE或FALSE #define N 9 // 数据元素个数 #define EQ(a,b) ((a)==(b)) #define LT(a,b) ((a)<(b)) #define LQ(a,b) ((a)<=(b)) typedef char KeyType; // 设关键字域为字符型 struct ElemType // 数据元素类型(以教科书例9-1为例) { KeyType key; int weight; }r[N]={{'A',1},{'B',1},{'C',2},{'D',5},{'E',3}, {'F',4},{'G',4},{'H',3},{'I',5}}; // 全局变量 int sw[N+1]; // 累计权值,全局变量 typedef ElemType TElemType; typedef struct { ElemType *elem; // 数据元素存储空间基址,建表时按实际长度分配,0号单元留空 int length; // 表长度 }SSTable; // 静态查找表(顺序表和有序表)的基本操作(7个) Status Creat_Seq(SSTable &ST,int n) { // 操作结果: 构造一个含n个数据元素的静态顺序查找表ST(数据来自全局数组r) int i; ST.elem=(ElemType*)calloc(n+1,sizeof(ElemType)); // 动态生成n个数据元素空间(0号单元不用) if(!ST.elem) return ERROR; for(i=1;i<=n;i++) *(ST.elem+i)=r[i-1]; // 将全局数组r的值依次赋给ST ST.length=n; return OK; } void Ascend(SSTable &ST) { // 重建静态查找表为按关键字非降序排序 int i,j,k; for(i=1;i<ST.length;i++) { k=i; ST.elem[0]=ST.elem[i]; // 待比较值存[0]单元 for(j=i+1;j<=ST.length;j++) if LT(ST.elem[j].key,ST.elem[0].key) { k=j; ST.elem[0]=ST.elem[j]; } if(k!=i) // 有更小的值则交换 { ST.elem[k]=ST.elem[i]; ST.elem[i]=ST.elem[0]; } } } Status Creat_Ord(SSTable &ST,int n) { // 操作结果: 构造一个含n个数据元素的静态按关键字非降序查找表ST // 数据来自全局数组r Status f; f=Creat_Seq(ST,n); if(f) Ascend(ST); return f; } Status Destroy(SSTable &ST) { // 初始条件: 静态查找表ST存在。操作结果: 销毁表ST free(ST.elem); ST.elem=NULL; ST.length=0; return OK; } int Search_Seq(SSTable ST,KeyType key) { // 在顺序表ST中顺序查找其关键字等于key的数据元素。若找到,则函数值为 // 该元素在表中的位置,否则为0。算法9.1 int i; ST.elem[0].key=key; // 哨兵 for(i=ST.length;!EQ(ST.elem[i].key,key);--i); // 从后往前找 return i; // 找不到时,i为0 } int Search_Bin(SSTable ST,KeyType key) { // 在有序表ST中折半查找其关键字等于key的数据元素。若找到,则函数值为 // 该元素在表中的位置,否则为0。算法9.2 int low,high,mid; low=1; // 置区间初值 high=ST.length; while(low<=high) { mid=(low+high)/2; if EQ(key,ST.elem[mid].key) // 找到待查元素 return mid; else if LT(key,ST.elem[mid].key) high=mid-1; // 继续在前半区间进行查找 else low=mid+1; // 继续在后半区间进行查找 } return 0; // 顺序表中不存在待查元素 } Status Traverse(SSTable ST,void(*Visit)(ElemType)) { // 初始条件: 静态查找表ST存在,Visit()是对元素操作的应用函数 // 操作结果: 按顺序对ST的每个元素调用函数Visit()一次且仅一次。 // 一旦Visit()失败,则操作失败 ElemType *p; int i; p=++ST.elem; // p指向第一个元素 for(i=1;i<=ST.length;i++) Visit(*p++); return OK; } typedef struct BiTNode { TElemType data; BiTNode *lchild,*rchild; // 左右孩子指针 }BiTNode,*BiTree; Status SecondOptimal(BiTree &T, ElemType R[],int sw[],int low,int high) { // 由有序表R[low..high]及其累计权值表sw(其中sw[0]==0)递归构造 // 次优查找树T。算法9.3 int i,j; double min,dw; i=low; min=fabs(sw[high]-sw[low]); dw=sw[high]+sw[low-1]; for(j=low+1;j<=high;++j) // 选择最小的△Pi值 if(fabs(dw-sw[j]-sw[j-1])<min) { i=j; min=fabs(dw-sw[j]-sw[j-1]); } if(!(T=(BiTree)malloc(sizeof(BiTNode)))) return ERROR; 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); // 构造右子树 return OK; } void FindSW(int sw[],SSTable ST) { // 按照有序表ST中各数据元素的Weight域求累计权值表sw int i; sw[0]=0; for(i=1;i<=ST.length;i++) sw[i]=sw[i-1]+ST.elem[i].weight; } typedef BiTree SOSTree; // 次优查找树采用二叉链表的存储结构 Status CreateSOSTree(SOSTree &T,SSTable ST) { // 由有序表ST构造一棵次优查找树T。ST的数据元素含有权域weight。算法9.4 if(ST.length==0) T=NULL; else { FindSW(sw,ST); // 按照有序表ST中各数据元素的Weight域求累计权值表sw SecondOptimal(T,ST.elem,sw,1,ST.length); } return OK; } Status Search_SOSTree(SOSTree &T,KeyType key) { // 在次优查找树T中查找关键字等于key的元素。找到则返回OK,否则返回FALSE while(T) // T非空 if(T->data.key==key) return OK; else if(T->data.key>key) T=T->lchild; else T=T->rchild; return FALSE; // 顺序表中不存在待查元素 } void print(ElemType c) // Traverse()调用的函数 { printf("(%c %d) ",c.key,c.weight); } int main() { SSTable st; SOSTree t; Status i; KeyType s; Creat_Ord(st,N); // 由全局数组产生非降序静态查找表st Traverse(st,print); CreateSOSTree(t,st); // 由有序表构造一棵次优查找树 printf("\n请输入待查找的字符: "); scanf("%c",&s); i=Search_SOSTree(t,s); if(i) printf("%c的权值是%d\n",s,t->data.weight); else printf("表中不存在此字符\n"); }
0 0
- 次优查找树的实现【严蔚敏】
- 次优查找树的查找原理
- 构造次优查找树的算法
- 次优查找树的原理是什么?
- 构造次优查找树
- 次优查找树
- 构造次优查找树
- 次优查找树
- 次优查找树
- 次优查找树
- 【数据结构】查找番外篇 静态数表的查找 次优查找树
- 【数据结构-查找】次优排序树
- 数据结构——次优查找树的构造
- 数据结构_查找_次优查找树
- 数据结构笔记-构造次优查找树
- C++代码,数据结构-次优查找树
- 第九章(2).次优查找树
- 次优查找树(Nearly Optimal Search Tree)
- java JVM的内存区域(运行时数据区域)
- 15---RAID 和 LVM
- UE4快速实现涂鸦功能
- android属性动画完全解析
- Hbase高并发读写优化
- 次优查找树的实现【严蔚敏】
- Java基础知识点
- 阵前第一功
- kvm:连接虚拟机的几种方式(ssh,vnc,console,virt-viewer)
- 树链剖分&树状数组区间加减区间求和模板
- 数组实现的线性表基本操作[C]
- 线性表
- 三、Guava的缓存
- PHP学习路径