您的位置:首页 > 其它

二叉树精选

2015-11-01 23:10 225 查看
题目:输入两棵二叉树A和B,判断树B是不是A的子结构

递归判断:如果当前结点值相等,就判断左子树和右子树是否是子结构

[cpp]
view plaincopy

bool IsChildTree(Node * father, Node * son)
{
if(father == NULL && son == NULL)
return true;

if(father == NULL && son != NULL)
return false;

if(father != NULL && son == NULL)
return true;

if(father->data == son->data )
{
return IsChildTree(father->left, son->left) && IsChildTree(father->right, son->right);
}

if(IsChildTree(father->left, son))
return true;

if(IsChildTree(father->right, son))
return true;

return false;
}

题目:求二叉树中相距最远的两个节点之间的距离

求两节点的最远距离,实际就是求二叉树的直径。本问题可以转化为求“二叉树每个节点的左右子树高度和的最大值”。

[cpp]
view plaincopy

int TreeHeight(Node* root, int& max_distance)
{
if(root == NULL)
{
max_distance = 0;
return 0;
}

int left_height,right_height;

if(root->left)
left_height = TreeHeight(root->left,max_distance)+1;
else
left_height = 0;

if(root->right)
right_height = TreeHeight(root->right,max_distance)+1;
else
right_height = 0;

int distance = left_height + right_height;
if (max_distance < distance) max_distance = distance;

return (left_height > right_height ? left_height : right_height);
}

int TreeDiameter(Node* root)
{
int max_distance = 0;
if(root) TreeHeight(root, max_distance);
return max_distance;
}

题目:求二叉树中节点的最大距离:如果我们把二叉树看成一个图,父子节点之间的连线看成是双向的,定义“距离”为两节点之间边的个数。

[cpp]
view plaincopy

//结点的定义
typedef struct Node
{
Node * left;
Node * right;
int maxLeft;
int maxRight;
char chValue;
}Node,*pNode;

//最大距离
int maxLen = 0;

//寻找二叉树中节点的最大距离
void findMaxLength(Node* root)
{
if(root == NULL) return;

//如果左子树为空,则该节点左边最长距离为0
if(root->left == NULL) root->maxLeft = 0;

//如果右子树为空,则该节点右边最长距离为0
if(root->right == NULL) root->maxRight = 0;

//如果左子树不为空,递归寻找左边最长距离
if(root->left != NULL) findMaxLength(root->left);

//如果右子树不为空,递归寻找右边最长距离
if(root->right != NULL) findMaxLength(root->right);

//计算左子树最长节点距离
if(root->left != NULL)
{
int tempMax = 0;
if(root->left->maxLeft > root->left->maxRight)
tempMax = root->left->maxLeft;
else tempMax = root->left->maxRight;
root->maxLeft = tempMax+1;
}

//计算右子树最长节点距离
if(root->right != NULL)
{
int tempMax = 0;
if(root->right->maxLeft > root->right->maxRight)
tempMax = root->right->maxLeft;
else tempMax = root->right->maxRight;
root->maxRight = tempMax+1;
}

//更新最长距离
if(root->maxLeft+root->maxRight > maxLen)
maxLen = root->maxLeft+root->maxRight;
}

题目:重建二叉树:通过先序遍历和中序遍历的序列重建二叉树

[cpp]
view plaincopy

//通过先序遍历和中序遍历的序列重建二叉树
void ReBuild(char* pPreOrder,char* pInOrder,int nTreeLen,Node** pRoot)
{
//检查边界条件
if(pPreOrder == NULL || pInOrder == NULL)
return ;

//获得前序遍历的第一个节点
Node* temp = new Node;
temp->data = *pPreOrder;
temp->left = NULL;
temp->right = NULL;

//如果节点为空,把当前节点复制到根节点
if(*pRoot == NULL) *pRoot = temp;

//如果当前树长为1,那么已经是最后一个节点
if(nTreeLen == 1) return;

//寻找子树长度
char* pOrgInOrder = pInOrder;
char* pLeftEnd = pInOrder;
int nTempLen = 0;

//找到左子树的结尾
while(*pPreOrder != *pLeftEnd)
{
if(pPreOrder == NULL || pLeftEnd == NULL)
return;
//记录临时长度,以免溢出
nTempLen++;
if(nTempLen > nTreeLen) break;
pLeftEnd++;
}

//寻找左子树长度
int nLeftLen = (int)(pLeftEnd-pOrgInOrder);

//寻找右子树长度
int nRightLen = nTreeLen-nLeftLen-1;

//重建左子树
if(nLeftLen > 0)
ReBuild(pPreOrder+1,pInOrder,nLeftLen,&((*pRoot)->left));

//重建右子树
if(nRightLen > 0)
ReBuild(pPreOrder+nLeftLen+1,pInOrder+nLeftLen+1,nRightLen,&((*pRoot)->right));
}

