关于二叉树先序遍历和后序遍历为什么不能唯一确定一个二叉树分析

article/2025/9/1 18:13:16

文章目录

  • 二叉树唯一确定
  • 先序和中序递归构建二叉树的过程
  • 先序和后序递归构建二叉树的过程
  • 先序和后序递归构建二叉树的代码
  • 如果二叉树不唯一,怎么处理
  • 完整代码分析
  • 自己的问题

二叉树唯一确定

        对于一个二叉树,并不是说给出了先序和后序就是无法唯一确定的。只是说,在某些情况下,不能唯一确定。这里先给出结论,然后来分析。

当二叉树中某个节点仅仅只有一个孩子节点的时候,就无法更具其先序和后序唯一的确定一个二叉树。

例如:

preorder: 1 2 3 4
postorder:2 4 3 1
那么,构建出来的树可能是下面两种情况:

在这里插入图片描述
至于严格数学证明我这里无法给出。但是,如果你和我一样,都有点转牛角尖的话,可以自己多多去测试几个数据,然后时间一久,你就可以说服自己了。如果是这样的preorder和postorder的话,是可以唯一确定一个二叉树的。

preorder:1 2 3 4 6 7 5
postorder:2 6 7 4 5 3 1
确定的二叉树就是这样的:

在这里插入图片描述
很明显,因为这个二叉树所有的节点仅仅只有二个或者没有(叶子节点)。所以,这个二叉树是可以唯一确定的。

先序和中序递归构建二叉树的过程

        大家下来看一下维基百科上对于二叉树定义:

In computer science, a binary tree is a tree data structure in which each node has at most two children, which are referred to as the left child and the right child. A recursive definition using just set theory notions is that a (non-empty) binary tree is a tuple (L, S, R), where L and R are binary trees or the empty set and S is a singleton set.Some authors allow the binary tree to be the empty set as well.

也就是说:二叉树的定义是一个递归(recursive)的。我相信大家在学习二叉树的构建的时候老师也讲过递归构建二叉树。在树的数据结构中,递归还是很有必要掌握的,毕竟有很多算法都和这个有关。

        那么,接下来,我们就采用递归的构造方法来创建这个二叉树。为了说明清楚这个构建的过程,有必要提一下先序或者后序和中序是怎么构建一个二叉树的。下面以先序和中序举例:

preorder:1 2 3 4 6 7 5
inorder:2 1 6 4 7 3 5

构建的方法如下:
在preorder序列中,找到第一个节点,根据先序遍历的规则(根 左 右),所以节点1是根节点。然后我们利用中序遍历的规则(左 根 右),只要我们在inorder序列中找到1节点,那么在它的左边和右边的就分别是1节点的左孩子和右孩子了。结合代码看一下:

//preorder的下标为[preLmpreR]
//inorder的下标为[inL,inR]
Node* create(int preL, int preR, int inL, int inR)
{//伏笔(1)if (preL > preR){return NULL;}Node *root = new Node;root->data = preorder[preL];//(伏笔2)//root->left = root->right = NULL;//(伏笔3)/*if (preL == preR){return root;}*/int tmp = root->data;int k = inL;for (; k <= inR; k++){if (inorder[k] == tmp){break;}}int num = k- inL;root->left = create(preL + 1, preL + num, inL, k- 1);root->right = create(preL + num + 1, preR, k+ 1, inR);return root;
}

有些对递归不太懂的同学,可能看到这里就懵了。那么我来说一个我方便理解的方法。就是你不要想太多:例如1节点左右孩子,3节点还有左右孩子啊。递归如果你想的太深入,就很容易把自己想晕。所以,你应该仅仅只想简单情况,具体复杂的情况要计算机自己去执行。那么这里,你就先仅仅只想1节点就只有两个孩子,那么做下面这两个语句就可以了:

root->left = create(preL + 1, preL + num, inL, i - 1);
root->right = create(preL + num + 1, preR, i + 1, inR);

