1. 程式人生 > >劍指offer-重建二叉樹

劍指offer-重建二叉樹

題目:

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都

不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},
則重建二叉樹並返回。

解題:仔細觀察重建二叉樹,前序遍歷和中序遍歷規律,前序遍歷是存放根節點,中序就是以此節點做切分左右子樹!遞迴是樹本質,遞迴這個時候寫出來的程式碼特美!

struct TreeNode {
	int val;
	TreeNode *left;
	TreeNode *right;
	TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
	int vin_size = vin.size();
	if (vin_size == 0)
		return NULL;
	
	int val = pre[0];//root or subroot
	TreeNode* node = new TreeNode(val);
	int p = 0;
	for (; p<vin_size; p++){
		if (vin[p] == val)//root positon
			break;
	}
	//直接初始化,注意容器初始化另外一個容器最好採用偏移位置,不要採用陣列[]索引形式傳入地址,容器的最後一個地址是end是不給陣列形式索引的!
	vector<int> vin_left(vin.begin(), vin.begin()+p),\
	vin_right(vin.begin() + p + 1, vin.begin()+vin_size),\
	pre_left(pre.begin() + 1, pre.begin()+p+1),\
	pre_right(pre.begin()+p+1, pre.begin()+vin_size);
	//或者採用迴圈
	/*for (int i = 0; i<vin_size; i++){
		if (i<p){
			vin_left.push_back(vin[i]);
			pre_left.push_back(pre[i + 1]);
		}
		else if (i>p){
			vin_right.push_back(vin[i]);
			pre_right.push_back(pre[i]);
		}
	}*/
	node->left = reConstructBinaryTree(pre_left, vin_left);//先構造左邊
	node->right = reConstructBinaryTree(pre_right, vin_right);//接著右邊
	return node;
}

void printf_middle_order(TreeNode* boot)
{
	if (boot != NULL)
	{
		printf_middle_order(boot->left);
		printf("%d ",boot->val);
		printf_middle_order(boot->right);
	}
}
void printf_pre_order(TreeNode* boot)
{
	if (boot != NULL)
	{
		printf("%d ", boot->val);
		printf_middle_order(boot->left);
		printf_middle_order(boot->right);
	}
}

int main()
{
	int  pre_shuzu[8] = { 1, 2, 4, 7, 3, 5, 6, 8 };
	int  vin_shuzu[8] = { 4, 7, 2, 1, 5, 3, 8, 6 };
	vector<int> pre(&pre_shuzu[0],&pre_shuzu[8]);//注意vector結束是要陣列的最後一個元素的下一個地址
	vector<int> vin(&vin_shuzu[0], &vin_shuzu[8]);
	
	TreeNode* tree_boot = reConstructBinaryTree(pre,vin);
	printf_middle_order(tree_boot);
	while (true)
	{
		
	}
	return 0;
}