找最小成本二分检索树

从文件读取成本,实现找出最小成本二分检索树的算法,并以树状结构输出

#include  < stdio.h >
#include 
< stdlib.h >
#define  N 4
typedef 
struct  te {
        
int node;
        
struct te *left,*right;
    }
tree;
int  findmin( int  i, int  j, int  ( * r)[N], int  ( * c)[N]);
tree 
*  OBST( int   * p, int   * q, int  n);
void  buileTree(tree  ** head, int  a, int  b);
void  travseTree(tree  * p);
void  printTree(tree  * head);
void  treeToArray(tree  * p, int  num);
/*
**这里假设数组P和Q都乘了一个相应的整数,使得P和Q的元素值都为整数
*/

char  a[N][ 20 ];  
int  node[ 100 ];   // 用于按顺序保存树中各个结点,以便按树状打印树中结点 
int  main( void )
{
    
    
int p[N],q[N+1],i;
    FILE 
*fp;
    tree 
*head;
    
if((fp=fopen("cost.txt","r"))==NULL){
        printf(
"Cannot open the file. ");
        exit(
-1);
    }

    
for(i=0;i<N;i++)
        fscanf(fp,
"%s",a[i]);
    
for(i=0;i<N;i++)
        fscanf(fp,
"%d",&p[i]);
    
for(i=0;i<N+1;i++)
        fscanf(fp,
"%d",&q[i]);
    
for(i=0;i<100;i++) node[i]=-1;
    head
=OBST(p,q,N);
    putchar(
' ');
    printf(
"该二分检索树的树状结构如下所示: ");
    printTree(head);
system(
"pause");
    
return 0;
}

int  r[N + 1 ][N + 1 ];
tree 
*  OBST( int   * p, int   * q, int  n)
    
int c[N+1][N+1],w[N+1][N+1];//,r[N+1][N+1];
    int i,j,m,k;
    tree 
*head;
    n
++;
    
for(i=0;i<n;i++)
        
for(j=0;j<n;j++){
            w[i][j]
=-1;
            c[i][j]
=-1;
            r[i][j]
=-1;
        }

    
for(i=0;i<n-1;i++){
        w[i][i]
=*(q+i);
        r[i][i]
=0;
        c[i][i]
=0;
        w[i][i
+1]=*(q+i)+*(q+i+1)+*(p+i);
        r[i][i
+1]=i+1;
        c[i][i
+1]=w[i][i+1];
    }

    w[n
-1][n-1]=*(q+n-1);
    r[n
-1][n-1]=0;
    c[n
-1][n-1]=0;
    
for(m=2;m<n;m++)
        
for(i=0;i<n-m;i++){
            j
=i+m;
            w[i][j]
=w[i][j-1]+*(p+j-1)+*(q+j);
            k
=findmin(i,j,r,c);
            c[i][j]
=w[i][j]+c[i][k-1]+c[k][j];
            r[i][j]
=k;
        }

    printf(
"计算W,C,R的值如下(输出的是他们的逆矩阵)(其中-1表示该数不必考虑): ");
    
for(j=0;j<n;j++){
        
for(i=0;i<n;i++)
            printf(
"%2d,%2d,%2d ",w[i][j],c[i][j],r[i][j]);
        putchar(
' ');
    }

    buileTree(
&head,0,N);
    
return head;
}

int  findmin( int  i, int  j, int  ( * r)[N + 1 ], int  ( * c)[N + 1 ]) {
    
int min,minL,k,m,n;
    m
=(*(r+i))[j-1];
    n
=(*(r+i+1))[j];
    min
=c[i][m-1]+c[m][j];
    minL
=m;
    
for(m+=1;m<=n;m++){
        k
=c[i][m-1]+c[m][j];
        
if(k<min){
            min
=k;
            minL
=m;
        }

    }

    
return minL;
}

void  buileTree(tree  ** p, int  a, int  b) {
    
int mk;
    
if(a==b) return;
    mk
=r[a][b];
    
*p=(tree *)malloc(sizeof(tree));
    (
*p)->node=mk;
    (
*p)->left=NULL;
    (
*p)->right=NULL;
    buileTree(
&(*p)->left,a,mk-1);
    buileTree(
&(*p)->right,mk,b);
}

void  treeToArray(tree  * p, int  num) {  
    
//将树中的结点按顺序保存到数组中,num表示当前结点的号码,初始调用设为1
    if(!p) return;
    node[num]
=p->node;
    treeToArray(p
->left,2*num);
    treeToArray(p
->right,2*num+1);
}

void  printTree(tree  * head) {
    
int i,j,level,space,num;
    i
=1;level=1;num=0;
    treeToArray(head,
1);
    
for(i=1,level=1;i<100&&num<N;i++){
        
if(i==level) 
            putchar(
' ');
        space
=60/(level+1);
        
for(j=0;j<space;j++) printf(" ");
        
if(node[i]!=-1{ printf("%s",a[node[i]-1]); num++;}
        
else printf(" ");
        
if((i+1)==level*2) level*=2;
    }

    putchar(
' ');
}

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值