这里就是在说:构建1节点的左孩子然后赋值給left;然后构建1节点的右孩子赋值給right。你先当作preL+1和pre+num相等,inL和i-1相等,那么是不是就仅仅只包含一个节点,就不会继续递归了,然后你自己就可以模拟出来构建的情况了。这里大家就自行体会,我一开始也是有点难理解,但是你多想几天,时间会帮你克服的。下面的中可能会出现(伏笔x)之类的字,大家先忽略,最后会有用的。上面的代码中也有伏笔,注意看。最后要和先序和后序建立二叉树的代码做比较的。

        上面一个很重要的操作就是找到preorder中1节点(根节点)(伏笔4)在inorder序列中的位置。因为根据中序遍历的规则,这个节点1的左边和右边就是1节点的左子树和右子树在inorde序列中的数据。先序和中序之所以可以唯一确定一个二叉树,就是因为可以根据inorder来确定每一个根节点的左右子树。同理,中序和后序也是一样的。

先序和后序递归构建二叉树的过程

        但是,根据先序和后序的遍历规则,根节点不会在左子树和右子树的中间了。但是大家看上面的先序遍历:
preorder:1 2 3 4 6 7 5
对于序列1 2 3 来说,1是根节点,2是左孩子,3是右孩子。(当然,2和3不一定就是1的左孩子和右孩子)。但是对于序列2 3 4 来说,2是根节点,3是左孩子,4是右孩子(当然,3和4不一定就是2的左孩子和右孩子)。但是,可以确定的就是2一定可以当作根节点来对待。重点来了:我在preorde序列中找到根节点1,然后找到下一个节点2,将其当作根节点,然后在postorder中去找到这个节点2。根据后序遍历的规则(左右根),那么2节点的前面的就是2节点自己的左孩子和右孩子,2节点和1节点之间的就是1号节点的孩子。当然,2肯定也是1号节点的孩子节点(可能是左孩子,也可能是右孩子)。那么,如果2节点和1节点之间没有节点了,那么是不是说明1节点仅仅只有2节点这样一个孩子。再根据上面的结论:

当二叉树中某个节点仅仅只有一个孩子节点的时候,就无法更具其先序和后序唯一的确定一个二叉树。

此时应该无法确定一个唯一的二叉树。上面的重点位置(如果看不懂的话)一定要反复体会。因为这个涉及到代码的实现了。

先序和后序递归构建二叉树的代码

Node *create(int preL, int preR, int posL, int posR)
{//伏笔(1)//这个可以作为递归结束条件if(preL > preR){return NULL;}Node *root = (Node*)malloc(sizeof(Node));root->data = preorder[preL];//伏笔(2)root->left = NULL;root->right = NULL;//伏笔(3)//这个可以作为递归结束条件if (preL == preR)return root;//以先序遍历的根节点后一个结点为根节点去查看左右子树int tmp = preorder[preL + 1];int k = posL;//在后序遍历中查看for (; k <= posR - 1; k++){if (postorder[k] == tmp){break;}}int num = k - posL;if (k != posR - 1){root->left = create(preL + 1, preL + 1 + num, posL, k);root->right = create(preL + num + 2, preR, k + 1, posR - 1);}else{flag = false;//伏笔(5)root->left = create(preL + 1, preL + 1 + num, posL, k);}return root;
}

        上面的伏笔都是我写代码过程中遇到的问题。现在来一一解释。

        伏笔(1)(2)(3),可以一次性讲完。(1)(3)都是递归函数的退出条件。至于为什么这两个都可以作为递归的条件,大家可以自己简单模拟一下,或者自己上机调试。对于先序或者后序和中序来确定一个二叉树使用(1)是可以的,但是对于先序和后序的,就只能使用(2)(3)的组合。至于原因就是:在调试过程中我发现:最后会导致preorder下标越界。究其原因就是因为在递归的退出条件是:if(preL>preR)才会退出。但是,其实preL==preR就可以退出了,因为此时就是已经可以唯一确定一个节点了,if(preL>preR)就是会多执行一次,然后返回NULL。所以(2)(3)要一起使用,在返回之前要給root->left=root->right=NULL初始化。但是使用if(preL>preR)就不用担心,因为此时会return NULL,不需要自己手动初始化。这里是需要对这部分递归熟悉一点才可以理解我说的意思(估计我也没有表达清楚我的意思),所以大家多多看几遍,然后测试几遍就好理解一点。

        大家仔细去看,先序和中序求树的代码中,num和k的意思和先序和后序求树中有点发生变化了。在先序和中序求树中,num是代表根节点左孩子的个数,k代表根节点的位置,所以k是没有出现在create()形参,因为这就是要求inorder[k]节点的左右孩子,所以自然就不包括自己了。先序和后序求树中num代表的就是preorder[preL+1]这个节点的左右孩子的个数,但是因为preL+1是preL的孩子节点,而且一定是左孩子节点。至于为什么一定是左孩子节点,我先留在这里,后面会说明。同时,这个事情还与上面代码中伏笔(5)有关。回到正题,既然preL+1一定是preL的左孩子,num+1的个数就是preL节点的左孩子的个数。所以,就会有下面这个代码:

