二叉樹面試題
阿新 • • 發佈:2019-02-14
1. 前序/中序/後序遍歷(非遞迴)
前序
void PrevOrderNonR()
{
stack<Node*> s;
Node* cur = _root;
while (cur || !s.empty())
{
while (cur)
{
cout<<cur->_data<<" ";
s.push(cur);
cur = cur->_left;
}
// top從棧取出來表示這個節點的左子樹訪問過了
// 剩餘右子樹還沒訪問,迴圈子問題訪問右樹
Node* top = s.top();
s.pop();
// 子問題的方式訪問右樹
cur = top->_right;
}
cout<<endl;
}
中序
void InOrder()
{
_InOrder(_root);
cout<<endl;
}
void InOrderNonR()
{
Node* cur = _root;
stack <Node*> s;
while (cur || !s.empty())
{
while (cur)
{
s.push(cur);
cur = cur->_left;
}
Node* top = s.top();
s.pop();
cout<<top->_data<<" ";
// 子問題
cur = top->_right;
}
}
後序
void PostOrderNonR()
{
Node* cur = _root;
stack<Node*> s;
Node* prev = NULL;
while (cur || !s.empty())
{
while (cur)
{
s.push(cur);
cur = cur->_left;
}
Node* front = s.top();
if (front->_right == NULL || front->_right == prev)
{
cout<<front->_data<<" ";
prev = front;
s.pop();
}
else
{
// 子問題
cur = front->_right;
}
}
cout<<endl;
}
判斷一棵二叉樹是否是平衡二叉樹
//判斷一棵樹是不是平衡二叉樹
bool IsBalancedTree_old(Node* root)
{
if (root == NULL)
return true;
int lenleft = BinaryTreeDepth(root->Lchild);//每往下一層,計算一次深度,時間複雜度N^2
int lenright = BinaryTreeDepth(root->Rchild);
int temp = lenleft - lenright;
if (temp >1 || temp < -1)
return false;
return IsBalancedTree_old(root->Lchild) && IsBalancedTree_old(root->Rchild);//滿足條件,計算它的下一層的左右子樹
}
//判斷是否為平衡二叉樹(優化)
bool _IsBlancedtree_new(Node* root,int* pDepth)
{
if (root == NULL)
{
*pDepth = 0;
return true;
}
int left, right;
if (_IsBlancedtree_new(root->Lchild, &left) && _IsBlancedtree_new(root->Rchild, &right))//後序遍歷思想
{
int temp = left - right;
if (temp <= 1 && temp >= -1)//拿到深度值
{
*pDepth = left > right ? left + 1 : right + 1;
return true;
}
}
return false;
}
bool IsBlancedTree_new(Node* root)
{
int pDepth;
bool tag = _IsBlancedtree_new(root, &pDepth);
return tag;
}
求二叉樹的映象
//求一顆二叉樹的映象 :兩棵樹左右對稱
void Mirror(Node* root)
{
if (root == NULL)
return ;
if (root->Lchild == NULL && root->Rchild == NULL)
return ;
Node* temp = root->Lchild;//交換左右子樹
root->Lchild = root->Rchild;
root->Rchild = temp;
if (root->Lchild)//遞迴下去
MirrorRecursively(root->Lchild);
if (root->Rchild)
MirrorRecursively(root->Rchild);
}
求兩個節點的最近公共祖先
bool GetNodePath(Node* root, Node* x, stack<Node*>& paths)
{
if (root == NULL)
return false;
paths.push(root);
if (root == x)
return true;
if(GetNodePath(root->_left, x, paths))
return true;
if (GetNodePath(root->_right, x, paths))
return true;
paths.pop();
return false;
}
Node* GetCommonAncestor(Node* root, Node* x1, Node* x2)
{
assert(x1 && x2);
stack<Node*> paths1;
stack<Node*> paths2;
if (GetNodePath(root, x1, paths1) == false)
return NULL;
if (GetNodePath(root, x2, paths2) == false)
return NULL;
while(paths1.size() != paths2.size())
{
if (paths1.size() > paths2.size())
paths1.pop();
else
paths2.pop();
}
while (1)
{
if (paths1.top() == paths2.top())
{
return paths1.top();
}
paths1.pop();
paths2.pop();
}
}
Node * FindLCA(Node * node, Node * target1, Node * target2)
{
if (node == nullptr)
return nullptr;
if (node == target1 || node == target2)
return node;
Node * left = FindLCA(node->left, target1, target2);
Node * right = FindLCA(node->right, target1, target2);
if (left && right) // 分別在左右子樹
return node;
return left ? left : right; // 都在左子樹或右子樹
}
求二叉樹中最遠的兩個節點的距離
int _FindMaxLen(Node* root, int& maxLen)
{
if (root == NULL)
return 0;
int l = _FindMaxLen(root->_left, maxLen);
int r = _FindMaxLen(root->_right, maxLen);
if (l+r > maxLen)
{
maxLen = l+r;
}
return l > r ? l+1 : r+1;
}
int FindMaxLen(Node* root)
{
int max = 0;
_FindMaxLen(root, max);
return max;
}
//void _FindMaxLen(Node* root, int& maxLen)
//{
// if (root == NULL)
// return;
//
// int l = Height(root->_left);
// int r = Height(root->_right);
// if (l + r > manLen)
// manLen = l + r;
// FindMaxLen(root->_left);
// FindMaxLen(root->_right);
//}
由前序遍歷和中序遍歷重建二叉樹(如:前序序列:1 2 3 4 5 6 - 中序序列:3 2 4 1 6 5)
Node* ReBulidTree(char*& prev, char* inStart, char* inEnd)
{
if (*prev=='\0')
return NULL;
Node* root = new Node(*prev);
if (inStart == inEnd)
return root;
char* pos = inStart;
while (pos <= inEnd)
{
if (*pos == *prev)
break;
++pos;
}
assert(pos <= inEnd);
// [inStart,pos-1]
// [pos+1,inEnd]
root->_left = ReBulidTree(++prev, inStart, pos-1);
root->_right = ReBulidTree(++prev, pos+1, inEnd);
return root;
}
判斷一棵樹是否是完全二叉樹
bool IsCompleteTree(Node* root)
{
if (root == NULL)
return true;
bool tag = true;
queue<Node*> q;
q.push(root);
while (!q.empty())
{
Node* front = q.front();
q.pop();
if (front->_left)
{
if (tag == false)
return false;
q.push(front->_left);
}
else
{
tag = false;
}
if (front->_right)
{
if (tag == false)
return false;
q.push(front->_right);
}
else
{
tag = false;
}
}
return true;
}
將二叉搜尋樹轉換成一個排序的雙向連結串列。要求不能建立任何新的結點,只能調整樹中結點指標的指向。
Node* ToSortList(Node* root)
{
Node* prev = NULL;
ToSortList(root, prev);
while (root && root->_left)
{
root = root->_left;
}
return root;
}
Node* _ToSortList(Node* cur, Node*& prev)
{
if (cur == NULL)
return;
_ToSortList(cur->_left, prev);
cur->_left = prev;
if (prev)
prev->_right = cur;
prev = cur;
_ToSortList(cur->_right, prev);
}
}