题目:寻找最近公共祖先LCA(Lowest Common Ancestor)

[cpp]
view plaincopy

Node* getLCA(Node* root,Node* x,Node* y)
{
if(root == NULL) return NULL;
if(x == root || y == root) return root;
Node* pleft = getLCA(root->left,x,y);
Node* pright = getLCA(root->right,x,y);
if(pleft == NULL) return pright;
else if(pright == NULL)return pleft;
else return root;
}

分别得到根节点root到结点x的路径和到结点y的路径,再比较路径中第一个相同的结点,即是LCA

[cpp]
view plaincopy

//得到根节点pHead到pNode的路径
bool GetNodePath(Node* pHead, Node* pNode, std::list<Node*>& path)
{
if(pHead == pNode)
return true;

path.push_back(pHead);

bool found = false;

if(pHead->left != NULL)
found = GetNodePath(pHead->left, pNode, path);

if(!found && pHead->right)
found = GetNodePath(pHead->right, pNode, path);

if(!found)
path.pop_back();

return found;
}

题目:寻找二叉搜索树(BST)的最低公共祖先(LCA)

利用BST的性质:从根结点开始搜索,当第一次遇到当前结点的值介于两个给定的结点值之间时,这个当前结点就是要找的LCA

[cpp]
view plaincopy

Node* FindLCA(Node* root,int x, int y)
{
Node * t = root;
while(1)
{
if(t->data > x && t->data > y)
t = t->left;
else if(t->data < x && t->data < y)
t = t->right;
else return t;
}
}

题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果。如果是返回true,否则返回false。

例如输入5、7、6、9、11、10、8,由于这一整数序列是如下树的后序遍历结果,因此返回true。

8

/ \

6 10

/ \ / \

5 7 9 11

如果输入7、4、6、5,没有哪棵树的后序遍历的结果是这个序列,因此返回false。

分析:这是一道trilogy的笔试题,主要考查对二元查找树的理解。

在后续遍历得到的序列中,最后一个元素为树的根结点。从头开始扫描这个序列,比根结点小的元素都应该位于序列的左半部分;从第一个大于根节点开始到根结点前面的一个元素为止,所有元素都应该大于根结点,因为这部分元素对应的是树的右子树。根据这样的划分,把序列划分为左右两部分,我们递归地确认序列的左、右两部分是不是都是二元查找树。

参考代码:

[cpp]
view plaincopy

///////////////////////////////////////////////////////////////////////
// Verify whether a squence of integers are the post order traversal
// of a binary search tree (BST)
// Input: squence - the squence of integers
// length - the length of squence
// Return: return ture if the squence is traversal result of a BST,
// otherwise, return false
///////////////////////////////////////////////////////////////////////
bool verifySquenceOfBST(int squence[], int length)
{
if(squence == NULL || length <= 0)
return false;

// root of a BST is at the end of post order traversal squence
int root = squence[length - 1];

// the nodes in left sub-tree are less than the root
int i = 0;
for(; i < length - 1; ++ i)
{
if(squence[i] > root)
break;
}

// the nodes in the right sub-tree are greater than the root
int j = i;
for(; j < length - 1; ++ j)
{
if(squence[j] < root)
return false;
}

// verify whether the left sub-tree is a BST
bool left = true;
if(i > 0)
left = verifySquenceOfBST(squence, i);

// verify whether the right sub-tree is a BST
bool right = true;
if(i < length - 1)
right = verifySquenceOfBST(squence + i, length - i - 1);

return (left && right);
}

题目:怎样编写一个程序,把一个有序整数数组放到二叉搜索树中?

分析:本题考察二叉搜索树的建树方法,简单的递归结构。关于树的算法设计一定要联想到递归,因为树本身就是递归的定义。

参考代码:

[cpp]
view plaincopy

Node* array_to_tree(int array[],int start,int end)
{
if (start > end) return NULL;
int m = start+(end-start)/2;
Node* root = new Node(array[m]);
root->left = array_to_tree(array,start,m-1);
root->right = array_to_tree(array,m+1,end);
return root;
}

Node* array2Tree(int array[],int n)
{
return array_to_tree(array,0,n-1);
}

题目:输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表。要求不能创建任何新的结点,只调整指针的指向。

比如将二元查找树

10

/ \

6 14

/ \ / \

4 8 12 16

转换成双向链表 4=6=8=10=12=14=16。

