我编写了C++代码:
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
template <class T>
class TreeNode {
public:
T data;
TreeNode<T> *left, *right;
TreeNode() {
data = {};
left = right = NULL;
}
TreeNode(T data) {
this->data = data;
}
};
template <class T>
class BinaryTree {
public:
TreeNode<T> *root;
vector<T> _largestIndependentSet(TreeNode<T> *root) {
static unordered_map< TreeNode<T>*, vector<T> > table;
if(!root)
return {};
if(table.find(root) != table.end())
return table[root];
vector<T> lis = {}, lis_left = {}, lis_right = {},
lis_nrl_left = {}, lis_nrl_right = {}, lis_nrr_left = {}, lis_nrr_right = {};
// Leaf
if(!root->left && !root->right) {
lis.push_back(root->data);
}else{
if(root->left){
lis_left = _largestIndependentSet(root->left);
lis_nrl_left = _largestIndependentSet(root->left->left);
lis_nrl_right = _largestIndependentSet(root->left->right);
}
if(root->right){
lis_right = _largestIndependentSet(root->right);
lis_nrr_left = _largestIndependentSet(root->right->left);
lis_nrr_right = _largestIndependentSet(root->right->right);
}
if( lis_left.size() + lis_right.size() >
lis_nrl_left.size() + lis_nrl_right.size() +
lis_nrr_left.size() + lis_nrr_right.size() + 1 ){ // don't keep root
lis.insert(lis.end(), lis_left.begin(), lis_left.end());
lis.insert(lis.end(), lis_right.begin(), lis_right.end());
}
else {
lis.insert(lis.end(), lis_nrl_left.begin(), lis_nrl_left.end());
lis.insert(lis.end(), lis_nrl_right.begin(), lis_nrl_right.end());
lis.insert(lis.end(), lis_nrr_left.begin(), lis_nrr_left.end());
lis.insert(lis.end(), lis_nrr_right.begin(), lis_nrr_right.end());
lis.push_back(root->data);
}
}
cout<<"Calculated Results for: "<<root->data<<": ";
for_each(lis.begin(), lis.end(), [](T data) {
cout<<data<<" ";
});
cout<<"\n";
table[root] = lis;
return table[root];
}
void largestIndependentSet() {
vector<T> lis = _largestIndependentSet(this->root);
for_each(lis.begin(), lis.end(), [](T data) {
cout<<data<<" ";
});
}
};
int main() {
BinaryTree<int> bt;
TreeNode<int> *root = new TreeNode<int>(10);
root->left = new TreeNode<int>(7);
root->right = new TreeNode<int>(15);
root->left->left = new TreeNode<int>(9);
root->left->right = new TreeNode<int>(12);
root->right->left = new TreeNode<int>(6);
root->right->right = new TreeNode<int>(11);
root->left->left->left = new TreeNode<int>(20);
root->right->left->right = new TreeNode<int>(5);
root->left->left->left->left = new TreeNode<int>(22);
root->left->left->left->right = new TreeNode<int>(21);
root->right->left->right->left = new TreeNode<int>(4);
root->right->left->right->right = new TreeNode<int>(3);
bt.root = root;
bt.largestIndependentSet();
return 0;
}我在Cygwin上使用Cygwin编译它
g++ binary_tree.cpp -std=c++11问题是在递归函数_largestIndependentSet()完成后,最后一次打印给了我正确的答案。但在此之后,我得到了一个错误:中止了(内核转储),而largestIndependentSet()中的打印没有执行。
这令人费解,因为我的逻辑似乎是正确的。是什么引起的?
PS:如果我用c++14标志编译它,它会运行很好的o_O:
g++ binary_tree.cpp -std=c++14发布于 2016-07-26 17:09:29
在发布的代码中不会出现两个以上的主要问题。
T-value构造函数的子指针值。largestIndependentSet()的返回值前者是常见的,特别是对于C++中的初学者。确保您没有留下任何不确定的值。在这种情况下,left和right在TreeNode(T value)构造函数中是不确定的。
后者是非常重要的。函数largestIndependentSet()声称它返回了一个向量,但实际上根本没有return。同样,这也会调用未定义的行为。从这里我可以推测,但要注意的是:推测:
推测:编译器愉快地生成了代码,它最终将您未设置的激活堆栈中发生的任何事情作为一个std::vector<T>来处理。当然,这是不确定的胡言乱语,因为您从来没有返回一个实际的对象。但是std::vector<>的非虚拟析构函数的调用当然不知道这一点,在这样做的过程中,不管发生了什么事情,它都把它认为是其成员变量的东西作为有效数据来处理,而在现实中,它却完全不是。它的缺点是:获取随机内存,将std::vector<>析构函数代码指向它,对代码撒谎,并说内存持有一个有效的std::vector<>对象,然后释放析构函数。
为什么编译器没有出错。嗯,通常在C或C++中,做一些不明智的事情并不是一个错误。编译器希望您对所做的事情有足够的了解,在这种情况下,没有出现任何语言冲突,因此它给您带来了疑问。然而..。在大多数现代编译器(icc、gcc、clang和msvc )上,将编译器警告级别提高到迂腐的高度,就会警告您丢失的返回值。这些警告存在是有原因的,我强烈支持将它们打开并将它们作为错误处理(也是一个编译器选项)。
https://stackoverflow.com/questions/38593288
复制相似问题