算法筆記---二叉查找樹的性質

題目描述

給出N個正整數來作爲一棵二叉排序樹的結點插入順序,問:這串序列是否是該二叉排序樹的先序序列或是該二叉排序樹的鏡像樹的先序序列。所謂鏡像樹是指交換二叉樹的所有結點的左右子樹而形成的樹(也即左子樹所有結點數據域大於或等於根結點,而根結點數據域小於右子樹所有結點的數據域)。如果是鏡像樹,則輸出YES,並輸出對應的樹的後序序列;否則,輸出NO。

輸入樣例1
7
8 6 5 7 10 8 11
輸出樣例1
YES
5 7 6 8 11 10 8
輸入樣例2
8 10 11 8 6 7 5
輸出樣例2
YES
11 8 10 7 5 6 8
輸入樣例3
8 6 8 5 10 9 11
輸出樣例3
No

解題思路:
保存輸入序列origin
先構造一棵二叉排序樹(二叉查找樹),然後求出
前序遍歷pre
鏡像前序遍歷preM
後序遍歷post
鏡像後序遍歷postM
然後分別比較origin和pre ,preM,若相等,則輸出後序遍歷或者鏡像後序遍歷序列

#include<iostream>
using namespace std;
#include<queue>
#include <vector>

//結點定義
struct node
{
	int data;//數據域
	int layer;//層次
	node* lchild;
	node* rchild;
};

//先序遍歷
void pre_order(node* root) {
	if (root == NULL)
	{
		return;
	}
	cout << root->data << endl;
	pre_order(root->lchild);
	pre_order(root->rchild);
}

//中序遍歷
void in_order(node* root) {
	if (root == NULL)
	{
		return;
	}
	in_order(root->lchild);
	cout << root->data << endl;
	in_order(root->rchild);
}

//後序遍歷
void post_order(node* root) {
	if (root == NULL)
	{
		return;
	}
	post_order(root->lchild);
	post_order(root->rchild);
	cout << root->data << endl;
}

//層次遍歷且計算每個結點所在層次
void layer_order(node* root) {
	if (root == NULL)
	{
		return;
	}
	queue<node*> q;
	root->layer = 1;
	q.push(root);
	while (!q.empty())
	{
		node* top = q.front();
		q.pop();
		cout << top->data << endl;
		if (top->lchild)
		{
			//左孩子的層號 = 當前層號 + 1
			top->lchild->layer = top->layer + 1;
			q.push(top->lchild);
		}
		if (top->rchild)
		{
			top->rchild->layer = top->layer + 1;
			q.push(top->rchild);
		}
	}
}

//求樹的高度
int tree_height(node* root) {
	if (root == NULL)
	{
		return 0;
	}
	int left_height, right_height;
	left_height = tree_height(root->lchild);
	right_height = tree_height(root->rchild);
	if (left_height > right_height)
	{
		return left_height + 1;
	}
	else
	{
		return right_height + 1;
	}
}
//根據先序和中序構建二叉樹
node* reConstructBinaryTree(vector<int> pre, vector<int> vin) {
	if (pre.empty() || vin.empty() || pre.size() != vin.size())
	{
		return NULL;
	}
	vector<int> pre_left, pre_right, vin_left, vin_right;
	int i = 0;
	for (i = 0; i < vin.size(); i++)
	{
		if (pre[0] == vin[i])
		{
			break;
		}
		//構造先序遍歷和中序遍歷的左子樹
		pre_left.push_back(pre[i + 1]);
		vin_left.push_back(vin[i]);
	}
	for (int j = i + 1; j < vin.size(); j++)
	{
		pre_right.push_back(pre[j]);
		vin_right.push_back(vin[j]);
	}
	node* root = new node;
	root->data = pre[0];
	root->lchild = reConstructBinaryTree(pre_left, vin_left);
	root->rchild = reConstructBinaryTree(pre_right, vin_right);
	return root;
}