root->left = create(preL + 1, preL + 1 + num, posL, k);

preL+1是preL左孩子的第一个下标(也相当于是preL所有左孩子中的根节点)。preL+num+1就是preL节点左孩子的在先序序列中最后一个下标。因为postorder[k]=preorder[preL],所以在后序序列中最后一个下标就是k。因为postorder[k]是从posL开始找起的,说明在[posL,k]这个序列中,所有的都是preL的左孩子。那么preL的右孩子也是一样的,我就不多说了。大家如果没有理解的话,可以自己测试上面我给出的数据,加上调试代码,多多看几遍就可以懂了。

root->right = create(preL + num + 2, preR, k + 1, posR - 1);

如果二叉树不唯一,怎么处理

        在讲伏笔(5)之前,先讲点别的。我之所以写这个文章就是因为我在做PAT 甲级1119号题目的时候,发现自己写不出来。然后就去看大家的博客,发现都不怎么清楚。基本上就是只有代码,解释的都不多。而且清一色的在处理不唯一的情况的时候,都是将其root->right赋值。也就是说,都是默认为右孩子。(如果你听不懂我在说什么,建议先看看这个题目)我是一个喜欢转牛角尖的人,而且我觉得这个知识也应该掌握,毕竟就是一个递归的使用。大家可以看到上面的代码,我采用的方式是当二叉树不唯一的时候,形成左子树。那么大家可能会想,是不是左子树和右子树都可以了,其实这个就得看你采用什么方法了。以下内容都是我自己测试出来,不一定具有普遍性(但是至少我采用的两种不同的方法在PAT上都测试通过了,说明我的结论应该没有问题)。

        前面提到,我们采用的就是找preL后面的一个节点preL+1,去当做根节点,然后去到postorder序列里面去找到这个根节点,然后做一些操作。而且我认为preL+1一定就是preL的左孩子。这个要反推才好理解。因为我最后要构建一个二叉树出来,所有这个二叉树是是固定的。所有对于一个二叉树固定的来说,在先序遍历中,根节点后面一定是它的左孩子。因为这个二叉树是唯一的,所以每一个节点都应该有两个节点或者为叶子节点,如果仅仅只有一个节点,那么也一定是左子树。因为我们的代码就是这么写的,就是认为preL+1一定就是preL的左孩子。那么你可以会问,这样子不会有问题吗?你要这样想,如果这个二叉树是可以唯一确定的,那么preL+1一定是preL的左孩子(因为二叉树可以唯一确定,所以必定就是两个节点或者为叶子节点)。如果不可以唯一确定(不能唯一确定固定原因就是在在于这个节点既可以为左孩子,又可以为右孩子),那么我就在构建这个二叉树的时候,默认为左孩子就可以了,所以我就能建立出二叉树。(看不懂很正常,因为都是我自己的话,一点都不官方与严谨。但是我觉得可以給读者一个思考的方向。欢迎下面评论交流)

        如果你还有疑问,你可以把上面的代码伏笔(5)改成下面这个代码:

