次优查找树(纯链表构建)

构建思路

1.把有序表中的每个关键字都当成根节点;

2.遍历有序表,计算出每个关键字的左子树累加权值sw和右子树累加权值dw;

3.根据swdw求出最小权值▲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;

        }

       

    }

   

}

        

  • 19
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值