//根據中序和後續遍歷來構建二叉樹
node* create(vector<int> vin, vector<int> post) {
	if (vin.empty() || post.empty() || vin.size() != post.size())
	{
		return NULL;
	}
	vector<int> vin_left, vin_right, post_left, post_right;
	int i = 0;
	for (i = 0; i < vin.size(); i++)
	{
		if (post[post.size() - 1] == vin[i])
		{
			break;
		}
		vin_left.push_back(vin[i]);
		post_left.push_back(post[i]);
	}
	for (int j = i + 1; j < vin.size(); j++)
	{
		vin_right.push_back(vin[j]);
		post_right.push_back(post[j - 1]);
	}
	node* root = new node;
	root->data = post[post.size() - 1];
	root->lchild = create(vin_left, post_left);
	root->rchild = create(vin_right, post_right);
	return root;
}

//層序遍歷
void bfs(node* root) {
	if (root == NULL)
	{
		return;
	}
	queue<node*> q;
	q.push(root);
	while (!q.empty())
	{
		node* top = q.front();
		q.pop();
		cout << top->data << endl;
		if (top->lchild)
		{
			q.push(top->lchild);
		}
		if (top->rchild)
		{
			q.push(top->rchild);
		}
	}
}

//二叉樹中和爲某一值的路徑
vector< vector<int> > find_path(node* root, int number) {
	
	vector< vector<int> > ret;//返回結果
	if (root == NULL)
	{
		return ret;
	}
	vector<int> temp_array;//臨時存放當前路徑
	temp_array.push_back(root->data);
	vector< vector<int> > array;//保存每條路徑的結點值
	array.push_back(temp_array);
	queue<node*> q;
	q.push(root);
	while (!q.empty())//bfs
	{
		node* top = q.front();
		q.pop();
		temp_array = array[0];
		if (top->lchild == NULL && top->rchild == NULL)
		{
			int sum = 0;
			for (int i = 0;i < temp_array.size();i++)
			{
				sum += temp_array[i];
			}
			if (sum == number)
			{
				ret.push_back(temp_array);
			}
		}
		if (top->lchild)
		{
			q.push(top->lchild);
			vector<int> temp(temp_array);
			temp.push_back(top->lchild->data);
			array.push_back(temp);
		}
		if (top->rchild)
		{
			q.push(top->rchild);
			vector<int> temp(temp_array);
			temp.push_back(top->rchild->data);
			array.push_back(temp);
		}
		vector< vector<int> >::iterator it = array.begin();
		array.erase(it);//將當前不完整的路徑刪除
	}
	return ret;
}

//************************************
// Method:    dfs
// FullName:  dfs
// Access:    public 
// Returns:   void
// Qualifier:
// Parameter: vector< vector<int> > & res 結果集
// Parameter: vector<int> & temp_array 臨時存放訪問路徑
// Parameter: node * root 當前結點
// Parameter: int target 目標值
// Parameter: int sum 當前路徑結點的和
//************************************
void dfs(vector< vector<int> >& res, vector<int>& temp_array, node* root, int target, int sum) {

	/*if (target < sum)
	{
		return;
	}*/
	temp_array.push_back(root->data);
	if (root->lchild == NULL && root->rchild == NULL && target == sum)
	{
		res.push_back(temp_array);
	}
	if (root->lchild)
	{
		dfs(res, temp_array, root->lchild, target, sum + root->lchild->data);
	}
	if (root->rchild)
	{
		dfs(res, temp_array, root->rchild, target, sum + root->rchild->data);
	}
	if (!temp_array.empty())
	{
		temp_array.pop_back();
	}
}

//二叉樹中和爲某一值的路徑
vector< vector<int> > find_path_part(node* root, int target) {
	vector< vector<int> > res;//返回結果集
	vector<int> temp_array;//臨時存放路徑
	if (root == NULL)
	{
		return res;
	}
	dfs(res, temp_array, root, target, root->data);
	return res;
}

//二叉查找樹的查找
void search_node(node* root, int x) {
	if (root == NULL)
	{
		cout << "查找失敗!" << endl;
		return;
	}
	if (root->data == x)
	{
		cout << root->data << endl;
	}
	else if (root->data < x)
	{
		search_node(root->rchild, x);//查找右子樹
	}
	else
	{
		search_node(root->lchild, x);//查找左子樹
	}
}