root->right = create(preL + num + 2, preR, k + 1, posR - 1);

也就是你在二叉树不唯一的时候,默认为右孩子。然后测试数据:

4
1 2 3 4
2 4 3 1

就会报错。说明,你在采用以先序遍历中preL+1为分割节点到postorde序列中找的时候,在二叉树不能确定的时候,只能默认为左孩子。 但是网络上很多都是默认右孩子,那么他们是怎么思考的呢?下面先给出代码:然后分析

Node *create(int preL, int preR, int posL, int posR)
{Node *root = (Node*)malloc(sizeof(Node));root->data = preorder[preL];root->left = NULL;root->right = NULL;//这个代码一定的要,不然就会报错if (preL == preR)return root;//以后序遍历的根节点前一个节点为分割节点int tmp = postorder[posR - 1];int k = preL+1;for ( ;k<=preR;k++){if (preorder[k] == tmp){break;}}int num = k - (preL+1);if (k!=preL+1){root->left = create(preL + 1, k-1, posL, posL+num-1);root->right = create(k, preR, posL +num, posR-1);}else{flag = false;root->right = create(k, preR, posL + num, posR - 1);}return root;
}

同样的套路分析,根据后序遍历的规则(左 右 根)把posR-1当作posR的右孩子。那么,在先序序列中,找到了,下标为k。因为preorder[preL]==postorder[posR],所以posR-1也是preL也是的右孩子。根据先序遍历的规则(根 左 右),从preL+1开始,到k就是preL的所有直接孩子节点。所以,[preL+1,k]都是preL的孩子。然后num什么的就都可以分析出来了。所以,在这里,就是二叉树不唯一的时候默认为右孩子节点才对。

完整代码分析

        下面将会给出两中代码,则可以直接通过PAT 1119这到题。大家可以针对上面说的两种情况,自己去试试。如果我就不那么做,会出现什么样的问题。这样子可能有利于大家理解。

//以后序遍历的根节点前一个节点为分割节点

#include<iostream>
#include<vector>using namespace std;
typedef struct Node
{int data;struct Node *left;struct Node *right;
}Node;vector<int> preorder;
vector<int> postorder;
bool flag = true;
vector<int> ans;Node *create(int preL, int preR, int posL, int posR)
{Node *root = (Node*)malloc(sizeof(Node));root->data = preorder[preL];root->left = NULL;root->right = NULL;if (preL == preR)return root;//以后序遍历的根节点前一个节点为分割节点int tmp = postorder[posR - 1];int k = preL+1;for ( ;k<=preR;k++){if (preorder[k] == tmp){break;}}int num = k - (preL+1);if (k!=preL+1){root->left = create(preL + 1, k-1, posL, posL+num-1);root->right = create(k, preR, posL +num, posR-1);}else{flag = false;root->right = create(k, preR, posL + num, posR - 1);}return root;
}void inorder(Node *root)
{if (!root){return;}inorder(root->left);ans.push_back(root->data);inorder(root->right);
}int main()
{int N;cin >> N;int tmp;for (int i = 0; i < N; i++){cin >> tmp;preorder.push_back(tmp);}for (int i = 0; i < N; i++){cin >> tmp;postorder.push_back(tmp);}Node *root = create(0, preorder.size() - 1, 0, postorder.size() - 1);if (flag){cout << "Yes" << endl;}else{cout << "No" << endl;}inorder(root);for (int i = 0; i < ans.size(); i++){cout << ans[i];if (i != ans.size() - 1){cout << " ";}}return 0;
}

//以先序遍历的根节点后一个结点为分割节点

