(计蒜客)二叉树的分裂

试写一个算法,将一棵二叉查找树,分裂成两棵二叉查找树,使得一棵的关键字都小于或等于x,另一棵的关键字都大于x

本题输入输出广义表达式,空的结点上存在一个-占位符

输入格式

输入有两行,第一行为待操作的二叉树广义表达式

第二行输入值为x


输出格式

输出也为两行,为分裂后的二叉树广义表达式,第二行数值为x

样例输入

5(2,8)
3

样例输出

2
5(-,8)

解题思路:

这道题有多个难点,第一是广义表的输入和输出,这里有模板可以仿照,但要根据题意稍加改动

比如在读入的时候,空结点要用 - 符号进行代替,然后就是数字在入栈时,如果这个数字是二位数,该怎么处理

Node* Node::buildTree(const string& input)  //根据广义表的建树操作
{
	stack<Node*> treeStack;
	int k = -1;
	if (input == "") {
		return nullptr;
	}

	for (int i = 0; i < input.length(); ++i) {
		if (input[i] == '(') {
			k = 0;
			treeStack.push(new Node(input[i] - 48, nullptr));
		}
		else if (input[i] == ',') {
			k = 1;
		}
		else if (input[i] == ')') {
			treeStack.pop();
		}
		else {
			//空结点忽略
			if (input[i] == '-') {
				continue;
			}

			//读入两位数时的处理方式
			Node* temp = nullptr;
			if (input[i] >= 48 && input[i] <= 57 && input[i+1] >= 48 && input[i+1] <= 57) {
				temp = new Node(10 * (input[i] - 48) + (input[i + 1] - 48), nullptr);
				i++;
			}
			else {
				temp = new Node(input[i] - 48, nullptr); //暂存
			}

			if (k == -1) {
				treeStack.push(temp);
			}
			else if (k == 0) {
				treeStack.pop();  //栈顶元素出栈
				treeStack.top()->lchild = temp;
				temp->father = treeStack.top();
				treeStack.push(temp);
			}
			else if (k == 1) {
				treeStack.pop();
				treeStack.top()->rchild = temp;
				temp->father = treeStack.top();
				treeStack.push(temp);
			}
		}
	}
	return treeStack.top();   //最后返回的是根节点
}

输出函数只需在结点为空时加上 - 符号即可

void Node::lambdaprint()
{
	cout << data;
	if (lchild != nullptr) {
		cout << "(";
		lchild->lambdaprint();
		if (rchild == nullptr) {
			cout << ",-)";
		}
	}

	if (rchild != nullptr) {
		if (lchild == nullptr) {
			cout << "(-";
		}
		cout << ",";
		rchild->lambdaprint();
		cout << ")";
	}
}

之后是寻找分裂的左节点和右节点:

1找到小于等于x的最大结点max

if (root == nullptr) {
			return;
		}

		Node* current_node = root;
		Node* mmax = nullptr;

		while (1) {
			if (current_node == nullptr) {
				break;
			}
			if (value == current_node->data) {
				mmax = current_node;
				break;
			}
			else if (current_node->data < value) {
				if (mmax == nullptr || current_node->data > mmax->data) {
					mmax = current_node;
				}
				current_node = current_node->rchild;
			}
			else {
				current_node = current_node->lchild;
			}
		}

2.求出两棵分裂后的树

if (mmax == nullptr) {
			cout << endl;
			root->lambdaprint();
			return;
		}

		Node* l = mmax;
		Node* r = mmax->rchild;
		mmax->rchild = nullptr;

		while (mmax != root) {
			if (mmax == mmax->father->lchild) {
				mmax->father->lchild = r;
				r = mmax->father;
			}
			else {
				mmax->father->rchild = l;
				l = mmax->father;
			}
			mmax = mmax->father;
		}


		if (l != nullptr) {
			l->lambdaprint();
		}
		cout << endl;
		if (r != nullptr) {
			r->lambdaprint();
		}
	}

整体代码如下:

#include <iostream>
#include <algorithm>
#include <string>
#include <stack>
using namespace std;

class Node {
public:
	int data;
	Node* lchild, *rchild, *father;
	Node(int _data, Node* _father) {
		data = _data;
		lchild = nullptr;
		rchild = nullptr;
		father = _father;
	}
	~Node() {
		if (lchild != nullptr) {
			delete lchild;
		}
		if (rchild != nullptr) {
			delete rchild;
		}
	}

