Algorithms and Data Structures (5)

1. C++ binary tree structure

insert image description here

typedef struct BiNode 
{
    
    
	int data;  //结点内值域
	struct BiNode* lchild, * rchild; //左孩子 右孩子
} BiNode, * BiTree;

or:

 
class Node
{
    
    
public:
	char data;// data表示该节点代表的内容;
	Node* L;//左子树
	Node* R;//右子树
}; 
Node* T;//创个指针,指向二叉树的根节点;

2. Realize the pre-order, in-order and post-order traversal of binary trees in two ways: recursive and non-recursive

Have the following tree:
insert image description here

Recursive method:
pre-order traversal:
first traverse the head, then traverse the nodes of the left subtree, and then traverse the nodes of the right subtree. The traversal results are as follows: the
insert image description here
recursive method code is as follows:

void preOrder(Node*& T)
{
    
    
	if (T == NULL)
	{
    
    
		return;//如果该结点为空就返回;
	}
 	//递归遍历 
	else
	{
    
    
		cout << T->data << " ";  //先输出根节点的那个数字
		preOrder(T->L);          //然后访问左孩子,开始递归
		preOrder(T->R);          //左孩子访问完成,开始右孩子递归
	}
}

The output of the above code is traversal first.
The traversal result of the recursive order is:
insert image description here
we only need to print when the number appears for the first time during the recursive traversal.
Non-recursive:
idea:
first put the root node in the stack
1, then pop a node cur from the stack
2, print cur;
3, first right and then left (if there is), otherwise do nothing
4, loop 1- 3, until there is no data in the stack.

