【PAT甲级】1115 Counting Nodes in a BST (30分):构造BST+DFS树的遍历
1115 Counting Nodes in a BST (30分)
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:
- The left subtree of a node contains only nodes with keys less than or equal to the node's key.
- The right subtree of a node contains only nodes with keys greater than the node's key.
- Both the left and right subtrees must also be binary search trees.
Insert a sequence of numbers into an initially empty binary search tree. Then you are supposed to count the total number of nodes in the lowest 2 levels of the resulting tree.
Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤1000) which is the size of the input sequence. Then given in the next line are the N integers in [−10001000] which are supposed to be inserted into an initially empty binary search tree.
Output Specification:
For each case, print in one line the numbers of nodes in the lowest 2 levels of the resulting tree in the format:
n1 + n2 = n
where n1
is the number of nodes in the lowest level, n2
is that of the level above, and n
is the sum.
Sample Input:
9
25 30 42 16 20 20 35 -5 28
Sample Output:
2 + 4 = 6
分析:构造BST+DFS树的遍历
构造BST,计算倒数两层节点的总个数
代码
-
柳神
1.一边输入数据一边构造BST,能使代码量变少
2.不需要记录每个节点的层数,depth作为函数的参数,在DFS遍历时记录num[]和最大深度maxDepth,最后得到num[maxDepth-1]和num[maxDepth-2]即可。
3.注意最后一层是maxDepth-1,因为比较depth和maxDepth谁更大时的depth比实际多+1(此时root==NULL)。
#include <iostream> #include <vector> using namespace std; struct node { int v; struct node *left, *right; }; node* build(node *root, int v) { if(root == NULL) { root = new node(); root->v = v; root->left = root->right = NULL; } else if(v <= root->v) root->left = build(root->left, v); else root->right = build(root->right, v); return root; } vector<int> num(1000); int maxdepth = -1; void dfs(node *root, int depth) { if(root == NULL) { maxdepth = max(depth, maxdepth); return ; } num[depth]++; dfs(root->left, depth + 1); dfs(root->right, depth + 1); } int main() { int n, t; scanf("%d", &n); node *root = NULL; for(int i = 0; i < n; i++) { scanf("%d", &t); root = build(root, t); } dfs(root, 0); printf("%d + %d = %d", num[maxdepth-1], num[maxdepth-2], num[maxdepth-1] + num[maxdepth-2]); return 0; }
-
我的做法(不太简洁)
/*构造BST,计算倒数两层节点的总个数*/ #include<iostream> using namespace std; const int maxN=1010; struct node { int dt;//数据 int layer;//所在层数 node* lchild; node* rchild; }; int num[maxN];//记录每层节点的个数 int maxLayer=-1;//节点的最深层数 int N; /*构造树*/ //创建新节点 node* newNode(int d) { node* Node=new node;//申请一个node型变量的地址空间 Node->dt=d; Node->lchild=NULL; Node->rchild=NULL; return Node; } //插入节点 void insert(node* &root,int d) { if(root==NULL) {//若某个节点没有左、右孩子,则将data作为它的孩子 root=newNode(d); return; } if(d<=root->dt) { //去左子树 insert(root->lchild,d); } else//去右子树 insert(root->rchild,d); } //构造BST node* create(int data[],int n) {//data节点数据,n节点个数 node* root=newNode(data[0]);//创建根节点 for(int i=1; i<n; i++) {//根节点已经创建了,从1开始! insert(root,data[i]); } return root; } /*DFS遍历树,记录每个节点层数和每层节点个数*/ void DFS(node* root) { if(root->layer>maxLayer) maxLayer= root->layer; num[root->layer]++; if(root->lchild!=NULL) { root->lchild->layer=root->layer+1; DFS(root->lchild); } if(root->rchild!=NULL) { root->rchild->layer=root->layer+1; DFS(root->rchild); } } int main() { fill(num,num+maxN,0); scanf("%d",&N); int data[N]; for(int i=0; i<N; i++) { scanf("%d",&data[i]); } node* root=create(data,N); root->layer=0;//根节点层数为0 DFS(root); printf("%d + %d = %d",num[maxLayer],num[maxLayer-1],num[maxLayer]+num[maxLayer-1]); }
小知识
-
(与本题无关)有关结构体struct:
- 定义结构体时,不能定义自身类型的变量(会导致循环定义),但可以定义自身类型的指针变量。
- 另外声明结构体变量的两种方法
#include<iostream> using namespace std; struct node { int data; node* child;//不能定义node,但可以定义node* }; int main() { /*方一*/ node* childN=new node(); childN->data=2; cout<<childN->data<<endl; /*方二*/ // struct node childN; // childN.data=2; // cout<<childN.data<<endl; return 0; }
-
选择更大的数并返回:
max(x,y)
-
Java里有
NULL
和null
,C++里只有NULL
!!
备错本
-
[1115 Counting Nodes in a BST:LIU]
-
build函数内,为root声明变量地址
root =new node();
,不需要node* root =new node();
,这样是重新声明另一个变量。node* build(node* &root,int v) { if(root==NULL) { root =new node();//声明节点变量 root->data=v; root->lchild=root->rchild=NULL; } else if(v<=root->data) { //左子树 root->lchild=build(root->lchild,v); } else { //右子树 root->rchild=build(root->rchild,v); } return root; }
//main函数 node* root=NULL; for(int i=0; i<N; i++) { scanf("%d",&v); root=build(root,v); }
-
-
[1115 Counting Nodes in a BST:我的做法]
-
create()先创建根节点,之后循环插入其他节点时,注意data[]下标是从1开始的。我错写成从0开始,结果在root=25的左孩子又插入了一边25。
//插入节点 void insert(node* &root,int d) { if(root==NULL) {//若某个节点没有左、右孩子,则将data作为它的孩子 root=newNode(d); return; } if(d<=root->dt) { //去左子树 insert(root->lchild,d); } else//去右子树 insert(root->rchild,d); } //构造BST node* create(int data[],int n) {//data节点数据,n节点个数 node* root=newNode(data[0]);//创建根节点 // cout<<"root.data="<<root->dt<<endl; if(root==NULL) { cout<<"root是空的"<<endl; } for(int i=1; i<n; i++) {//根节点已经创建了,从1开始! insert(root,data[i]); } return root; }
-