二叉树的算法题

目录

一、非递归形式实现前中后序遍历

1.1 先序遍历

1.2  后序遍历(用两个栈)

1.3 后序遍历(用一个栈)骚操作

1.4中序遍历

​编辑

二、实现二叉树的按层遍历

1、用队列

三、统计二叉树最多的层


二叉树的结构:

class Node {
public:
	Node(int v) {
		value = v;
	}
public:
	int value;
	Node* left;
	Node* right;

};

一、非递归形式实现前中后序遍历

1.1 先序遍历

1.弹出就打印

2.如有右,压入右

3.如有左,压入左

void pre(Node* head) {
		cout << "前序遍历:" << endl;
		if (head != nullptr) {
			stack<Node*> stack;
			stack.push(head);
			while (!stack.empty()) {
				head = stack.top();
				stack.pop();
				cout << head->value << " ";
				if (head->right != nullptr) {
					stack.push(head->right);
				}
				if (head->left != nullptr) {
					stack.push(head->left);
				}
			}
		}
		cout << endl;
	}

1.2  后序遍历(用两个栈)

 那么 头  右   左  的顺序是不是有点眼熟呢?没错,这不倒过来不就是后序遍历了吗。

1.弹出就放入到第二个栈res中

2.如有左,压入左

3.如有右,压入右

4.最后将res中的全部打印

void pos(Node* head) {
		cout << "后序遍历:" << endl;
		if (head != nullptr) {
			stack<Node*> st1;
			stack<Node*> st2;
			st1.push(head);
			while (!st1.empty()) {
				head = st1.top();
				st1.pop();
				st2.push(head);
				if (head->left != nullptr) {
					st1.push(head->left);
				}
				if (head->right != nullptr) {
					st1.push(head->right);
				}	
			}
			while (!st2.empty()) {
				cout << st2.top()->value << " ";
				st2.pop();
			}
		}	
		cout << endl;
	}

1.3 后序遍历(用一个栈)骚操作

只用一个栈去完成

	void pos2(Node* h) {
		cout<<"后序遍历炫技版: "<<endl;
		if (h != nullptr) {
			stack<Node*> stack;
			stack.push(h);
			Node* c = nullptr;
			while (!stack.empty()) {
				c = stack.top();
				//说明这个c的左树都还没处理呢,肯定先要去处理左树
				if (c->left != nullptr && h != c->left && h != c->right) {
					stack.push(c->left);
				}
				//说明左树处理了,但右树没有处理,那就去处理右树
				else if (c->right != nullptr && h != c->right) {
					stack.push(c->right);
				}
				//左右树都处理完了,那就去处理头
				else {
					cout << stack.top()->value<<" ";
					stack.pop();
					h = c;//处理一个,那就让h记录刚处理的位置
				}
			}
		}
		cout << endl;
	}

1.4中序遍历

 1. 将整条左边界依次压入栈

 2. 1无法执行了,就弹出栈,并到弹出的右树上继续执行

为什么会这样做呢?

	void in(Node* cur) {
		cout<<"中序遍历 : "<<endl;
		if (cur != nullptr) {
			stack<Node*> stack;
			while (!stack.empty() || cur != nullptr) {
				if (cur != nullptr) {
					stack.push(cur);
					cur = cur->left;
				}
				else {
					cur = stack.top();
					stack.pop();
					cout << cur->value << " ";
					cur = cur->right;
				}
			}
		}
		cout << endl;
	}

二、实现二叉树的按层遍历

1、用队列

弹出就打印,先进左树,再进右树

void level(Node* head) {
		if (head == nullptr) {
			return;
		}
		queue<Node*> queue;
		queue.push(head);
		
		while (!queue.empty()) {
			Node* cur = queue.front();
			cout << cur->value << " ";
			queue.pop();
			//System.out.println(cur.value);
			if (cur->left != nullptr) {
				queue.push(cur->left);
			}
			if (cur->right != nullptr) {
				queue.push(cur->right);
			}
		}
	}