分析:本题是微软的面试题。很多与树相关的题目都是用递归的思路来解决,本题也不例外。下面我们用两种不同的递归思路来分析。

  思路一:当我们到达某一结点准备调整以该结点为根结点的子树时,先调整其左子树将左子树转换成一个排好序的左子链表,再调整其右子树转换右子链表。最后链接左子链表的最右结点(左子树的最大结点)、当前结点和右子链表的最左结点(右子树的最小结点)。从树的根结点开始递归调整所有结点。

  思路二:我们可以中序遍历整棵树。按照这个方式遍历树,比较小的结点先访问。如果我们每访问一个结点,假设之前访问过的结点已经调整成一个排序双向链表,我们再把调整当前结点的指针将其链接到链表的末尾。当所有结点都访问过之后,整棵树也就转换成一个排序双向链表了。

参考代码:

[cpp]
view plaincopy

//定义二元查找树结点的数据结构如下:
struct BSTreeNode // a node in the binary search tree
{
int m_nValue; // value of node
BSTreeNode *m_pLeft; // left child of node
BSTreeNode *m_pRight; // right child of node
};

//思路一对应的代码:
///////////////////////////////////////////////////////////////////////
// Covert a sub binary-search-tree into a sorted double-linked list
// Input: pNode - the head of the sub tree
// asRight - whether pNode is the right child of its parent
// Output: if asRight is true, return the least node in the sub-tree
// else return the greatest node in the sub-tree
///////////////////////////////////////////////////////////////////////
BSTreeNode* ConvertNode(BSTreeNode* pNode, bool asRight)
{
if(!pNode)
return NULL;

BSTreeNode *pLeft = NULL;
BSTreeNode *pRight = NULL;

// Convert the left sub-tree
if(pNode->m_pLeft)
pLeft = ConvertNode(pNode->m_pLeft, false);

// Connect the greatest node in the left sub-tree to the current node
if(pLeft)
{
pLeft->m_pRight = pNode;
pNode->m_pLeft = pLeft;
}

// Convert the right sub-tree
if(pNode->m_pRight)
pRight = ConvertNode(pNode->m_pRight, true);

// Connect the least node in the right sub-tree to the current node
if(pRight)
{
pNode->m_pRight = pRight;
pRight->m_pLeft = pNode;
}

BSTreeNode *pTemp = pNode;

// If the current node is the right child of its parent,
// return the least node in the tree whose root is the current node
if(asRight)
{
while(pTemp->m_pLeft)
pTemp = pTemp->m_pLeft;
}
// If the current node is the left child of its parent,
// return the greatest node in the tree whose root is the current node
else
{
while(pTemp->m_pRight)
pTemp = pTemp->m_pRight;
}

return pTemp;
}

///////////////////////////////////////////////////////////////////////
// Covert a binary search tree into a sorted double-linked list
// Input: the head of tree
// Output: the head of sorted double-linked list
///////////////////////////////////////////////////////////////////////
BSTreeNode* Convert(BSTreeNode* pHeadOfTree)
{
// As we want to return the head of the sorted double-linked list,
// we set the second parameter to be true
return ConvertNode(pHeadOfTree, true);
}

//思路二对应的代码:
///////////////////////////////////////////////////////////////////////
// Covert a sub binary-search-tree into a sorted double-linked list
// Input: pNode - the head of the sub tree
// pLastNodeInList - the tail of the double-linked list
///////////////////////////////////////////////////////////////////////
void ConvertNode(BSTreeNode* pNode, BSTreeNode*& pLastNodeInList)
{
if(pNode == NULL)
return;

BSTreeNode *pCurrent = pNode;

// Convert the left sub-tree
if (pCurrent->m_pLeft != NULL)
ConvertNode(pCurrent->m_pLeft, pLastNodeInList);

// Put the current node into the double-linked list
pCurrent->m_pLeft = pLastNodeInList;
if(pLastNodeInList != NULL)
pLastNodeInList->m_pRight = pCurrent;

pLastNodeInList = pCurrent;

// Convert the right sub-tree
if (pCurrent->m_pRight != NULL)
ConvertNode(pCurrent->m_pRight, pLastNodeInList);
}

///////////////////////////////////////////////////////////////////////
// Covert a binary search tree into a sorted double-linked list
// Input: pHeadOfTree - the head of tree
// Output: the head of sorted double-linked list
///////////////////////////////////////////////////////////////////////
BSTreeNode* Convert_Solution1(BSTreeNode* pHeadOfTree)
{
BSTreeNode *pLastNodeInList = NULL;
ConvertNode(pHeadOfTree, pLastNodeInList);

// Get the head of the double-linked list
BSTreeNode *pHeadOfList = pLastNodeInList;
while(pHeadOfList && pHeadOfList->m_pLeft)
pHeadOfList = pHeadOfList->m_pLeft;

return pHeadOfList;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: