[专题五] 二叉树
Posted recoverableti
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[专题五] 二叉树相关的知识,希望对你有一定的参考价值。
树结构专题
二叉树
几种典型运算
typedef struct BTNode{
int data;
struct BTNode *left;
struct BTNode *right;
}BTNode;
// 创建二叉树
BTNode BinaryTree() {
BTNode *T = (BTNode*)malloc(sizeof(BTNode));
T->data = 0;
return T;
}
//BinaryEmpty(T):bool 判断树是否为空
//Root(T):int 返回根结点data
//构造二叉树
BTNode MakeTree(int x, BTNode *l, BTNode *r) {
BTNode *T = (BTNode*)malloc(sizeof(BTNode));
T->data = x;
T->left = l; T->right = r;
return T;
}
//BreakTree(x,T,l,r):void makeTree的逆运算 拆成左右树
先序非递归
//PreOrder(root):void 先序遍历
//PreOut(root):void 先序序列
void PreOrder(BTNode *root) {
if(!root) exit(1);
stack<BTNode*> stack;
BTNode *cur;
stack.push(root);
while(!stack.empty()) {
cur = stack.top();
stack.pop();
cout << cur->data << " ";
if (cur->right) {
stack.push(cur->right);
}
if (cur->left) {
stack.push(cur->left);
}
}
}
中序非递归 — 记忆区别 1
//InOrder(root):void 中序遍历
//InOut(root):void 中序序列
void InOrder(BTNode *root) {
if(!root) exit(1);
stack<BTNode*> stack;
// 与先序区分
BTNode *cur = root;
while(!stack.empty() || cur) {
while (cur) {
stack.push(cur);
cur = cur->left;
}
if (!stack.empty()) {
cur = stack.top();
stack.pop();
cout << cur->data << " ";
cur = cur->right;
}
}
}
后序非递归
//先序左右孩子入栈顺序交换得到逆后序,逆后序再逆序得后序
//PostOrder(root):void 后序遍历
//PostOut(root):void 后序序列
void PostOrder(BTNode *root) {
if(!root) exit(1);
stack<BTNode*> stack1;
stack<BTNode*> stack2;
BTNode *cur;
stack1.push(root);
while(!stack1.empty()) {
cur = stack1.top();
stack1.pop();
stack2.push(cur);
if (cur->left) { /*左右孩子入栈顺序改变*/
stack1.push(cur->left);
}
if (cur->right) {
stack1.push(right);
}
}
while (!stack2.empty()) {
cur = stack2.top();
cout<< cur->data << " ";
stack2.pop();
}
}
层序遍历 可记录层数
void LevelOrder(BTNode *root) {
queue<BTNode*> que;
BTNode *cur;
que.push(root);
while (!que.empty()) {
int size = que.size(); // 嵌套for循环使用
while (!que.empty()) {
cur = que.front();
que.pop();
if (cur->left) {
que.push(cur->left);
}
if (cur->right) {
que.push(cur->right);
}
}
}
}
中序遍历的二叉树线索化 — 记忆
/** 首先明确是使用递归,传入的是pre和root
对于某结点而言,如果它没有左孩子,则左线索指向前驱
同理 如果它的前驱没有右孩子,则指向后继
然后使pre指针后移一位,而中序遍历中,本结点后继是右孩子,所以p移向右孩子
**/
void Inthread(BTNode *p, BTNode *&pre) {
if (p) {
Inthread(p->left, pre);
if (p->left==NULL) {
p->left = pre;
p->ltag = 1;
}
if (pre!=NULL && pre->right==NULL) {
pre->right = p;
p->rtag = 1;
}
pre = p;
Inthread(p->rchild, pre);
}
}
二叉搜索树
二叉搜索树基本操作 — 记忆
/** 根据BST的特性,对于每个节点:如果目标值等于节点的值,则返回节点;如果目标值小于节点的值,则继续在左子树中搜索;如果目标值大于节点的值,则继续在右子树中搜索。 **/
// 增加结点
TreeNode* insertIntoBST(TreeNode* root, int val) {
TreeNode *p = root, *pre;
while(p) { /**先搜索,边保存前驱结点**/
pre = p;// 保存前驱很重要!!
if(p->val>val) p = p->left;
else if(p->val<val) p = p->right;
else return 0;
}
TreeNode *r = new TreeNode(val); //创建结点
if(root) { /**如果树存在,则创建前驱结点与新结点的关系,反之,则将该结点插入空树**/
if(pre->val > val) pre->left = r;
else pre->right = r;
}
else root = r;
return root;
}
// 删除结点 我无能,抄大佬的递归
TreeNode* deleteNode(TreeNode* root, int key) {
if(root==NULL)return NULL;
if(root->val>key)
{
root->left = deleteNode(root->left,key);
return root;
}
if(root->val<key)
{
root->right = deleteNode(root->right,key);
return root;
}
if(root->left==NULL&&root->right==NULL)return NULL;
if(root->left==NULL&&root->right!=NULL)return root->right;
if(root->left!=NULL&&root->right==NULL)return root->left;
int val = findMax(root->left);
root->val=val;
root->left = deleteNode(root->left,val);
return root;
}
int findMax(TreeNode* root)
{
if(root->right==NULL)return root->val;
return findMax(root->right);
}
二叉树的路径最大和
// lmr讨论的是 包含a作为根结点的结果 可能
int maxs = INT_MIN;
int maxPathSum(TreeNode* root) {
findroot(root);
return maxs;
}
int findroot(TreeNode *root) {
if(!root) return 0;
int left = max( findroot(root->left), 0); //用这种方法舍去左右孩子可能为负值的情况
int right = max( findroot(root->right), 0);
int lmr = root->val + right + left;
maxs = max(maxs, lmr);
// 如果大于0 说明可以使分支变大 太难了
return max(0,root->val + max(left, right));
}
知识点和代码均学习于Acwing: https://www.acwing.com/activity/
以上是关于[专题五] 二叉树的主要内容,如果未能解决你的问题,请参考以下文章