#include<iostream>
#include<vector>using namespace std;
typedef struct Node
{int data;struct Node *left;struct Node *right;
}Node;vector<int> preorder;
vector<int> postorder;
bool flag = true;
vector<int> ans;Node *create(int preL, int preR, int posL, int posR)
{Node *root = (Node*)malloc(sizeof(Node));root->data = preorder[preL];root->left = NULL;root->right = NULL;if (preL == preR)return root;//以先序遍历的根节点后一个结点为分割节点int tmp = preorder[preL + 1];int k = posL;for (; k <= posR - 1; k++){if (postorder[k] == tmp){break;}}int num = k - posL;if (k != posR - 1){root->left = create(preL + 1, preL + 1 + num, posL, k);root->right = create(preL + num + 2, preR, k + 1, posR - 1);}else{flag = false;root->left = create(preL + 1, preL + 1 + num, posL, k);}return root;
}void inorder(Node *root)
{if (!root){return;}inorder(root->left);ans.push_back(root->data);inorder(root->right);
}int main()
{int N;cin >> N;int tmp;for (int i = 0; i < N; i++){cin >> tmp;preorder.push_back(tmp);}for (int i = 0; i < N; i++){cin >> tmp;postorder.push_back(tmp);}Node *root = create(0, preorder.size() - 1, 0, postorder.size() - 1);if (flag){cout << "Yes" << endl;}else{cout << "No" << endl;}inorder(root);for (int i = 0; i < ans.size(); i++){cout << ans[i];if (i != ans.size() - 1){cout << " ";}}return 0;
}

自己的问题


10月15日更新
我发现我上面有点问题,下面是我总结的:

对于递归出口条件:
在先序和中序推出这棵树:1.if (preL > preR) {}适合于只有一个孩子节点或者叶子节点;仅仅使用这个判断不会报错2.if (preL == preR){}仅仅适合于叶子节点的构造,如果对于只有一个孩子节点的来说,就会出现下标越界;仅仅使用这个判断就会报错
在中序和后序推出这棵树:1.if (preL > preR){}适合于只有一个孩子节点或者叶子节点;仅仅使用这个判断不会报错2.if (preL == preR){}仅仅适合于叶子节点的构造,如果对于只有一个孩子节点的来说,就会出现下标越界;仅仅使用这个判断就会报错
在先序和后序推出这颗树:1.if (preL > preR){}仅仅使用这个判断就会报错这个会报错的原因在于:下标越界。为什么会出现这样的情况,我觉得就是因为我们采用的思想就是(假设这里是以prel+1作为分割点去后序遍历中找):认为preL+1就是preL的左孩子,但是,在仅仅通过先序来判断的话,preL+1可能于preL没有任何关系。也就是说,preL+1可能就是另外一颗子树上面的节点。但是程序无法知道,而且你仅仅使用了一个 if (preL > preR){};如果没有到叶子节点话形参还是在变大,最后导致下标越界。2.if (preL == preR){}仅仅使用这个判断不会报错。之前上面的说到这里,针对于仅仅只有一个孩子节点的时候这种判断在这里是会下标越界的。那么为什么在这里不仅没有越界,反而还可以成功呢?原因在于当先序和后序无法推导出一颗唯一的二叉树的时候,我的算法就会默认其是根节点的左子树(当然,你如果想要默认为右子树也是可以,不过就要稍微修改一下代码),那么也就是说,此时仅仅只会給root->left赋值,而不会给root->right赋值。而你现在回头过去看一下,是不是在先序和中序推出这棵树(中序和后序推出这棵树)仅仅使用 if (preL == preR){} 的时候,如果root仅仅只有左孩子的话,那么你在递归调用root->left赋值结束之后,再给root->right赋值的时候,如果不使用if (preL > preR){}就会出现下标越界。但是,在先序和后序推出这颗树的时候就不会了,因为如果可以唯一的确定一棵树,那么节点必然都是有两个孩子或者是叶子节点。如果只有一个节点,那么就无法唯一的推出这棵树,所以代码中就仅仅只会对默认左(或者右)孩子进行赋值,从而即时没有写 if(preL>preR){}也不会导致下标越界。综上所述:如果想要简单点写代码,然后又可以使用于所有的情况,那么就是这两个判断条件都写上去就欧克了。这个就是万能操作。

http://chatgpt.dhexx.cn/article/ZblQWQ10.shtml

相关文章

二叉树的递归遍历(先序输入)