class Solution {
    
    
public:
    void preorderTraversal(TreeNode* root) {
    
    
    	if(root != NULL){
    
    
    	//申请一个临时栈
        stack<TreeNode*> st;
        //将根节点首先压入栈中
        st.push(root);
   		//如果栈不为空,则开始循环
        while(!st.empty())
        {
    
    		//弹出栈中的一个结点
                root = st.pop();
                //打印弹出的结点
                cout << root->val << " ";
                //如果叶结点不为空,则开始先将出栈节点的右结点和左结点先后压入栈中
                if(root->right != NULL)
                {
    
    
                	st.push(root->right);
				}
                if(root->left != NULL)
                {
    
    
                	st.push(root->left);
				}
		}
	}
}		

In-order traversal:
first traverse the left, then traverse the nodes of the head, and then traverse the nodes of the right subtree. The traversal results are as follows: the
insert image description here
recursive method code is as follows:

void inOrder(Node*& T)
{
    
    
	if (T == NULL)
		return;
	else
	{
    
    
		inOrder(T->L);
		cout << T->data << " ";
		inOrder(T->R);
	}
}

Non-recursive method:
ideas:
1. Push the left border of each subtree under the pushed node into the stack (starting from the root node for the first time). For the following figure, the stack is (1, 2, 4)
2. Pop up the node, print the pop-up node during the pop-up process
3. Push the right node of the pop-up node
4. Cycle the above two steps
insert image description here

class Solution {
    
    
public:
    void inOrderTraversal(TreeNode* root) {
    
    
    	if(root != NULL){
    
    
    	//申请一个临时栈
        stack<TreeNode*> st;
   		//如果栈不为空,则开始循环
        while(!st.empty() || root != NULL)
        {
    
    	
        	//如果当前结点不为空,则一直将其左结点压栈	
			if(root != NULL){
    
    
				st.push(root);        		
                root = root->left;
                }
            //否则从栈中弹出一个结点,并打印,将其右结点返回
			else{
    
    
				root = st.pop();
                cout << root->val << " ";
                root = root->right;
			}
		}
	}
}            
	

Post-order traversal:
first traverse the left, then traverse the right, and then traverse the head node. The traversal results are as follows: the
insert image description here
recursive method code is as follows:

 
void posOrder(Node*& T)
{
    
    
	if (T == NULL)
		return;
	else
	{
    
    
		posOrder(T->L);
		posOrder(T->R);
		cout << T->data << " ";
	}
}

Non-recursive method:
idea:
first put the root node in the stack
1, then pop a node cur from the stack
2, put the popped node in a recovery stack;
3, first left and then right (if any), Otherwise, do nothing
4. Loop 1-3 until there is no data in the stack.
5. Pop data from the recovery stack one by one and print

class Solution {
    
    
public:
    void posOrderTraversal(TreeNode* root) {
    
    
    	if(root != NULL){
    
    
    	//申请一个临时栈
        stack<TreeNode*> st1;
        stack<TreeNode*> st2;
        //将根节点首先压入栈中
        st1.push(root);
   		//如果栈不为空,则开始循环
        while(!st1.empty())
        {
    
    		//弹出栈中的一个结点
                root = st1.pop();
                //将弹出的结点压入回收栈中
                st2.push(root);
                //如果叶结点不为空,则开始先将出栈节点的左结点和右结点先后压入栈中
                if(root->left != NULL)
                {
    
    
                	st1.push(root->left);
				}
                if(root->right != NULL)
                {
    
    
                	st1.push(root->right);
				}
		}
		//将回收栈中的数据打印
		while(!st2.empty())
		{
    
    
			cout<<st2.pop()->val<< " ";
		}
	}
}		

3. Breadth-first traversal of a binary tree (common question: find the width of a binary tree)

insert image description here
There are trees like above. The breadth-first traversal output is: 1, 2, 3, 4, 5, 6, 7, 8, 9
Ideas:
We use the queue method to solve this problem:
1. First put the root node in the queue
2. Pop out the queue The first node, then print the node, and put the left and right child nodes of the node into the queue one after another (if there is no left or right, skip and put another node directly).
3. Repeat step 2 until the queue is empty

#include<stdio.h>
#include<vector>
#include<queue>
//树的机构体
struct TreeNode
{
    
    
 int val;
 TreeNode* left;
 TreeNode* right;
 TreeNode(int x): val(x), left(NULL), right(NULL){
    
    }
};
//开始进行宽度优先遍历
void BFS(TreeNode* root)
{
    
    
	//实例化一个队列
	 std::queue<TreeNode*> Q;
	
	//将根节点压入队列中
	 Q.push(root);
	//如果该队列非空,则一直循环操作
	 while (!Q.empty())
	 {
    
    
		//将第一个元素返回并打印
		  TreeNode* node = Q.front();
		  printf("[%d]", node->val);
		//弹出第一个元素
		  Q.pop();
		//开始先放左结点再放右节点的操作
		  if (node->left)
		  {
    
    
		   	Q.push(node->left);
		  }
		  if (node->right)
		  {
    
    
		   	Q.push(node->right);
		  }
	 }
}
//初始化树
int main()
{
    
    
 TreeNode a(1);
 TreeNode b(2);
 TreeNode c(5);
 TreeNode d(3);
 TreeNode e(4);
 TreeNode f(6);
 a.left = &b;
 a.right = &c;
 b.left = &d;
 b.right = &e;
 c.right = &f;
 BFS(&a);
 return 0;
}

Fourth, find the maximum width of the binary tree

Ideas:
1) First, we need to know the layer number of each node: the layer number of each node is the layer number of its parent node + 1. Therefore, when we push the child node of a node into the queue, we can save its child node level: current level +1.
2) Second, we need to obtain the width of each layer, and return the maximum value of all layer widths. Because the nodes at the same level in the width traversal method must be output and traversed sequentially, it is very convenient for us to count the width of a certain layer.

int MaxWidth(TreeNode* root)
{
    
    
	int widMax = 0; //记录结果:最大宽度
	if (nullptr == root)
	{
    
    
		return 0;
	}
	queue<TreeNode*> nodeQueue; //遍历二叉树的辅助队列
	unordered_map< TreeNode*, int> levelMap; //记录每个节点所在层数的哈希表
	//根节点入队列
	nodeQueue.push(root);
	levelMap[root] = 1; //根节点定义为在第1层
	int curLevel = 1; //当前所在层数
	int curWidth = 0; //当前层记录的宽度
	while (!nodeQueue.empty())
	{
    
    
		TreeNode* temp = nodeQueue.front();
		//弹出队首节点
		nodeQueue.pop();
		//获取队首节点的层数,如果和上一个队首节点的层数curLevel相同,则curWidth+1;否则,说明已经开始进入下一层,则重置curWidth并更新curLevel
		if (levelMap[temp] == curLevel)
		{
    
    
			++curWidth;
		}
		//已经进入下一层
		else
		{
    
    
			//在进入下一层结点之前先要保存最大宽度
			widMax = curWidth > widMax ? curWidth : widMax;
			//将宽度置一
			curWidth = 1;
			//重置层数
			curLevel = levelMap[temp];
		}
 
		if (temp->left != NULL)
		{
    
    
			nodeQueue.push(temp->left);
			//保存当前节点左孩子的层数:当前层数+1
			levelMap[temp->left] = curLevel + 1;
		}
		if (temp->right != NULL)
		{
    
    
			nodeQueue.push(temp->right);
			//保存当前节点右孩子的层数:当前层数+1
			levelMap[temp->right] = curLevel + 1;
		}
	}
	return widMax;
}

We can also implement this operation without using a hash table.
Ideas:
1) enter the queue
2) cur_end records the last node
next_end records each node entering the queue
curlevel records the number of nodes in each layer
3) whenever the node that comes out is not equal to cur_end, curlevel++
; When the node is equal to cur_end, curlevel++, and next_end is assigned to cur_end, next_end is set to NULL,
max is updated and compared with curlevel, and curlevel is set to 0

