次优二叉树

来源:互联网 发布:google drive mac 编辑:程序博客网 时间:2024/06/14 14:29

在有序序列的查找中,如果各个元素的查找概率都是一样的,那么二分查找是最快的查找算法,但是如果查找元素的查找概率是不一样的,那么用二分查找就不一定是最快的查找方法了,可以通过计算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

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          }      }  }  



0 0
原创粉丝点击