构建思路
1.把有序表中的每个关键字都当成根节点;
2.遍历有序表,计算出每个关键字的左子树累加权值sw和右子树累加权值dw;
3.根据sw和dw求出最小权值▲p;
4.最小权值对应的根节点移出有序表,作为树的根节点。
5.因此有序表被拆成两个有序表,两个有序表中找两个最小权值对应根节点作为根节点左孩子和右孩子,然后拆成四个有序表找出节点作为这两个孩子的孩子节点以此类推;
对于▲p的理解(个人理解,不一定对)
被查找的关键字有了查找概率时(权值),二分查找就不一定合适了。
如果让有序表左右两边权值相差为零或很小,那么这个权值可以忽略不记,这样就转化为了二分查找。
代码
▲p可以由有序表最后一个关键字的sw减去目标关键字的sw和目标的前一个元素的插值的得出。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct Array{
char data;
int w;
int sw;
}Array;
typedef struct Tree{
Array arr;
struct Tree *next;//链表指针
struct Tree *front;//节点头指针
struct Tree *lchild;//节点左孩子
struct Tree *rchild;//节点右孩子
}Tree;
typedef struct SFTree{
Tree *front;
int length;
}SFTree;
//创建链表
int init_SFTree(SFTree *st,Array arr[],int n){
st->front=(Tree *)malloc(sizeof(Tree));
Tree *p,*q;
st->front->front=0;
p=st->front;
for(int i=0;i<n;i++){
//创建节点
q=(Tree *)malloc(sizeof(Tree));
q->arr.data=arr[i].data;
q->arr.w=arr[i].w;
//尾插法
q->front=p;
q->next=NULL;
p->next=q;
p=p->next;
}
st->length=n;
return 1;
}
//计算SW
int cmpuSW(Tree *f){
int sw=0;
while (f->next)
{
sw=sw+f->arr.w;
f->arr.sw=sw;
f=f->next;
// printf("%d ",sw);
}
f->arr.sw=sw+f->arr.w;
return f->arr.sw;//
}
//构建查找树
int creat_SFTree(Tree **z,Tree *f){
if(!f){
(*z)=NULL;
return 1;
}else{
Tree *p,*q,*t;
q=f;
//delat是▲p的值
int dw=0,delat,min=100;
dw=cmpuSW(f);
// printf("%c %d \n",f->arr.data,f->arr.w);
while (q->next)
{
if(q!=f) {
delat=abs(dw-(q->arr.sw)-(q->front->arr.sw));
}else{
delat=dw-q->arr.sw;
}
if(min>abs(q->arr.sw-dw)){
(*z)=q;
min=abs(q->arr.sw-dw);
}
q=q->next;
}
// printf("%c %d \n",f->arr.data,f->arr.w);
// printf("%c %d \n",(*z)->arr.data,(*z)->arr.w);
if(!(*z)){
(*z)=f;
printf("%c %d \n",(*z)->arr.data,(*z)->arr.w);
(*z)->lchild=NULL;
(*z)->rchild=NULL;
return 1;
}else{
printf("%c %d \n",(*z)->arr.data,(*z)->arr.w);
(*z)->front->next=NULL;
(*z)->front=NULL;
t=(*z)->next;
(*z)->next=NULL;
if(f!=(*z)) creat_SFTree(&((*z)->lchild),f);
creat_SFTree(&((*z)->rchild),t);
}
}
}
//查找
int seach_stree(Array arr[],char s){
SFTree st;Tree *q1;
Tree **q=NULL;q=&q1;
init_SFTree(&st,arr,14);
creat_SFTree(q,st.front->next);
Tree *p=NULL;
p=*q;
printf("%c\n",(*q)->lchild->rchild->arr.data);
while (p)
{
if(p->arr.data==s){
printf("%c %d",p->arr.data,p->arr.w);
break;
}
else if (p->arr.data>s)
{
/* code */
p=p->lchild;
}
else{
p=p->rchild;
}
}
}