zoukankan      html  css  js  c++  java
  • 【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里有NULLnull,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;
        }
        
  • 相关阅读:
    《C#并发编程经典实例》学习笔记—2.4 等待一组任务完成
    Captcha服务(后续2)— 改造Captcha服务之Asp.Net Core项目中如何集成TypeScript
    VS Code调试.Net Core版Hello World
    Visual Studio Code 语言设置
    Captcha服务(后续1)
    css——格式
    作业 5/13
    css选择器
    作业 5/12
    前端——表格标签,表单标签,css
  • 原文地址:https://www.cnblogs.com/musecho/p/12322065.html
Copyright © 2011-2022 走看看