1. 程式人生 > >動態規劃實現最優二分搜尋樹

動態規劃實現最優二分搜尋樹

  1 #include <iostream>
  2 #include<fstream>
  3 #include<sstream>
  4 #include<vector>
  5 #include<string>
  6 using namespace std;
  7 const int Max_Num = 100;
  8 
  9 typedef struct Point {
 10     int n; //點的個數
 11     double p[Max_Num];
 12     double q[Max_Num];
 13
int root[Max_Num][Max_Num]; 14 double w[Max_Num][Max_Num]; 15 double e[Max_Num][Max_Num]; 16 }Point; 17 18 vector<Point> points; 19 vector<string> res; 20 vector<int> num; 21 22 void file_read(); 23 void createPoint(); 24 void optimalBST(); 25 void printRoot(Point P);
26 void printOptimalBST(int i, int j, int r, Point P, ofstream &fileWrite); 27 template <class Type> 28 Type stringToNum(const string& str) { 29 istringstream iss(str); 30 Type num; 31 iss >> num; 32 iss.str(""); 33 return num; 34 } 35 36 void file_read() {
37 string str2, str1 = "", result; 38 ifstream fileRead("in.dat"); 39 if (fileRead.is_open()) { 40 while (getline(fileRead, str2, '\n')) { 41 if (str2.find(" ") != -1) { 42 str1.append(str2 + " "); 43 } 44 else { 45 num.push_back(stringToNum<int>(str2)); 46 if (str1 != "") { 47 res.push_back(str1); 48 } 49 str1 = ""; 50 } 51 } 52 res.push_back(str1); 53 fileRead.close(); 54 } 55 } 56 57 void createPoint() { 58 string temp; 59 Point P; 60 for (int i = 0; i < res.size(); i++) { 61 vector<string> temp_str; //存放按照空格分開後的數字 62 int n = num[i]; 63 stringstream input(res[i]); 64 while (input >> temp) { 65 temp_str.push_back(temp); 66 } 67 P.n = n; 68 for(int k = 0; k<=n; k++) P.p[k] = stringToNum<double>(temp_str[k]); 69 for(int k = n + 1; k<temp_str.size(); k++) P.q[k-(n+1)] = stringToNum<double>(temp_str[k]); 70 points.push_back(P); 71 } 72 } 73 74 //根據書上的虛擬碼:接收概率列表p1....pn和q0.....qn以及規模n作為輸入 計算出e和root 75 void optimalBST(){ 76 Point P; 77 for(int i = 0; i<res.size(); i++) { 78 vector<string> temp_str; //存放按照空格分開後的數字 79 int n = num[i]; 80 string temp; 81 stringstream input(res[i]); 82 while (input >> temp) { 83 temp_str.push_back(temp); 84 } 85 P.n = n; 86 87 for(int k = 0; k<=n; k++) P.p[k] = stringToNum<double>(temp_str[k]); 88 for(int k = n + 1; k<temp_str.size(); k++) P.q[k-(n+1)] = stringToNum<double>(temp_str[k]); 89 90 //初始化只包括虛擬鍵的子樹 91 for (int i = 1;i <= P.n + 1;++i){ 92 P.w[i][i-1] = P.q[i-1]; 93 P.e[i][i-1] = P.q[i-1]; 94 } 95 //由下到上,由左到右逐步計算 96 for (int len = 1;len <= P.n;++len){ 97 for (int i = 1;i <= P.n - len + 1;++i){ 98 int j = i + len - 1; 99 P.e[i][j] = Max_Num; 100 P.w[i][j] = P.w[i][j-1] + P.p[j] + P.q[j]; 101 //求取最小代價的子樹的根 102 for (int r = i;r <= j;++r) 103 { 104 double temp = P.e[i][r-1] + P.e[r+1][j] + P.w[i][j]; 105 if (temp < P.e[i][j]) 106 { 107 P.e[i][j] = temp; 108 P.root[i][j] = r; 109 } 110 } 111 } 112 } 113 points.push_back(P); 114 } 115 } 116 117 void printOptimalBST(int i, int j, int r, Point P, ofstream &fileWrite){ 118 int root_node = P.root[i][j];//子樹根節點 119 if (root_node == P.root[1][P.n]){ 120 //輸出整棵樹的根 121 fileWrite << "k" << root_node << "是根" << endl; 122 printOptimalBST(i, root_node - 1, root_node, P, fileWrite); 123 printOptimalBST(root_node +1 , j, root_node, P, fileWrite); 124 return; 125 } 126 127 if (j < i - 1){ 128 return; 129 }else if (j == i - 1){//遇到虛擬鍵 130 if (j < r) 131 fileWrite << "d" << j << "是" << "k" << r << "的左孩子" << endl; 132 else 133 fileWrite << "d" << j << "是" << "k" << r << "的右孩子" << endl; 134 return; 135 } 136 else{//遇到內部結點 137 if (root_node < r) 138 fileWrite << "k" << root_node << "是" << "k" << r << "的左孩子" << endl; 139 else 140 fileWrite << "k" << root_node << "是" << "k" << r << "的右孩子" << endl; 141 } 142 printOptimalBST(i, root_node - 1, root_node, P, fileWrite); 143 printOptimalBST(root_node + 1, j, root_node, P, fileWrite); 144 } 145 146 //輸出最優二叉查詢樹所有子樹的根 147 void printRoot(Point P){ 148 cout << "各子樹的根:" << endl; 149 for (int i = 1;i <= P.n;++i){ 150 for (int j = 1;j <= P.n;++j){ 151 cout << P.root[i][j] << " "; 152 } 153 cout << endl; 154 } 155 cout << endl; 156 } 157 158 int main(){ 159 file_read(); 160 optimalBST(); 161 ofstream fileWrite("out.dat"); 162 Point P ; 163 for(int i = 0; i<points.size(); i++) { 164 P = points[i]; 165 printRoot(P); 166 printOptimalBST(1,P.n,-1, P, fileWrite); 167 } 168 fileWrite.clear(); 169 return 0; 170 }