# Binary Search Tree
有學弟來問我怎麼寫資料結構的作業,題目就是在已知資料的出現次數時,找到該筆測資的最佳二元搜尋樹 (opens new window)。所以我就順手寫了一個程式啦。只不過程式雖然是寫出來了,學弟他們當然還要自己轉成 Visual Basic 的程式碼囉~
# 輸入說明
每組測試資料中,第一行有一個整數 $n$
,代表這組測試資料有幾筆資料;接下來第二行有 $n$
個由小到大的整數,依序代表第 $1$
~ $n-1$
個資料的值;第三行有 $n$
個整數,依序代表第 $1$
~ $n-1$
個資料的出現次數。若沒有輸入 $n$
(EOF) 則程式結束。
# 輸出說明
請根據 $1$
~ $n-1$
個資料的出現次數,排出該資料的最佳二元搜尋樹(任一組解)。
# 範例輸入
5
29 36 41 49 57
1 5 2 3 6
# 範例輸出
{
"data": 49,
"left":
{
"data": 36,
"left":
{
"data": 29,
"left":
null,
"right":
null,
},
"right":
{
"data": 41,
"left":
null,
"right":
null,
},
},
"right":
{
"data": 57,
"left":
null,
"right":
null,
},
}
# 程式碼
#include<iostream>
#include<cstdio>
#include<cstring>
#define SIZE 10
#define oo 2147483647
using namespace std;
struct map_S{
int w,f,p;
// weight, frequence, parent
};
struct node{
node *left, *right;
int a;
};
node *root = NULL;
int arr1[ SIZE ], freq[ SIZE ], ia;
map_S map[ SIZE ][ SIZE ];
void debug()
{
cout<<"weight:"<<endl;
for(int i=0;i<SIZE;i++)
{
for(int j=0;j<SIZE;j++)
printf("%3d",map[i][j].w);
cout<<endl;
}
cout<<"frequence:"<<endl;
for(int i=0;i<SIZE;i++)
{
for(int j=0;j<SIZE;j++)
printf("%3d",map[i][j].f);
cout<<endl;
}
cout<<"parent:"<<endl;
for(int i=0;i<SIZE;i++)
{
for(int j=0;j<SIZE;j++)
printf("%3d",map[i][j].p);
cout<<endl;
}
}
int DP1(int left=0,int right=ia-1)
{
if( left<0 || left >= ia || right<0 || right >= ia || right<left )
return 0;
// cout<<endl<<"left="<<left<<" right="<<right<<endl;
// debug();
// cin.get();
if(map[left][right].p==-1)
{
map[left][right].w = oo;
map[left][right].p = -1;
for( int i = left; i<= right; i++ )
{
int sum = freq[i];
sum += DP1(left,i-1);
sum += DP1(i+1,right);
if(sum < map[left][right].w)
{
map[left][right].w = sum;
map[left][right].p = i;
}
}
}
return map[left][right].w + map[left][right].f;
}
void inline print_space(int ia)
{
while(ia--) printf(" ");
}
void print_tree( node *ptr = NULL, int tab_size = 2, int space = 0 )
{
if( ptr==NULL )
{
print_space(space);
printf("null%c\n",(space!=0?',':' '));
return;
}
print_space(space);
printf("{\n");
print_space(space + tab_size);
printf("\"data\": %d,\n", ptr->a);
print_space(space + tab_size);
printf("\"left\":\n");
print_tree( ptr->left, tab_size, space+tab_size );
print_space(space + tab_size);
printf("\"right\":\n");
print_tree( ptr->right, tab_size, space+tab_size );
print_space(space);
printf("}%c\n",(space!=0?',':' '));
}
void delete_tree(node* ptr=NULL)
{
if(ptr==NULL)
return;
delete_tree(ptr->left);
delete_tree(ptr->right);
delete ptr;
}
node* DP2(int left=0, int right=ia-1)
{
if( left<0 || left >= ia || right<0 || right >= ia || right<left )
return NULL;
node *pa = new node;
pa->a = arr1[map[left][right].p];
pa->left = DP2(left,map[left][right].p-1);
pa->right = DP2(map[left][right].p+1,right);
return pa;
}
int main()
{
while(cin>>ia)
{
for(int i=0;i<ia;i++)
cin>>arr1[i];
for(int i=0;i<ia;i++)
cin>>freq[i];
// cin.get();
memset(map, -1, sizeof(map));
for(int i=0;i<ia;i++)
for(int j=i;j<ia;j++)
map[i][j].f = ( j>i ? map[i][j-1].f : 0 ) + freq[j];
DP1();
// debug();
root = DP2();
print_tree(root);
delete_tree(root);
}
}