	//搜索函数
	Node* search(int value);
	Node* buildTree(const string& input);
	void lambdaprint();
};

Node* Node::search(int value)
{
	if (value == data) {
		return nullptr;
	}
	else if (value > data) {
		if (rchild == nullptr) {
			return nullptr;
		}
		else {
			return rchild->search(value);
		}
	}
	else {
		if (lchild == nullptr) {
			return nullptr;
		}
		else {
			return lchild->search(value);
		}
	}
}

Node* Node::buildTree(const string& input)
{
	stack<Node*> treeStack;
	int k = -1;
    if (input == "") {
		return nullptr;
	}

	for (int i = 0; i < input.length(); ++i) {
		if (input[i] == '(') {
			k = 0;
			treeStack.push(new Node(input[i]-48,nullptr));
		}
		else if (input[i] == ',') {
			k = 1;
		}
		else if (input[i] == ')') {
			treeStack.pop();
		}
		else {
			if (input[i] == '-') {
				continue;
			}

            Node* temp = nullptr;
			if (input[i] >= 48 && input[i] <= 57 && input[i+1] >= 48 && input[i+1] <= 57) {
				temp = new Node(10 * (input[i] - 48) + (input[i + 1] - 48), nullptr);
				i++;
			}
			else {
				temp = new Node(input[i] - 48, nullptr); //暂存
			}
            
			if (k == -1) {
				treeStack.push(temp);
			}
			else if (k == 0) {
				treeStack.pop();  //栈顶元素出栈
				treeStack.top()->lchild = temp;
				temp->father = treeStack.top();
				treeStack.push(temp);
			}
			else if (k == 1) {
				treeStack.pop();
				treeStack.top()->rchild = temp;
				temp->father = treeStack.top();
				treeStack.push(temp);
			}
		}
	}
	return treeStack.top();   //最后返回的是根节点
}

void Node::lambdaprint()
{
	cout << data;
	if (lchild != nullptr) {
		cout << "(";
		lchild->lambdaprint();
		if (rchild == nullptr) {
			cout << ",-)";
		}
	}

	if (rchild != nullptr) {
		if (lchild == nullptr) {
			cout << "(-";
		}
		cout << ",";
		rchild->lambdaprint();
		cout << ")";
	}
}

class BinaryTree {
private:
	Node* root;
public:
	BinaryTree() {
		root = nullptr;
	}
	~BinaryTree() {
		delete root;
	}

	void lambdaprint() {
		if (root != nullptr) {
			root->lambdaprint();
		}
	}
	
	void buildTree(const string& input) {
		root = root->buildTree(input);
	}

	Node* search(int value) {
		return root->search(value);
	}

	void searchAndDivide(int value)
	{
        if (root == nullptr) {
			return;
		}
        
		Node* current_node = root;
		Node* mmax = nullptr;

		while (1) {
			if (current_node == nullptr) {
				break;
			}
			if (value == current_node->data) {
				mmax = current_node;
				break;
			}
			else if (current_node->data < value) {
				if (mmax == nullptr || current_node->data > mmax->data) {
					mmax = current_node;
				}
				current_node = current_node->rchild;
			}
			else {
				current_node = current_node->lchild;
			}
		}

		if (mmax == nullptr) {
			cout << endl;
			root->lambdaprint();
			return;
		}

		Node* l = mmax;
		Node* r = mmax->rchild;
		mmax->rchild = nullptr;
	
		while (mmax != root) {
			if (mmax == mmax->father->lchild) {
				mmax->father->lchild = r;
				r = mmax->father;
			}
			else {
				mmax->father->rchild = l;
				l = mmax->father;
			}
			mmax = mmax->father;
		}
		
	
		if (l != nullptr) {
			l->lambdaprint();
		}
		cout << endl;
		if (r != nullptr) {
			r->lambdaprint();
		}
	}
};

int main() {
	BinaryTree binaryTree;
	
	string input;
	getline(cin, input);
	binaryTree.buildTree(input);
	int value = 0;
	cin >> value;
	binaryTree.searchAndDivide(value);

	
	return 0;
}

 

 

 

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值