樹的面試題

簡介

    前面介紹過二叉樹的數據結構,它的邏輯很簡單,除了根結點之外每個結點只有一個父節點,除了葉結點之外所有的結點都有一個或多個子節點。父和子之間用指針連接。

    二叉樹有三種變量方式:

    -前序遍歷:根左右

    -中序遍歷:左根右

    -後序遍歷:左右根

題目1:重建二叉樹

    輸入某二叉樹的前 序遍歷和中序遍歷的結果,重建該二叉樹

struct BinaryTreeNode//結點結構
{
	int _value;
	BinaryTreeNode* _left;
	BinaryTreeNode* _right;

	BinaryTreeNode(const int&x)
	{
		_value = x;
		_left = NULL;
		_right = NULL;
	}
};

BinaryTreeNode* Construct(int * prevOrder, int *inOrder, int length)
{
	if (prevOrder == NULL || inOrder == NULL || length == 0)
		return;
	return ConstructCore(prevOrder,prevOrder+length-1,inOrder,inOrder+length-1)
}

BinaryTreeNode*ConstructCore(int* PrevHead, int*prevTail, int*inHead, int*inTail)
{
	//前序遍歷的第一個節點即爲根結點
	BinaryTreeNode* root = new BinaryTreeNode(PrevHead[0]);
	//只有一個節點
	if (PrevHead == prevTail)
	{
		if (inHead == inTail)
			return root;
		else
			throw std::exception("Invalid inPut");//拋出異常
	}
	//在中序結點中找到根結點的值
	int *InorderRoot = inHead;
	while (InorderRoot<=inTail&&InorderRoot != PrevHead)
	{
		InorderRoot++;
	}
	if (InorderRoot == inTail&&*InorderRoot != PrevHead[0])
		throw std::exception("Invalid input");

	int leftLength = InorderRoot - inHead;
	int* leftPrevOrderTail = PrevHead + leftLength;
	if (leftLength > 0)
	{
		//構建左子樹
		root->_left = ConstructCore(PrevHead + 1, leftPrevOrderTail, inHead, InorderRoot - 1);
	}
	if (leftLength < prevTail - PrevHead)
	{
	//構建右子樹
		root->_right = ConstructCore(leftPrevOrderTail + 1, prevTail, InorderRoot + 1, inTail);
	}
	return root;
}

 題目二:二叉樹的鏡像

    先前序遍歷這棵樹的結點,若遍歷到的結點有子節點,就交換這個兩個子節點,當交換完成所有非葉子結點的左右結點之後,就得到數的鏡像

void MirrorRecursively(BinaryTreeNode *pRoot)
{
	if ((pRoot == NULL)||(pRoot->m_pLeft==NULL&&pRoot->m_pRight==NULL))
		return;
	swap(pRoot->m_pLeft, pRoot->m_pRight);
	if (pRoot->m_pLeft)
		MirrorRecursively(pRoot->m_pLeft);
	if (pRoot->m_pRight)
		MirrorRecursively(pRoot->m_pRight);

}

題目三:輸入兩顆二叉樹A和B,判斷B不是A的子結構

bool HasSubTree(BinaryTreeNode*pRoot1, BinaryTreeNode*pRoot2)
{
	BinaryTreeNode* pcur1 = pRoot1;
	BinaryTreeNode* pcur2 = pRoot2;
	bool result = false;
	if (pRoot1 != NULL || pRoot2 != NULL)
	{
		if (pcur1->m_value == pcur2->m_value)
			result = DoseTree1HaveTree2(pcur1, pcur2);
		if (!result)
			result = HasSubTree(pcur1->m_pLeft, pcur2);
		if (!result)
			result = HasSubTree(pcur1->m_pRight, pcur2);
	}
	return result;
}
bool DoseTree1HaveTree2(BinaryTreeNode* pRoot1, BinaryTreeNode* pRoot2)
{
	if (pRoot2 == NULL)
		return true;
	if (pRoot2 == NULL)
		return false;
	if (pRoot1->m_value != pRoot2->m_value)
		return false;
	return DoseTree1HaveTree2(pRoot1->m_pLeft, pRoot1->m_pLeft) && DoseTree1HaveTree2(pRoot1->m_pRight, pRoot2->m_pRight);
}