还可以用牛客给的答案的方法:实现之字形打印

  vector<vector<int> > levelOrder(TreeNode* root) {
        // write code here
        vector<vector<int>> vt;
        if(root==nullptr)
            return vt;
        
        //队列存储,进行层次遍历
        queue<TreeNode*> q;
        q.push(root);
        TreeNode* cur;
        while(!q.empty()){
            vector<int> temp;
            int n=q.size();
            for(int i=0;i<n;++i){
                cur=q.front();
                q.pop();
                temp.push_back(cur->val);
                if(cur->left)
                    q.push(cur->left);
                if(cur->right)
                    q.push(cur->right);
                
            }
            vt.push_back(temp);//一层都统计完之后再加入
        }
        return vt;
    }

三、统计二叉树最多的层

不仅要打印每一层,还要发现一个层的开始或结束

1、用map

int maxWidthUseMap(Node* head) {
		if (head == nullptr) {
			return 0;
		}
		queue<Node*> queue;
		queue.push(head);
		// key 在 哪一层,value
		unordered_map <Node*, int> levelMap;
		levelMap.insert(make_pair(head,1));

		int curLevel = 1; // 当前你正在统计哪一层的宽度
		int curLevelNodes = 0; // 当前层curLevel层,宽度目前是多少
		int Max = 0;
		while (!queue.empty()) {
			Node* cur = queue.front();
			queue.pop();

			int curNodeLevel = levelMap[cur];//当前的层数
			
			if (cur->left != nullptr) {
				levelMap.insert(make_pair(cur->left, curNodeLevel + 1));
				queue.push(cur->left);
			}
			if (cur->right != nullptr) {
				levelMap.insert(make_pair(cur->right, curNodeLevel + 1));
				queue.push(cur->right);
			}
			if (curNodeLevel == curLevel) {
				curLevelNodes++;
			}
			else {
				Max = max(Max, curLevelNodes);
				curLevel++;
				curLevelNodes = 1;//刚开始的时候下一层肯定是1
			}
		}
		Max = max(Max, curLevelNodes);
		return Max;
	}

2、不用map

int maxWidthNoMap(Node* head) {
		if (head == nullptr) {
			return 0;
		}
		queue<Node*> queue;
		queue.push(head);
		Node* curEnd = head; // 当前层,最右节点是谁
		Node* nextEnd = nullptr; // 下一层,最右节点是谁
		int Max = 0;
		int curLevelNodes = 0; // 当前层的节点数
		while (!queue.empty()) {
			Node* cur = queue.front();
			queue.pop();

			if (cur->left != nullptr) {
				queue.push(cur->left);
				nextEnd = cur->left;
			}
			if (cur->right != nullptr) {
				queue.push(cur->right);
				nextEnd = cur->right;
			}
			curLevelNodes++;
			if (cur == curEnd) {
				Max = max(Max, curLevelNodes);
				curLevelNodes = 0;
				curEnd = nextEnd;
			}
		}
		return Max;
	}

题:给二叉树的某节点,返回它的后继节点

 后继节点指他中序遍历的下一个节点

1、暴力:   

 最简单的方法就是一直去找parent,直到找到父节点,然后中序遍历,找到他的下一个

2、直接去找他的后继

既然是中序遍历,肯定是遵从  左  头  右  的顺序,

那如果一个树有右子树的话,他的后继直接就是右子树最左边的那个子树

 如果没有右子树的话,就一直往上去找,直到父子关系是子树是父的左子树,(右子树的话就继续向上)

 当然,最后一个节点是没有后继的,必然找不到,那就返回nullptr就是了

代码:

Node* getSuccessorNode(Node* node) {
		if (node == nullptr) {
			return node;
		}
		if (node->right != nullptr) {
			return getLeftMost(node->right);
		}
		else { // 无右子树
			Node* parent = node->parent;
			while (parent != nullptr && parent->right == node) { // 当前节点是其父亲节点右孩子
				node = parent;									 // 那就继续向上去找
				parent = node->parent;
			}
			return parent;
		}
	}

	Node* getLeftMost(Node* node) {
		if (node == nullptr) {
			return node;
		}
		while (node->left != nullptr) {
			node = node->left;
		}
		return node;
	}

同理,找前驱就是反过来就行了

 这棵树其实根本就i不存在,但我用递归模拟了他

明确规定的树,根本不用建树,就可以打印了


 

猜你喜欢

转载自blog.csdn.net/flyingcloud6/article/details/128873987