#include<iostream>
#include<stdlib.h> 
#include<deque>  //插入标准库中的头文件
using namespace std;
 
typedef struct treenode
{
    
    
	char data;
	treenode *right;
	treenode *left;
}*Node;
 
//创建二叉树
void creat_tree(treenode *&rt)
{
    
    
	char ch;
	ch = getchar();
	if ('#' == ch) {
    
    
		rt = NULL;
	} else {
    
    
		rt = new treenode;
		rt->data = ch;
		creat_tree(rt->left);        //构造左子树
		creat_tree(rt->right);    //构造右子树    
	}
}
 
int noMapWeight(Node* head) {
    
    
	//如果没有结点,则返回
	if (head == NULL)
		return 0;
	
	//创建一个队列
	queue<Node*> q;
	q.push(head);//先将头装进去
	Node* cur_end = head; //定义当前层最后一个结点
	Node* next_end = NULL; //定义下一层最后一个节点
	int curlevel = 0, max = 0; //定义每层的节点数以及最大的节点数
	while (!q.empty()) {
    
    
		Node* out = q.front(); //取出第一个元素的值
		q.pop();//弹出第一个元素
		if (out->left != NULL) {
    
    //将左结点压入,并且下一层的最后一个结点赋值
			q.push(out->left);
			next_end = out->left;
		}	
		if (out->right != NULL) {
    
    //将右结点压入,并对下一层最后一个节点赋值
			q.push(out->right);
			next_end = out->right;
		}//如果输出的元素不为当前层最后一个结点,则宽度加一
		if (out != cur_end) {
    
    
			curlevel++;
		//否则宽度先加一,然后将将所有变量移动到最后一层,并且暂存最大值
		}else {
    
    
			curlevel++;
			cur_end = next_end;
			next_end = NULL;
			max = max < curlevel ? curlevel : max;
			curlevel = 0;
		}
	}
	return max;//返回最大值
}
 
int main() {
    
    
	treenode *root = NULL;
	int height, width;  //表示高度和最大宽度
	cout << "请输入二叉树,空值以#代表:" << endl;
	creat_tree(root);        //创建二叉树
	Complete_binary_tree(root,height,width);
	cout << "高度为:" << height << endl;
	cout<<"最大宽度为:" << width << endl;
	system("pause");
	return 0;
}

5. How to judge that a binary tree is a search binary tree

Search binary tree: the left node is smaller than the head node, and the right node is larger than the head node. A classic search binary tree has no duplicate values.
insert image description here
The figure above is a classic search binary tree. As can be seen from the above figure, in the middle order traversal, all nodes are in ascending order, which is to search the binary tree. If a position is descending, the tree is not a search binary tree.
Method 1 : Directly traverse and compare subtrees one by one in a recursive manner.

/*
* 概念:每个结点都比左儿子大,比右儿子小,严格的搜索二叉树没有重复的值
step:   1)中序遍历得到的数组的升序的
*/
int preData = INT_MIN;
bool isBST(Node* head) {
    
    
	if (head == NULL)
		return true;
	bool isLeftBST = isBST(head->left);
	if (!isLeftBST)//如果左树不是,就直接返回false
		return false;
	if (preData >= head->data)//如果根的data比左的小,就返回false
		return false;
	else {
    
    
		preData = head->data;
	}
	return isBST(head->right);
}

Method 2 : Put all the nodes traversed each time in the list container, and then judge whether the values ​​of the nodes in the list container are in ascending order.

//判断是否为搜索二叉树2
#include<list>
#include<algorithm>
bool isBST2(Node* head) {
    
    
	if (head == NULL)
		return false;
	list<int> L;
	process(head, L);
	int sz = L.size();
	list<int>::iterator end = --L.end();
	for (list<int>::iterator it = L.begin();it != end;)
		if (*it >= *(++it))
			return false;
	return true;
}
void process(Node* head, list<int>& L) {
    
    
	if (head == NULL)
		return;
	process(head->left, L);
	L.push_back(head->data);
	process(head->right, L);
}

Method 3 : Compare in non-recursive process

bool isBST(node* head){
    
    
    if (head == NULL){
    
    
        return true;
    }
    stack<node*>newstack;
    int pre = INT_MIN;
    while (!newstack.empty() || head != NULL){
    
    
        if (head != NULL){
    
    
            newstack.push(head);
            head = head->left;
        }
        else{
    
    
            head = newstack.top();
            //cout << head->value << ",";
            if (pre < head->value){
    
    
                pre = head->value;
            }else{
    
    
                return false;
            }
            newstack.pop();
            head = head->right;
        }
    }
    return true;
}

Guess you like

Origin blog.csdn.net/qq_52302919/article/details/131102062