今天来看看二叉树的递归遍历&#xff0c;我们要实现二叉树的先序&#xff0c;中序&#xff0c;后续遍历 这里我们采用的是先序输入 下面是完整代码 #include <stdio.h> #include <stdlib.h> struct node {char data;node *Lchild;node *Rchild; }tree; node *cr…

根据二叉树先序遍历和中序遍历构建二叉树

前方有一个人在等着你&#xff0c;你只管勇敢的向前走 采用递归分治的思想&#xff0c;将一个大问题划分成子问题&#xff0c; 对于本题&#xff0c;根据二叉树先序遍历和中序遍历构建二叉树&#xff0c;思路&#xff1a; 我们可以求得根节点左子树的先序和中序序列&#xff0…

二叉树前序、中序、后序遍历非递归写法的透彻解析

前言 在前两篇文章二叉树和二叉搜索树中已经涉及到了二叉树的三种遍历。递归写法&#xff0c;只要理解思想&#xff0c;几行代码。可是非递归写法却很不容易。这里特地总结下&#xff0c;透彻解析它们的非递归写法。其中&#xff0c;中序遍历的非递归写法最简单&#xff0c;后…

二叉树的后序遍历

二叉树文章系列&#xff1a; 二叉树的前序遍历二叉树的中序遍历二叉树的后序遍历二叉树的层序遍历二叉树的前序、中序、后序、层序遍历【解法完整版】 本文目录 一、解题思路&#xff1a;递归二、解题思路&#xff1a;迭代&#xff08;方法1&#xff09;三、解题思路&#xff…

C语言完整代码实现:二叉树的先序遍历、中序遍历、后序遍历

一、先序遍历原理 先序遍历就是&#xff1a;根、左、右&#xff0c;也就是先遍历根结点再遍历左结点最后再遍历右结点&#xff0c;注意&#xff1a;如果遍历到的结点不是叶子结点的话需要对该结点进行拆分&#xff0c;比如这棵二叉树&#xff1a; 先遍历A&#xff0c;然后是B&a…

数据结构——二叉树的先序遍历

二叉树的遍历分为 先序遍历&#xff0c;中序遍历&#xff0c;后序遍历&#xff0c;层次遍历 四种遍历。 这节要分享的是先序遍历 如图所示&#xff0c;这是一个普通的二叉树。他的先序遍历是&#xff1a;A B D E H C F G I J 为什么呢&#xff1f; 先序遍历的遍历规则是&am…

二叉树三种遍历顺序

三.二叉树的三种遍历方式 1.先序遍历&#xff1a;按照根节点->左子树->右子树的顺序访问二叉树 先序遍历&#xff1a;&#xff08;1&#xff09;访问根节点&#xff1b;&#xff08;2&#xff09;采用先序递归遍历左子树&#xff1b;&#xff08;3&#xff09;采用先序…

二叉树(Binary Tree):先序遍历、中序遍历、后序遍历和层次遍历

二叉树&#xff08;Binary Tree&#xff09;&#xff1a;先序遍历、中序遍历、后序遍历和层次遍历 树 Tree二叉树 Binary Tree先序遍历 Preorder Traversal中序遍历 Inoreder Traversal后序遍历 Postorder Traversal层次遍历 Level Traversal 树 Tree 根 Root&#xff1a;树顶部…

oracle awr监控报告,一个Oracle小白的AWR报告分析(一)

背景&#xff1a;某个类似准实时的数据分析系统&#xff0c;每15分钟从其他6个数据库中抽取五百张增量数据表&#xff0c;并进行15分钟粒度统计&#xff0c;同时有个前端门户进行查询。 该数据分析系统由数据抽取服务器、应用服务器、数据库服务器组成&#xff0c;全部为虚拟机…

oracle生成awr报告命令,Oracle AWR报告生成方法

1、登录Oracle程序所在的服务器&#xff0c;查找出awrrpt.sql文件所在位置 D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\awrrpt.sql 2、登录Oracle&#xff0c;以sysdba身份连接 3、执行命令 D:\oracle\product\10.2.0\db_1\RDBMS\ADMIN\awrrpt.sql 4、输入report_type报告类型…