題目四:層序遍歷二叉樹

void PrintLevelOrder(BinaryTreeNode<T>*root)
	{
		if (root == NULL)
			return;
		queue<BinaryTreeNode<T>*>q1;
		q1.push(root);
		
		while (q1.size() != 0)
		{
			if (q1.front()->_left)
			{
				q1.push(q1.front()->_left);
			}
			if (q1.front()->_right)
			{
				q1.push(q1.front()->_right);
			}
			cout << q1.front()->_value << " ";
			q1.pop();
		}
	}

題目五:前序非遞歸實現

void PrintPrevOrder(BinaryTreeNode<T>root)
{
    if(root==NULL)
        return;
    stack<BinaryTreeNode<T>*>s;
    s.push(root);
    while(s.size()>0)
    {
        BinaryTreeNode<T>*cur=s.top();
        s.pop();
        cout<<cur->_value<<" ";
        
        if(root->_right!=NULL)
            s.push(root->_right);
        if(root->_left!=NULL)
            s.push(root->_left);
     }
 }

題目六:中序的非遞歸實現

void PrintInOrder(BinaryTreeNode<T>root)
{
    stack<BinaryTreeNode<T>*>s;
    BinaryTreeNode<T>*cur=root;
    
    while(cur||s.size>0)
    {
        s.push(cur);
        while(cur->_left)
        {
            s.pusu(cur->_left);
            cur=cur->_left;
        }
        cout<<s.top()->_value<<" ";
        cur=s.top()->_right;
        s.pop();
    }
}

題目七:後序的非遞歸實現

void PrintPostOrder(BinaryTreeNode<T>*root)
	{
		stack<BinaryTreeNode<T>*>s;
		BinaryTreeNode<T>*cur = root;
		BinaryTreeNode<T>*prev = NULL;
		while (cur || s.size() > 0)
		{
			while (cur != NULL)
			{
				s.push(cur);
				cur = cur->_left;
			}
			cur = s.top();
			if (cur->_right == NULL || cur->_right == prev)
			{
				cout << cur->_value << " ";
				prev = cur;
				cur = NULL;
				s.pop();
			}
			else
			{
				cur = cur->_right;
			}
		}
	}

題目八:二叉搜索樹的後序遍歷

輸入一個整數數組,判斷該數組是不是某二叉樹的後序遍歷結果,如果是返回true,否則返回false

bool VerifySquenceOfBST(int sequence[], int length)
{
	if (sequence == NULL || length <= 0)
		return false;
	int root = sequence[length - 1];

	size_t i = 0;
	for ( i = 0; i < length - 1; i++)
	{
		if (sequence[i]>root)
			break; 
	}
	
	size_t j = i;
	for (; j < length; j++)
	{
		if (sequence[j] < root)
			return false;
	}
	bool left = true;
	left = VerifySquenceOfBST(sequence, i);
	
	bool right = true;
	right = VerifySquenceOfBST(sequence + i, length - i - i);
	
	return left&&right;
}

題目九:二叉樹中和爲某一值的路徑

輸入一個二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的所有路徑,從樹的根開始往下一直到葉形成一條路徑

void Findpath(BinatryTreeNode<T>*root, T sum)
	{
		if (root == NULL)
			return;
		vector<BinatryTreeNode<T>*> path;
		int curSum = 0;
		_FindPath(root, sum, path, curSum);
	}
private:
	void _FindPath(BinatryTreeNode<T>*root, const T&sum, vector<BinaryTreeNode<T>*>&path, T&curSum)
	{
		curSum_ += root->_value;
		path.push_back(root);
		//如果爲葉結點且路徑值相等則輸出路徑
		bool IsLeaf = root->_right == NULL&&root->_left == NULL;
		if (curSum == sum&&IsLeaf)
		{
			for (size_t i = 0; i < path.size(); i++)
			{
				cout << path[i]->_value << " ";
			}
		}
		//若不是葉結點遍歷至葉結點
		if (root->_left != NULL)
			_FindPath(root->_left, sum, path, curSum);
		if (root->_right != NULL)
			_FindPath(root->_right, sum, path, curSum);
		
		curSum -= root->_value;
		path.pop_back();
	}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章