次优二叉树

来源:互联网 发布:顶级富豪 知乎 编辑:程序博客网 时间:2024/05/21 11:33

在有序序列的查找中,如果各个元素的查找概率都是一样的,那么二分查找是最快的查找算法,但是如果查找元素的查找概率是不一样的,那么用二分查找就不一定是最快的查找方法了,可以通过计算ASL来得知。

所以基于这种查找元素概率不想等的有序序列,可以通过构造最优二叉树的方法,使得该二叉树的带权路径长度最小,这样的二叉树的构造代价是非常大的,所以用一种近似的算法,构造次优查找树,该树的带权路径长度近似达到最小。

次优查找数的算法描述如下

已知一个序列:(rl,rl+1,……,rh),递增有序

它对应的权值为:(wl,wl+1,……,wh)

定义:


取△Pi最小的那个元素i作为根,然后分别对子序列(rl,rl+1,……,ri-1)和(ri+1,ri+2,……,rh)同样构造次优查找树,并分别作为i的左子树和右子树

在计算△Pi时,实际上就是计算元素i前面的元素的权值之和与元素i后面的元素的权值之和的差值。如果对每一个元素都要这样计算就有很多重复计算,为了提高效率,我们引入“累计权值和”



从上面这个公式可以看出,我们只要一次性地求出所有元素的swi值并保存起来,以后每次求 △Pi就只要查表中对应的四个sw值进行计算就可以了。

我们先来看看下面这个例子:

关键字ABCDEFGHI权值112534435j123456789swj12491216202328△Pj272522157

0

81523(根)




↑i


△Pj1196

1

9
8

1

7(根)


↑i


↑i
△Pj3

1

2
0
0
0(根)
↑i

↑i
↑i
↑i△Pj0
0





(根)↑i
↑i






代码如下:

#include <iostream>  

#include <cmath>  
using namespace std;  
  
typedef struct treenode  
{  
    char data;  
    int weight;  
    treenode *left;  
    treenode *right;  
}Treenode,*Treep;  
  
//初始化二叉树  
void init_tree(Treep &root)  
{  
    root=NULL;  
    cout<<"初始化成功!"<<endl;  
}  
  
//创建二叉树  
void SecondOptimal(Treep &rt, char R[],int sw[], int low, int high)  
{  
    //由有序表R[low....high]及其累积权值表sw(其中sw[0]==0)递归构造次优查找树T  
    int i=low;  
    int min = fabs(sw[high] - sw[low]);  
    int dw = sw[high] + sw[low-1];  
    for(int 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]);  
        }  
    }  
    rt=new Treenode;  
    rt->data=R[i];        //生成节点  
    if(i==low)            //左子树为空  
        rt->left = NULL; 
    else                //构造左子树  
        SecondOptimal(rt->left, R, sw, low, i-1);  
  
    if(i==high)            //右子树为空  
        rt->right = NULL;
    else                //构造右子树  
        SecondOptimal(rt->right, R, sw, i+1, high);  
return 1;
}//SecondOptimal  
  
//前序遍历二叉树  
void pre_order(Treep rt)  
{  
    if(rt)  
    {  
        cout<<rt->data<<"  ";  
        pre_order(rt->left);  
        pre_order(rt->right);  
    }  
}  
  
//中序遍历二叉树  
void in_order(Treep rt)  
{  
    if(rt)  
    {  
        in_order(rt->left);  
        cout<<rt->data<<"  ";  
        in_order(rt->right);  
    }  
}  
  
//后序遍历二叉树  
void post_order(Treep rt)  
{  
    if(rt)  
    {  
        post_order(rt->left);  
        post_order(rt->right);  
        cout<<rt->data<<"  ";  
    }  
}  
  
//查找二叉树中是否存在某元素  
int seach_tree(Treep &rt,char key)  
{  
    if(rt==NULL)   
        return 0;   
    else   
    {   
        if(rt->data==key)   
        {  
            return 1;  
        }  
        else  
        {  
            if(seach_tree(rt->left,key) || seach_tree(rt->right,key))  
                return 1;    //如果左右子树有一个搜索到,就返回1  
            else  
                return 0;    //如果左右子树都没有搜索到,返回0  
        }  
    }  
}  
原创粉丝点击