树  0.1
数据结构_第6章
ch6_6.cc
Go to the documentation of this file.
1 
14 #include "binaryTree.hh"
15 #include <ctime>
16 #include <fstream>
17 #include <string>
18 
19 // 常量定义
20 const std::string data_file_name("ch6_6.result");
21 
36 static bool GenTreeData(const char *_file_path = "./test0.txt", const char *empty_flag = "@");
37 
48 template <typename T, typename Comparator>
49 static void print_test_result(const Tree::binaryTree<T, Comparator> &tree_original, const typename Tree::binaryTree<T, Comparator>::value_type &flag, std::ostream &out = std::cout);
50 
51 int main(int argc, char const *argv[])
52 {
53  // time
54  clock_t t = clock();
55  time_t rawtime;
56  struct tm *timeinfo;
57 
58  time(&rawtime); // Get the current calendar time
59  timeinfo = localtime(&rawtime); // Convert time_t to tm as local time
60 
61  // 获取文件路径,参考:http://www.cplusplus.com/reference/string/string/find_last_of/
62  const std::string full_path_exec{argv[0]};
63  std::string::size_type found = full_path_exec.find_last_of("/\\", std::string::npos);
64  const std::string exec_path = full_path_exec.substr(0, found + 1);
65  const std::string exec_filename = full_path_exec.substr(found + 1, std::string::npos);
66 
67  // 生成数据文件,然后从文件中读取数据,依此建立一棵二叉树
68  std::string data_file_full_path{exec_path + data_file_name}; // 数据文件的绝对地址
69 
70  // 生成数据文件
71  if (!GenTreeData(data_file_full_path.c_str(), "@"))
72  {
73  std::cout << "文件:" << data_file_full_path << "生成失败!\n";
74  return 1;
75  }
76 
77  // 读数据文件
78  std::ifstream fin(data_file_full_path.c_str(), std::ios_base::in);
79  if (fin.fail())
80  {
81  std::cout << "文件:" << data_file_full_path << "读取失败!\n";
82  return 1;
83  }
84 
85  // 建立二叉树
86  Tree::binaryTree<std::string> tree_original{};
87  tree_original.createTree("@", fin);
88  fin.close();
89 
90  // 准备将结果写入数据文件
91  std::ofstream fout(data_file_full_path.c_str(), std::ios_base::app);
92  if (fout.fail())
93  {
94  std::cerr << "文件:" << data_file_full_path << "写入失败!\n";
95  return 1;
96  }
97 
98  // printf("Current local time and date: %s\n", asctime(timeinfo)); // Convert tm structure to string
99  std::cout << "\nCurrent local time and date: " << asctime(timeinfo) << '\n';
100  fout << "\nCurrent local time and date: " << asctime(timeinfo) << '\n';
101 
102  print_test_result(tree_original, "@", std::cout);
103  print_test_result(tree_original, "@", fout);
104 
105  // ch6_1
106  Tree::binaryTree<std::string> temp_tree = tree_original;
107  temp_tree.swaplr();
108  auto tree_swaplr = temp_tree;
109  std::cout << "\n交换左右结点后:\n";
110  fout << "\n交换左右结点后:\n";
111  print_test_result(tree_swaplr, "@", std::cout);
112  print_test_result(tree_swaplr, "@", fout);
113 
114  // ch6_3, ch6_4
115  temp_tree.delLeft("G");
116  temp_tree.delRight("G");
117  auto tree_swaplr_and_prune = temp_tree;
118  std::cout << "\n剪枝后:\n";
119  fout << "\n剪枝后:\n";
120  print_test_result(tree_swaplr_and_prune, "@", std::cout);
121  print_test_result(tree_swaplr_and_prune, "@", fout);
122 
123  // ch6_5
124  std::cout << "\ntree_swaplr == tree_swaplr_and_prune?\n"
125  << std::boolalpha << (tree_swaplr == tree_swaplr_and_prune);
126  fout << "\ntree_swaplr == tree_swaplr_and_prune?\n"
127  << std::boolalpha << (tree_swaplr == tree_swaplr_and_prune);
128  std::cout << "\ntree_original == tree_swaplr_and_prune?\n"
129  << std::boolalpha << (tree_original == tree_swaplr_and_prune);
130  fout << "\ntree_original == tree_swaplr_and_prune?\n"
131  << std::boolalpha << (tree_original == tree_swaplr_and_prune);
132  std::cout << "\ntree_original == tree_swaplr?\n"
133  << std::boolalpha << (tree_original == tree_swaplr);
134  fout << "\ntree_original == tree_swaplr?\n"
135  << std::boolalpha << (tree_original == tree_swaplr);
136  std::cout << "\ntree_original == tree_original?\n"
137  << std::boolalpha << (tree_original == tree_original);
138  fout << "\ntree_original == tree_original?\n"
139  << std::boolalpha << (tree_original == tree_original);
140  std::cout << "\ntree_swaplr == tree_swaplr?\n"
141  << std::boolalpha << (tree_swaplr == tree_swaplr);
142  fout << "\ntree_swaplr == tree_swaplr?\n"
143  << std::boolalpha << (tree_swaplr == tree_swaplr);
144  std::cout << "\ntree_swaplr_and_prune == tree_swaplr_and_prune?\n"
145  << std::boolalpha << (tree_swaplr_and_prune == tree_swaplr_and_prune);
146  fout << "\ntree_swaplr_and_prune == tree_swaplr_and_prune?\n"
147  << std::boolalpha << (tree_swaplr_and_prune == tree_swaplr_and_prune) << '\n';
148 
149  //ch6_6
150  std::cout << "\nis_symmetrical_tree(tree_original, tree_swaplr)?\n"
151  << std::boolalpha << Tree::binaryTree<std::string>::is_symmetrical_tree(tree_original, tree_swaplr);
152  fout << "\nis_symmetrical_tree(tree_original, tree_swaplr)?\n"
153  << std::boolalpha << Tree::binaryTree<std::string>::is_symmetrical_tree(tree_original, tree_swaplr);
154  std::cout << "\nis_symmetrical_tree(tree_swaplr, tree_swaplr)?\n"
155  << std::boolalpha << Tree::binaryTree<std::string>::is_symmetrical_tree(tree_swaplr, tree_swaplr);
156  fout << "\nis_symmetrical_tree(tree_swaplr, tree_swaplr)?\n"
157  << std::boolalpha << Tree::binaryTree<std::string>::is_symmetrical_tree(tree_swaplr, tree_swaplr);
158  std::cout << "\nis_symmetrical_tree(tree_original, tree_original)?\n"
159  << std::boolalpha << Tree::binaryTree<std::string>::is_symmetrical_tree(tree_original, tree_original);
160  fout << "\nis_symmetrical_tree(tree_original, tree_original)?\n"
161  << std::boolalpha << Tree::binaryTree<std::string>::is_symmetrical_tree(tree_original, tree_original) << '\n';
162 
163  // 测试赋值运算符、移动赋值和移动构造
164  // 复制构造
165  auto tree_copy_construct = tree_swaplr_and_prune;
166  std::cout << "\n(复制构造)auto tree_copy_construct = tree_swaplr_and_prune;\n";
167  fout << "\n(复制构造)auto tree_copy_construct = tree_swaplr_and_prune;\n";
168  print_test_result(tree_copy_construct, "@", std::cout);
169  print_test_result(tree_copy_construct, "@", fout);
170  // 移动构造
171  auto tree_move_construct = std::move(tree_swaplr_and_prune);
172  std::cout << "\n(移动构造)auto tree_move_construct = std::move(tree_swaplr_and_prune);\n";
173  fout << "\n(移动构造)auto tree_move_construct = std::move(tree_swaplr_and_prune);\n";
174  print_test_result(tree_move_construct, "@", std::cout);
175  print_test_result(tree_move_construct, "@", fout);
176  // 试图使用过期的对象
177  std::cout << "\n(使用过期的对象)print_test_result(tree_swaplr_and_prune, \"@\", std::cout);\n";
178  fout << "\n(使用过期的对象)print_test_result(tree_swaplr_and_prune, \"@\", fout);\n";
179  print_test_result(tree_swaplr_and_prune, "@", std::cout);
180  print_test_result(tree_swaplr_and_prune, "@", fout);
181  // 复制构造一个临时对象,然后向过期的对象移动赋值
182  tree_swaplr_and_prune = Tree::binaryTree(tree_move_construct);
183  std::cout << "\n(向过期的对象移动赋值)tree_swaplr_and_prune = Tree::binaryTree(tree_move_construct);\n";
184  fout << "\n(向过期的对象移动赋值)tree_swaplr_and_prune = Tree::binaryTree(tree_move_construct);\n";
185  print_test_result(tree_swaplr_and_prune, "@", std::cout);
186  print_test_result(tree_swaplr_and_prune, "@", fout);
187  // 赋值
188  Tree::binaryTree<std::string> tree_copy_assign{};
189  tree_copy_assign = tree_swaplr_and_prune;
190  std::cout << "\n(赋值)tree_copy_assign = tree_swaplr_and_prune;\n";
191  fout << "\n(赋值)tree_copy_assign = tree_swaplr_and_prune;\n";
192  print_test_result(tree_copy_assign, "@", std::cout);
193  print_test_result(tree_copy_assign, "@", fout);
194 
195  t = clock() - t;
196  // printf("\nIt took me %ld clicks (%f seconds).\n", t, ((float)t) / CLOCKS_PER_SEC);
197  std::cout << "\nIt took me " << t << " clicks (" << ((float)t) / CLOCKS_PER_SEC << " seconds).\n";
198  fout << "\nIt took me " << t << " clicks (" << ((float)t) / CLOCKS_PER_SEC << " seconds).\n";
199 
200  fout.close();
201  system("pause");
202  return 0;
203 }
204 
205 bool GenTreeData(const char *_file_path, const char *empty_flag)
206 {
207  std::string file_path(_file_path);
208 
209  // 调用DOS命令,询问是否删除文件
210  std::string cmd = std::string("DEL /P \"") + file_path + '"';
211  system("@echo on");
212  system("echo We are trying to delete some files, which will be created later.");
213  system("pause");
214  system(cmd.c_str());
215 
216  // 检查文件是否存在且可读
217  std::ifstream fin(file_path.c_str(), std::ios_base::in);
218  if (fin.good())
219  {
220  std::cerr << "文件已存在!\n";
221  fin.close();
222 
223  system("pause");
224  return true;
225  }
226 
227  // 文件不存在或不可读,尝试新建
228  std::ofstream fout(file_path.c_str(), std::ios_base::out);
229  if (fout.fail())
230  {
231  std::cerr << "无写权限,文件生成失败!\n";
232  system("pause");
233  return false;
234  }
235  fout << "A\n"
236  << "B\tC\n"
237  << "D\tE\tF\tG\n"
238  << empty_flag << '\t' << empty_flag << '\t' << empty_flag << '\t' << empty_flag << '\t' << empty_flag << '\t' << empty_flag << '\t' << "H\tI\n"
239  << empty_flag << '\t' << empty_flag << '\t' << empty_flag << '\t' << empty_flag << std::endl;
240 
241  // 检查是否生成成功
242  if (fout.good())
243  {
244  system("echo File created successfully!");
245  fout.close();
246  system("pause");
247  return true;
248  }
249 
250  std::cerr << "无法生成文件!\n";
251  system("pause");
252  return false;
253 }
254 
255 template <class T, typename Comparator>
256 void print_test_result(const Tree::binaryTree<T, Comparator> &tree_original, const typename Tree::binaryTree<T, Comparator>::value_type &flag, std::ostream &out)
257 {
258  out << "二叉树的规模(递归 非递归):\n"
259  << tree_original.size() << ' ' << tree_original.size_loop();
260  out << "\n二叉树的高(深)度(递归 非递归),从0起:\n"
261  << tree_original.height() << ' ' << tree_original.height_loop();
262  // ch6_2
263  out << "\n度为2的结点的个数是:\n"
264  << tree_original.CountDegreeTwo();
265  // ch6_3
266  out << "\n是否为满二叉树:\n"
267  << std::boolalpha << tree_original.isFullBinaryTree();
268  // ch6_4
269  out << "\n是否为完全二叉树:\n"
270  << std::boolalpha << tree_original.isCompleteTree();
271  out << "\n前序遍历(递归):\n";
272  tree_original.preOrder(out);
273  out << "\n前序遍历(非递归):\n";
274  tree_original.preOrder_loop(out);
275  out << "\n中序遍历(递归):\n";
276  tree_original.inOrder(out);
277  out << "\n中序遍历(非递归):\n";
278  tree_original.inOrder_loop(out);
279  out << "\n后序遍历(递归):\n";
280  tree_original.postOrder(out);
281  out << "\n后序遍历(非递归):\n";
282  tree_original.postOrder_loop(out);
283  out << "\n层次遍历:\n";
284  tree_original.levelOrder(out);
285  out << "\n层次打印(调用lchild(), rchild(), root()等API):\n";
286  Tree::printBinaryTree(tree_original, flag, out);
287 }
Tree::binaryTree::swaplr
void swaplr()
交换左右子树
Definition: binaryTree.hh:404
Tree::binaryTree::isFullBinaryTree
bool isFullBinaryTree() const
是否满二叉树
Definition: binaryTree.hh:699
Tree::binaryTree::delRight
void delRight(const value_type &x)
删除右subtree
Definition: binaryTree.hh:1041
GenTreeData
static bool GenTreeData(const char *_file_path="./test0.txt", const char *empty_flag="@")
生成一个文件,内容是一棵二叉树的层次遍历
Definition: ch6_6.cc:205
Tree::binaryTree::inOrder_loop
void inOrder_loop(std::ostream &out=std::cout) const
中序遍历(非递归版本)
Definition: binaryTree.hh:848
print_test_result
static void print_test_result(const Tree::binaryTree< T, Comparator > &tree_original, const typename Tree::binaryTree< T, Comparator >::value_type &flag, std::ostream &out=std::cout)
(测试用)将二叉树类的多种方法的输出插到输出流
Definition: ch6_1.cc:175
Tree::binaryTree::value_type
T value_type
类型别名定义
Definition: binaryTree.hh:108
Tree::binaryTree::preOrder_loop
void preOrder_loop(std::ostream &out=std::cout) const
前序遍历(非递归版本)
Definition: binaryTree.hh:769
data_file_name
const std::string data_file_name("ch6_6.result")
保存测试数据的文件名
Tree::binaryTree::isCompleteTree
bool isCompleteTree() const
返回是否完全二叉树
Definition: binaryTree.hh:711
Tree::binaryTree::height_loop
size_type height_loop() const
返回二叉树的高度(非递归版本)
Definition: binaryTree.hh:1201
Tree::binaryTree::size
size_type size() const
返回二叉树的结点数(递归版本)
Definition: binaryTree.hh:1312
Tree::binaryTree::levelOrder
void levelOrder(std::ostream &out=std::cout) const
层次遍历
Definition: binaryTree.hh:990
Tree::binaryTree::inOrder
void inOrder(std::ostream &out=std::cout) const
中序遍历(递归版本)
Definition: binaryTree.hh:906
Tree::binaryTree::size_loop
size_type size_loop() const
返回二叉树的结点数(非递归版本)
Definition: binaryTree.hh:1318
Tree::binaryTree::height
size_type height() const
返回二叉树的高度(递归版本)
Definition: binaryTree.hh:1195
Tree::binaryTree::postOrder_loop
void postOrder_loop(std::ostream &out=std::cout) const
后序遍历(非递归版本)
Definition: binaryTree.hh:923
main
int main(int argc, char const *argv[])
Definition: ch6_6.cc:51
Tree::binaryTree::delLeft
void delLeft(const value_type &x)
删除左subtree
Definition: binaryTree.hh:1031
Tree::binaryTree::postOrder
void postOrder(std::ostream &out=std::cout) const
后序遍历(递归版本)
Definition: binaryTree.hh:984
Tree::binaryTree::createTree
void createTree(const value_type &flag=value_type{}, std::istream &in=std::cin)
Create a Tree object.
Definition: binaryTree.hh:1324
Tree::binaryTree::preOrder
void preOrder(std::ostream &out=std::cout) const
前序遍历(递归版本)
Definition: binaryTree.hh:831
binaryTree.hh
Tree::binaryTree
用二叉链表实现的二叉树类
Definition: binaryTree.hh:53
Tree::binaryTree::CountDegreeTwo
size_type CountDegreeTwo() const
统计树中度为2的结点的个数
Definition: binaryTree.hh:409
Tree::printBinaryTree
void printBinaryTree(const binaryTree< T, Comparator > &bin_tree, const typename binaryTree< T, Comparator >::value_type &flag, std::ostream &out=std::cout)
输出一棵二叉树
Definition: binaryTree.hh:1426