第四题
题目:输入一个整数和一棵二元树。
从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。
例如 输入整数22和如下二元树
10
/ \
5 12
/ \
4 7
则打印出两条路径:10, 12和10, 5, 7。
分析:(本人拙见)
这道题目主要考察的是二叉树的非递归周游,因此很容易想到使用栈来作为数据遍历的时候的节点存储。每次压入栈数据的时候判断是否达到了叶节点且栈中元素之和
满足给定值,如果满足上面两个条件,为真,打印栈中的元素。继续遍历。
首先是树的构建,为了方便这里使用了广度优先的插入算法,跟这道题木有太大关系。
然后就是对于二叉树的非递归周游。
#include<iostream>
#include<queue>
#include<stack>
using namespace std;
typedef struct NodeBinaryTree
{
int value;
NodeBinaryTree * nodeLeft;
NodeBinaryTree * nodeRight;
}NodeBinaryTree;
class BinaryTree
{
private:
NodeBinaryTree * root;
stack<int> Path;
public:
BinaryTree();
//~BSTree(); 这个地方需要递归delete所有节点
NodeBinaryTree * Root(){return root;}
void addNodeBSTree(const int item);
void inOrder(NodeBinaryTree * root);
void inOrderStack(const int item);
};
BinaryTree::BinaryTree()
{
root = NULL;
}
void BinaryTree::addNodeBSTree(const int item)
{
//这个地方写代码的时候使用了广度优先的插入节点,当时不知道怎么想的就写了这个
//与本题关系不大,可以直接忽略
if(NULL==root)
{
NodeBinaryTree * node2add = new NodeBinaryTree();
node2add->value = item;
node2add->nodeLeft = NULL;
node2add->nodeRight = NULL;
root = node2add;
}
else
{
//BinaryTree的节点的插入采用的是广度优先的插入方式,因此这里我们定义了一个队列,直接采用了STL里面的队列
using std::queue;
queue<NodeBinaryTree *> aQueue;
NodeBinaryTree * pointer = root;
if(pointer)
aQueue.push(pointer);
while(!aQueue.empty())
{
pointer = aQueue.front();
aQueue.pop();
if(NULL!=pointer->nodeLeft && NULL!=pointer->nodeRight){//为什么书上这个地方有括号
aQueue.push(pointer->nodeLeft);
aQueue.push(pointer->nodeRight);
}
else if(NULL!=pointer->nodeLeft && NULL==pointer->nodeRight)
{
//找到当前的没有右子树的点,将待加入的点插入的右子树
NodeBinaryTree * node2add = new NodeBinaryTree();
pointer->nodeRight = node2add;
node2add->value = item;
node2add->nodeLeft = NULL;
node2add->nodeRight = NULL;
break;
}
else //说明是左子树是NULL
{
NodeBinaryTree * node2add = new NodeBinaryTree();
pointer->nodeLeft = node2add;
node2add->value = item;
node2add->nodeLeft = NULL;
node2add->nodeRight = NULL;
break;
}
}
}
}
void BinaryTree::inOrder(NodeBinaryTree * root)
{
if(NULL!=root)
{
inOrder(root->nodeLeft);
cout<<root->value<<" ";
inOrder(root->nodeRight);
}
}
void BinaryTree::inOrderStack(const int item)
{
cout<<"the expected sum of the path is "<<item<<endl;
NodeBinaryTree * root = this->root;
//非递归周游二叉树
enum Tags{Left,Right};
struct StackElement
{
NodeBinaryTree * pointer;
Tags tag;
};
StackElement element;
StackElement elementCopy;
stack<StackElement> aStack;
stack<StackElement> aCopyStack;
NodeBinaryTree * pointer;
if(NULL==root){return;}
else pointer = root;
int sumValue = 0;
int nodeValue;
while(true){
while(NULL!=pointer)
{
element.pointer = pointer;
element.tag = Left;
aStack.push(element);
sumValue = sumValue + element.pointer->value;
pointer = pointer->nodeLeft;
}
element = aStack.top();
if(element.tag==Right && NULL==element.pointer->nodeLeft&& NULL== element.pointer->nodeRight && item==sumValue)
{
//因为每次考虑Tag的时候考虑了right和left 所以要使不使用element.tag==Right判断条件会打印两遍
//若找到了路径
//输出栈中的元素 然后再把栈重新组织成原来的样子
while(!aStack.empty()){
elementCopy = aStack.top();
aStack.pop();
aCopyStack.push(elementCopy);
}
while(!aCopyStack.empty()){
elementCopy = aCopyStack.top();
aCopyStack.pop();
aStack.push(elementCopy);
cout<<elementCopy.pointer->value<<" ";
}
cout<<endl;
}
aStack.pop();
sumValue = sumValue - element.pointer->value;
pointer = element.pointer;
//从右子树回来
while(element.tag==Right){
if(aStack.empty()) return;
else {
element = aStack.top();
aStack.pop();
sumValue = sumValue - element.pointer->value;
pointer = element.pointer;
}
}
//从左子树回来
element.tag = Right;
aStack.push(element);
sumValue = sumValue + element.pointer->value;
pointer = pointer->nodeRight;
}
}
int main()
{
BinaryTree a;
a.addNodeBSTree(1);
a.addNodeBSTree(2);
a.addNodeBSTree(3);
a.addNodeBSTree(4);
a.addNodeBSTree(6);
a.addNodeBSTree(5);
a.addNodeBSTree(7);
NodeBinaryTree * head = a.Root();
//test inorder
a.inOrder(head);
cout<<endl;
a.inOrderStack(9);
return 0;
}