oracle打印awr报告,oracle导出AWR报告步骤

1、进入数据库 sqlplus / as sysdba ps:如果出现用户密码错误&#xff0c; 计算机管理 > 组 > ora_dba组里的用户登陆操作系统&#xff0c;就可以无需输入用户和口令&#xff0c;直接以sysdba的身份连上数据库。 2、查看用户 show parameter db_name 3、开始压测后执行 e…

Oracle导出AWR报告

一、使用root用户登录Linux服务器 二、切换至oracle用户 执行命令&#xff1a;su – oracle&#xff0c;然后回车 三、使用管理员权限连接数据库 执行命令&#xff1a;sqlplus / as sysdba&#xff0c;然后回车 四、生成报告快照 执行脚本&#xff1a;exec DBMS_WORKLOAD_RE…

如何分析AWR 报告

Automatic Workload Repository是10g引入的一个重要组件。在里面存贮着近期一段时间内&#xff0c;默认是7天&#xff0c;数据库活动状态的详细信息。 AWR报告是对AWR视图进行查询而得到的一份自动生成的报告。可以通过下面的脚本手工得到一份AWR报告。 exec dbms_w…

oracle 取awr报告,Oracle生成awr报告

Oracle生成awr报告 达芬奇的梦 2018-04-22 21:28:32 Oracle 一、手工生成awr报告的方法 1、相应权限用户登录(sysdba)后,在$ORACLE_HOME/rdbms/admin 2、在sqlplus里执行@?/rdbms/admin/awrrpt.sql,按照提示操作。 3、生成AWR报告说明 单实例:@$ORACLE_HOME/rdbms/admin/aw…

Oracle SQL调优系列之AWR报告简介

文章目录 一、AWE报告生成步骤1.1 工具选择1.2 自动创建快照1.3 手工创建快照1.4 生成AWR报告 二、AWR报告分析2.1 AWR之DB Time2.2 AWR之load_profile2.3 AWR之efficiency percentages2.4 AWR之top 10 events2.5 AWR之SQL Statistics 一、AWE报告生成步骤 对于SQL调优&#x…

AWR报告解读

0 初步结论 ① 数据库CPU资源不够&#xff0c;CPU使用率较高&#xff0c;造成CPU等待时间较长&#xff0c;可适当提升CPU资源&#xff1b; ② 数据库I/O资源消耗不太大&#xff0c;不存在IO瓶颈&#xff1b; ③ 可适当调大SGA空间&#xff08;增加10G左右&#xff09;&#xf…

用sql统计vintage,滚动率,迁移率,逾期率

获取代码请移步&#xff1a;用sql统计vintage&#xff0c;滚动率&#xff0c;迁移率&#xff0c;逾期率

如何用R语言做Vintage分析

一、背景 Vintage一词源自葡萄酒业&#xff0c;意思是葡萄酒酿造年份。因为每年的天气、温度、湿度、病虫害等情况不同&#xff0c;而这些因素都会对葡萄酒的品质产生很大的影响&#xff0c;所以人们对葡萄酒以葡萄当年的采摘年份进行标识来加以品质区分。现在Vintage分析被广泛…

风控中必做的数据分析

大数据领域就没有不做数据分析的&#xff0c;大数据风控也不例外。 我的观点是风控和其他互联网业务都是互通的&#xff0c;本文介绍下风控中必做的数据分析&#xff0c;用以说明数据分析是一通百通的。 工欲善其事&#xff0c;必先利其器。先说下数据分析的工具。 分析工具…

Vintage、滚动率、迁移率的应用

更多风控建模、大数据分析等内容请关注公众号《bigdatafengkong》 BY 小石头 一、Vintage Vintage源于葡萄酒酿造&#xff0c;葡萄酒的品质会因葡萄生长的年份不同、气候不同而不同。Vintage分析是指评估不同年份的葡萄酒的品质随着窖藏时间的推移而发生的变化&#xff0c;并且…