【算法笔记】二叉树基本算法

给定一个结点,如何找该结点中序遍历的后继结点

分析:解法1:执行中序遍历,当遍历的前一个结点是该结点时,输出当前结点,当前结点就是后继结点,时间复杂度O(N)
解法2:如果结点的结构如下:

class Node {
public:
	int val;
	Node* left;
	Node* right;
	Node* parent;
};

则可以降低时间复杂度O(K),K最大为二叉树的高度
分两种情况:
一:如果X结点有右子树,那么X的后继结点就是右子树最左边的结点

在这里插入图片描述

二:如果X结点没有右子树,那么就一直往上找,直到结点不是父亲的右孩子,此时父亲就是后继结点

在这里插入图片描述

Node* mostLeftNode(Node* node) {
	if (node == NULL) {
		return NULL;
	}
	while (node->left != NULL) {
		node = node->left;
	}
	return node;
}
Node* succeedingNode(Node* node) {
	if (node == NULL) {
		return NULL;
	}
	if (node->right != NULL) {
		return mostLeftNode(node->right);
	}
	if (node->right == NULL) {
		Node* parent = node->parent;
		while (parent != NULL && parent->right == node) {
			node = parent;
			parent = node->parent;
		}
		return parent;
	}
}

请把一段纸条竖着放在桌子上,然后从纸条的下边向上方对折1次,压出折痕后展开。此时折痕是凹下去的(下折痕),即折痕突起的方向指向纸条的背面。如果从纸条的下边向上方连续对折2次,压出折痕后展开,此时有三条折痕,从上到下依次是下折痕、下折痕和上折痕。
给定一个输入参数N,代表纸条从下边向上方连续对折N次。请从上到下打印所有折痕的方向。
例如:
N=1时,打印: 凹
N=2时,打印: 凹 凹 凸

分析:经实践所得,根结点是凹的,左子树的根结点是凹的,右子树的根结点是凸的,每一个结点的左孩子是凹的,每一个结点的右孩子是凸的。
对该树进行中序遍历就是所得结果。

void process(int i, int N, bool down) {
	if (i > N) {
		return;
	}
	process(i + 1, N, true);//遍历左子树
	//遍历根结点
	if (down) {//true为凹,false为凸
		cout << "凹" << " ";
	}
	if (!down) {
		cout << "凸" << " ";
	}
	process(i + 1, N, false);//遍历右子树
}
//假想一颗树,i表示当前在第几层,N表示这棵树一共有几层,
//down为true表示凹,fals表示凸
void foldTimes(int N){
	process(1,N,true);
}

对折N次,该二叉树就会有N层,也就会有2N -1个结点,所以时间复杂度为O(2N -1)
空间复杂度O(N),主要是递归占用的额外空间


判断一个树是否为完全二叉树?

分析:完全二叉树需要满足以下两个条件:
一:不存在一个结点只有右孩子,没有左孩子
二:层序遍历,如果第一次遇到了一个结点只有左孩子没有右孩子,或者没有左孩子只有右孩子,那么往后的结点一定都是叶子结点。

bool isCompleteBinaryTree(Node* root) {
	if (root == NULL) {
		return true;
	}
	queue<Node*>q;
	bool flag = false;//标志是否遇到了不全的结点
	q.push(root);
	while (!q.empty()) {
		Node* cur = q.front();
		q.pop();
		if (cur->right != NULL && cur->left == NULL) {//左子树为空,右子树不空返回false
			return false;
		}
		if (flag) {//已经遇到第一个不全的结点,往后的结点只要不是叶子结点就返回false
			if (cur->left != NULL || cur->right != NULL) {
				return false;
			}
		}
		if (cur->left == NULL || cur->right == NULL) {//第一次遇到不全的结点就会将flag置true
			flag = true;
		}
		if (cur->left != NULL) {
			q.push(cur->left);
		}
		if (cur->right != NULL) {
			q.push(cur->right);
		}
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值