//尋找最大值
node* find_max(node* root) {
	while (root->rchild)
	{
		root = root->rchild;//不斷往右,直到沒有右孩子
	}
	return root;
}
//尋找最小值
node* find_min(node* root) {
	while (root->lchild)
	{
		root = root->lchild;
	}
	return root;
}

//刪除結點
void delete_node(node* &root, int x) {
	if (root == NULL)
	{
		return;
	}
	if (root->data == x)//找到刪除的結點
	{
		if (root->lchild == NULL && root->rchild == NULL)
		{
			root = NULL;
		}else if (root->lchild)
		{
			node* pre = find_max(root->lchild);//找到前驅
			root->data = pre->data;
			delete_node(root->lchild, pre->data);//在左子樹中刪除結點
		}
		else if (root->rchild)
		{
			node* next_node = find_min(root->rchild);//找到後繼
			root->data = next_node->data;
			delete_node(root->rchild, next_node->data);//在右子樹中刪除結點
		}
	}else if (root->data < x)
	{
		delete_node(root->rchild,x);//在右子樹中刪除
	}
	else
	{
		delete_node(root->lchild, x);//在左子樹中刪除
	}
}

//結點插入
void insert_node(node*& root, int data) {
	if (root == NULL)//此時需要插入
	{
		root = new node;
		root->data = data;
		root->lchild = root->rchild = NULL;
		return;
	}
	if (data < root->data)
	{
		insert_node(root->lchild, data);
	}
	else
	{
		insert_node(root->rchild, data);
	}
}

//先序遍歷然後將結果存入v
void pre_order(node* root, vector<int> &v) {

	if (root == NULL)
	{
		return;
	}
	v.push_back(root->data);
	pre_order(root->lchild, v);
	pre_order(root->rchild, v);
}

//後序遍歷然後將結果存入v
void post_order(node* root, vector<int> &v) {
	if (root == NULL)
	{
		return;
	}
	post_order(root->lchild, v);
	post_order(root->rchild, v);
	v.push_back(root->data);
}

//鏡像樹前序遍歷,然後將結果存入v中
void pre_order_mirror(node* root, vector<int> &v) {
	if (root == NULL)
	{
		return;
	}
	v.push_back(root->data);
	pre_order_mirror(root->rchild, v);
	pre_order_mirror(root->lchild, v);
}

//鏡像樹後序遍歷,然後將結果存入v中
void post_order_mirror(node* root, vector<int> &v) {
	if (root == NULL)
	{
		return;
	}
	post_order_mirror(root->rchild, v);
	post_order_mirror(root->lchild, v);
	v.push_back(root->data);
}


int main() {
	
	/*int vin_arr[] = { 1,2,3,4,5,6,7 };
	int post_arr[] = { 2,3,1,5,7,6,4 };
	vector<int> vin,post;
	for (int i = 0; i < 7; i++)
	{
		vin.push_back(vin_arr[i]);
		post.push_back(post_arr[i]);
	}
	node* root = create(vin, post);
	bfs(root);*/
	vector<int> origin, pre, preM, post, postM;
	int n, data;
	cin >> n;
	node* root = NULL;
	for (int i = 0;i < n; i++)
	{
		cin >> data;
		origin.push_back(data);
		insert_node(root, data);//構造二叉樹
	}

	//求出各個序列
	pre_order(root, pre);
	pre_order_mirror(root, preM);
	post_order(root, post);
	post_order_mirror(root, postM);
	if (origin == pre)//初始序列等於先序
	{
		cout << "YES" << endl;
		for (int i = 0;i < post.size(); i++)
		{
			cout << post[i];
			if (i < post.size() - 1)
			{
				cout << " ";
			}
		}
	}else if (origin == preM)//初始序列等於鏡像先序
	{
		cout << "YES" << endl;
		for (int i = 0;i < postM.size(); i++)
		{
			cout << postM[i];
			if (i < postM.size() - 1)
			{
				cout << " ";
			}
		}
	}
	else
	{
		cout << "No" << endl;
	}

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