1. 二叉树结构体。
struct BinaryTreeNode
{
char m_cValue;
BinaryTreeNode * m_pLeft;
BinaryTreeNode * m_pRight;
};
typedef BinaryTreeNode* BiTree;
2. 先序创建二叉树。
void CreateBTree(BiTree &T) //前序顺序创建二叉树, 如果不加这个引用&,指针出来后就没有了。。。。。。。
{
char c;
cin >> c;
if (c == '#')
T = nullptr;
else
{
T = new BinaryTreeNode;
T->m_cValue = c;
CreateBTree(T->m_pLeft);
CreateBTree(T->m_pRight);
}
}
3. 先序中序后序,递归遍历二叉树。
void PreTraverse(BiTree T)
{
if (T)
{
cout << T->m_cValue << " ";
PreTraverse(T->m_pLeft);
PreTraverse(T->m_pRight);
}
}
void MidTraverse(BiTree T)
{
if (T)
{
MidTraverse(T->m_pLeft);
cout << T->m_cValue << " ";
MidTraverse(T->m_pRight);
}
}
void PostTraverse(BiTree T)
{
if (T)
{
PostTraverse(T->m_pLeft);
PostTraverse(T->m_pRight);
cout << T->m_cValue << " ";
}
}
4. 先序非递归遍历二叉树。
void PreTraverseNoRecur(BiTree T)
{
if (T)
{
stack<BinaryTreeNode *> m_stack;
m_stack.push(T);
BinaryTreeNode * pNode = nullptr;
while( !m_stack.empty() )
{
pNode = m_stack.top();
m_stack.pop();
cout << pNode->m_cValue << " ";
if (pNode->m_pRight)
m_stack.push(pNode->m_pRight);
if (pNode->m_pLeft)
m_stack.push(pNode->m_pLeft);
}
}
}
5. 中序非递归遍历二叉树。
void MidTraverseNoRecur(BiTree T)
{
if (T==nullptr)
return;
stack<BiTree> s1;
BinaryTreeNode * pNode = T;
while (pNode || !s1.empty())
{
if(pNode)
{
s1.push(pNode);
pNode = pNode->m_pLeft;
}
else //这里的栈是没有push的
{
pNode = s1.top();
cout << pNode->m_cValue << " ";
s1.pop();
pNode = pNode->m_pRight;
}
}
}
6. 后序非递归遍历二叉树。
void PostTraverseNoRecur(BiTree T)
{
if(T == nullptr)
return;
stack<BiTree> s1;
vector<char> v1;
s1.push(T);
BinaryTreeNode *pNode = nullptr;
while (!s1.empty())
{
pNode = s1.top();
s1.pop();
v1.insert(v1.begin(), pNode->m_cValue); //这是指每次都在这个位置插入。
if (pNode->m_pLeft)
s1.push(pNode->m_pLeft);
if (pNode->m_pRight)
s1.push(pNode->m_pRight);
}
for (int ii=0; ii<v1.size(); ++ii)
cout << v1[ii] << " ";
}
方法二
void PostTraverTree(BiTree& pHead)
{
if (pHead == nullptr)
return;
stack<BiTree> stack1;
stack<BiTree> stack2;
BiTree pNode = pHead;
stack1.push(pNode);
while (!stack1.empty())
{
pNode = stack1.top();
stack1.pop();
stack2.push(pNode);
if (pNode->m_pLeft)
stack1.push(pNode->m_pLeft);
if (pNode->m_pRight)
stack1.push(pNode->m_pRight);
}
while (!stack2.empty())
{
cout << stack2.top << " ";
stack2.pop();
}
return;
}
7. 层序遍历二叉树(与先序遍历只是用的容器不同,语句几乎一样)。
void LayerTraverseBST(BiTree T)
{
if (T == nullptr)
return;
deque<BiTree> q1;
q1.push_back(T);
BinaryTreeNode *pNode = nullptr;
while (! q1.empty() )
{
pNode = q1.front();
q1.pop_front();
cout << pNode->m_cValue << " ";
if (pNode->m_pLeft)
q1.push_back(pNode->m_pLeft);
if (pNode->m_pRight)
q1.push_back(pNode->m_pRight);
}
}
8. 二叉树的重建。给出前序与中序遍历的结果,重建二叉树。
int GetPos(string inOrder, char c)
{
if (inOrder.empty())
return -1;
int ret = -1;
for (int ii=0; ii!=inOrder.size(); ++ii)
{
if (inOrder[ii] == c)
ret = ii;
}
return ret;
}
void ReBuild(string preOrder, string inOrder, BiTree &T)
{
if (preOrder.empty() )
{
T = nullptr;
return ;
}
if ( (preOrder.size() != inOrder.size() ))
{
cout << "Invalid input. " << endl;
return ;
}
T = new BinaryTreeNode;
T->m_cValue = preOrder[0];
if (preOrder.size() == 1)
{
T->m_pLeft = nullptr;
T->m_pRight = nullptr;
return ;
}
int pos = GetPos(inOrder, preOrder[0]);
if (pos == 0)
{
T->m_pLeft = nullptr;
string preTmp2 = preOrder.substr(pos+1, preOrder.size());
string inTmp2 = inOrder.substr(pos+1, inOrder.size());
ReBuild(preTmp2, inTmp2, T->m_pRight);
}
else if (pos == inOrder.size()-1)
{
T->m_pRight = nullptr;
string preTmp2 = preOrder.substr(1, pos);
string inTmp2 = inOrder.substr(0, pos);
ReBuild(preTmp2, inTmp2, T->m_pLeft);
}
else if (pos>0 && pos<inOrder.size()-1)
{
string preTmp1 = preOrder.substr(1, pos);
string preTmp2 = preOrder.substr(pos+1, preOrder.size());
string inTmp1 = inOrder.substr(0, pos);
string inTmp2 = inOrder.substr(pos+1, inOrder.size());
ReBuild(preTmp1, inTmp1, T->m_pLeft);
ReBuild(preTmp2, inTmp2, T->m_pRight);
}
else
{
cout << "Cannot rebuild a binary tree ." << endl;
}
return ;
}
二叉树的重建,使用STL容器。
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
int GetPos(vector<int> v1, int val)
{
if (v1.empty())
return -1;
int pos = -1;
for (int ii=0; ii != v1.size(); ++ii)
{
if (v1[ii] == val)
pos = ii;
}
return pos;
}
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin)
{
if (pre.size() != vin.size())
return nullptr;
if (pre.empty() && vin.empty())
return nullptr;
int val = pre[0];
int pos = GetPos(vin, val);
if (pos == -1)
return nullptr;
vector<int> preLeft(pre.begin()+1, pre.begin()+pos+1);
vector<int> preRight(pre.begin()+pos+1, pre.end());
vector<int> vinLeft(vin.begin(), vin.begin()+pos);
vector<int> vinRight(vin.begin()+pos+1, vin.end());
TreeNode * root = new TreeNode(val);
root->left = reConstructBinaryTree(preLeft, vinLeft);
root->right = reConstructBinaryTree(preRight, vinRight);
return root;
}
9. 获取二叉树的深度。
int GetTreeDepth(BiTree T)
{
if (T == nullptr)
return 0;
int lDepth = 0, rDepth = 0;
if (T->m_pLeft)
lDepth = GetTreeDepth(T->m_pLeft);
if (T->m_pRight)
rDepth = GetTreeDepth(T->m_pRight);
return ( (lDepth>rDepth)?lDepth:rDepth ) + 1;
}
10. 求二叉树相距最大的两个节点的距离。(这里距离指的是边的个数)【注:方法有待改进】
void GetBiTreeLagPath(BiTree T, int &maxLen)
{
if (T == nullptr)
return ;
int lDepth = GetTreeDepth(T->m_pLeft);
int rDepth = GetTreeDepth(T->m_pRight);
maxLen = max( (lDepth + rDepth), maxLen);
GetBiTreeLagPath (T->m_pLeft, maxLen);
GetBiTreeLagPath (T->m_pRight, maxLen);
return ;
}
11. 求二叉树宽度。
int GetBiTreeWidth(BiTree T)
{
if (T == nullptr)
return 0;
queue<BiTree> Q1;
Q1.push(T);
BiTree pNode = new BinaryTreeNode;
int maxWidth = 1;
int frontWidth = 1;
int curWidth = 0;
while ( !Q1.empty() )
{
pNode = Q1.front();
Q1.pop();
if (pNode->m_pLeft)
{
Q1.push(pNode->m_pLeft);
++curWidth;
}
if (pNode->m_pRight)
{
Q1.push(pNode->m_pRight);
++curWidth;
}
if ( ! --frontWidth )
{
frontWidth = curWidth;
maxWidth = (maxWidth>curWidth)? maxWidth:curWidth;
curWidth = 0;
}
}
return maxWidth;
}
12. 树的子结构。(判断B是不是A的子结构)
bool IsTreeEqual(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
if (pRoot1 == nullptr && pRoot2 == nullptr)
return true;
else if(pRoot1 == nullptr && pRoot2 != nullptr)
return false;
else if(pRoot1 != nullptr && pRoot2 == nullptr)
return true;
bool ret = (pRoot1->val == pRoot2->val);
if ( !ret )
return false;
bool lRet = IsTreeEqual(pRoot1->left, pRoot2->left);
bool rRet = IsTreeEqual(pRoot1->right, pRoot2->right);
return (lRet && rRet);
}
bool HasSubtree(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
bool ret = false;
if (pRoot1 != nullptr && pRoot2 != nullptr)
{
ret = IsTreeEqual(pRoot1, pRoot2);
if ( !ret )
ret = HasSubtree(pRoot1->left, pRoot2);
if ( !ret )
ret = HasSubtree(pRoot1->right, pRoot2);
}
return ret;
}
13. 二叉树镜像。
struct TreeNode
{
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
void Mirror(TreeNode *pRoot)
{
if (pRoot == nullptr)
return ;
swap(pRoot->left, pRoot->right);
if (pRoot->left)
Mirror(pRoot->left);
if (pRoot->right)
Mirror(pRoot->right);
return;
}
14、判断一组数是否为二叉搜索树的后序遍历序列。
bool JudgePostOrderSeq(vector<int> &sequence, int sIdx, int eIdx, int root)
{
if (sIdx == eIdx && sequence[sIdx]==root)
return true;
else if(sIdx == eIdx && sequence[sIdx]!=root)
return false;
int ret = false;
int pos = 0;
for (int ii=0; ii<sequence.size(); ++ii)
{
if (sequence[ii] >= root)
{
pos = ii;break;
}
}
for (int ii=pos; ii<=eIdx; ++ii)
{
if (sequence[ii]<root)
{
return false;
}
}
bool lRet = true, rRet = true;
if (pos >= 1)
lRet = JudgePostOrderSeq(sequence, 0, pos-1, sequence[pos-1]);
if (pos <= eIdx-1)
rRet = JudgePostOrderSeq(sequence, pos, eIdx-1, sequence[eIdx-1]);
ret = rRet && lRet;
return ret;
}
bool VerifySquenceOfBST(vector<int> &sequence)
{
if (sequence.empty())
return false;
if ( sequence.size() == 1 )
return true;
bool ret = JudgePostOrderSeq(sequence, 0, sequence.size()-1, sequence[sequence.size()-1]);
return ret;
}
15. 求二叉树所有和为某值的路径。
void DFSFindPath(TreeNode* root, int tarNum, int lastSum, vector<vector<int> > &v1, vector<int> &tmp)
{
/*
深度优先遍历算法:看起来形式比较像先序遍历。
用到的思想是:一直向下递归,直到叶子节点,期间所有的节点都保存下来,然后判断这条路径是否是需要的
如果是,整条路径保存;如果不是,依次弹出最后面的节点,并寻找最近的不同路径压入。
*/
int rootValue = root->val;
tmp.push_back(rootValue); // 用以保存单条路径。
if (lastSum+rootValue == tarNum && !root->left && !root->right)
v1.push_back(tmp); // 二维数组添加可以一次添加一维的数据,这样就可以将路径整体存下来!
else
{
if (root->left)
DFSFindPath(root->left, tarNum, lastSum+rootValue, v1, tmp) ;
if (root->right)
DFSFindPath(root->right, tarNum, lastSum+rootValue, v1, tmp) ;
}
tmp.pop_back();
return ;
}
vector<vector<int> > FindPath(TreeNode* root,int expectNumber)
{
if (root == nullptr)
return vector<vector<int> >();
vector<vector<int> > v1;
vector<int> tmp;
DFSFindPath(root, expectNumber, 0, v1, tmp);
return v1;
}
16. 将二叉搜索树转为单调排序的链表。
// -----------------实现二叉树转链表--------中序遍历+保存前节点的指针 ------------
TreeNode* Convert(TreeNode* pRootOfTree)
{
if (pRootOfTree==nullptr)
return nullptr;
int flag = 1;
stack<TreeNode*> s1;
TreeNode* pHead = nullptr;
TreeNode* pLastNode = nullptr;
TreeNode * pCurNode = pRootOfTree;
while (pCurNode || !s1.empty())
{
if(pCurNode)
{
s1.push(pCurNode);
pCurNode = pCurNode->left;
}
else
{
pCurNode = s1.top();
if (flag)
{
pHead = pCurNode;
flag = 0;
}
pCurNode->left = pLastNode;
if ( pLastNode )
pLastNode->right = pCurNode;
pLastNode = pCurNode;
pCurNode = pCurNode->right;
s1.pop();
}
}
return pHead;
}
递归版本
void InOrderConvert(TreeNode* pRootOfTree, TreeNode* &pLast)
{
if (pRootOfTree == nullptr)
return;
if (pRootOfTree)
InOrderConvert(pRootOfTree->left, pLast);
pRootOfTree->left = pLast;
if (pLast)
pLast->right = pRootOfTree;
pLast = pRootOfTree;
InOrderConvert(pRootOfTree->right, pLast);
return;
}
TreeNode* Convert(TreeNode* pRootOfTree)
{
if (pRootOfTree==nullptr)
return nullptr;
TreeNode* pLast = nullptr;
InOrderConvert( pRootOfTree, pLast);
while(pLast->left)
pLast = pLast->left;
return pLast;
}
17. 判断二叉树是否为平衡二叉树。
// -------方法一:从上到下遍历,每个节点遍历多次-----------
int TreeDepth(TreeNode* pRoot)
{
if (pRoot == nullptr)
return 0;
int lefDepth = TreeDepth(pRoot->left);
int rigDepth = TreeDepth(pRoot->right);
return (lefDepth>rigDepth)?lefDepth+1 : rigDepth+1;
}
bool IsBalanced_Solution(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
int lefDepth = TreeDepth(pRoot->left);
int rigDepth = TreeDepth(pRoot->right);
bool ret = ( abs(lefDepth-rigDepth) <= 1 );
return ret && (IsBalanced_Solution(pRoot->left)) && (IsBalanced_Solution(pRoot->right));
}
// -------方法二:从下往上判断,各个节点只遍历一遍,但是需要加一个全局变量--------
bool JudgeRet = true;
int TreeDepth(TreeNode* pRoot)
{
if (pRoot == nullptr)
return 0;
int lefDepth = TreeDepth(pRoot->left);
int rigDepth = TreeDepth(pRoot->right);
if ( abs(lefDepth-rigDepth) > 1)
JudgeRet = false;
return (lefDepth>rigDepth)?lefDepth+1 : rigDepth+1;
}
bool IsBalanced_Solution(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
TreeDepth(pRoot);
return JudgeRet;
}
// -------方法三:每个节点至多遍历一次+剪枝策略-------------
int Max(int a, int b)
{
return (a>b)?a:b;
}
int TreeDepth(TreeNode* pRoot)
{
if (pRoot == nullptr)
return 0;
int lefDepth = TreeDepth(pRoot->left);
if (lefDepth == -1)
return -1; // 剪枝策略
int rigDepth = TreeDepth(pRoot->right);
if (rigDepth == -1)
return -1;
return abs(lefDepth-rigDepth) > 1 ? -1 : Max(lefDepth, rigDepth)+1;
}
bool IsBalanced_Solution(TreeNode* pRoot)
{
if (pRoot == nullptr)
return true;
return TreeDepth(pRoot) != -1;
}
18. 主函数。
int main(int argc, char **argv)
{
BiTree T;
CreateBTree(T);
cout << "先序递归遍历: "; PreTraverse(T);
cout << endl;
cout << "中序递归遍历: "; MidTraverse(T);
cout << endl;
cout << "后序递归遍历: "; PostTraverse(T);
cout << endl;
cout << "先序非递归遍历:"; PreTraverseNoRecur(T);
cout << endl;
cout << "中序非递归遍历:"; MidTraverseNoRecur(T);
cout << endl;
cout << "后序非递归遍历:"; PostTraverseNoRecur(T);
cout << endl;
cout << "层序遍历: "; LayerTraverseBST(T);
////Print(T);
//cout << endl;
//PrintZigzag(T);
getchar();getchar();
return 0;
}
19. 测试结果。