18_2

Posted sybil-hxl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18_2相关的知识,希望对你有一定的参考价值。

一、收获

1.层序输出二叉树,需要一个队列作为中转,如图(将就),以及queue模板的使用

技术图片

2.C++,当变量不好用时,可以考虑全局变量,虽然不太好,但是对于一个算法无妨

eg:

const int MAX=1000;
int arr[MAX][4]={0};
int n=0;
int dlmNum=1;//特别好用,如果不用全局,DLR中将无法编号
int coutData;//这个也很好用

 3.三叉树输入不是先序而是层序的问题:先用二维数组存储,再创建三叉树,学到了!!

4.当一个算法进行不下去的时候,一般来说,都是数据结构缺属性,大单添加就对了!

eg:

18_1添加了xd_num属性

struct XianDuan{
    int a_x;
    int a_y;
    int b_x;
    int b_y;
    int xd_num;//你的数据结构没有新线段中原始线段条数,缺乏一个合并的过程,怪不得没法处理
};

18_2添加了branch,dept,dlmrNum三个属性

struct Node{
    int data;
    Node *lchild,*mchild,*rchild;
    int branch;//0,分支数
    int dept;//1,深度
    int dlmrNum;//1,先序遍历顺序号
    Node(){
        branch=0;
        dept=1;
        dlmrNum=1;
    }
};

5.判断指针是否为空用 if(p) or if(!p),见https://www.cnblogs.com/sybil-hxl/p/10427772.html

6.三叉树你真是个磨人的小妖精!都要把朕折磨死了!

二、题目

第二题

燕子会将巢穴建在最稳定的地方,对于三叉树而言 子分支越多,越稳定。

第一行输入n,之后输入n行,每行输入4个数字,分别为子节点,左孩子,中孩子,右孩子(确保每个根已经在之前出现过),
计算子分支最多的节点中深度(高度)最深的节点编号(data),如果深度相同按前序遍历顺序输出第一个

eg:
输入:
8
1 2 3 4
2 5 6 7
3 8 0 0
4 0 0 0
5 0 0 0
6 0 0 0
7 0 0 0
8 0 0 0

输出:
2

三、本题思路

1.创建三叉树

(1)由于输入不是先序,而是层序,先用二维数组存储,再创建三叉树

(2)创建时候

①找出当前节点所在的行index,判断条件是该行第一个元素==当前(父)节点的data值

②对当前行的3个孩子分别进行赋值,若不是叶子则创建新子节点

2.先序遍历,目的是得到先序排序的顺序号

3.层序遍历,目的是得到子分支数和深度(以及最后的排序)

4.排序:按照分支数(大)>深度(深)>先序遍历顺序号(小/先)排序所有节点

(1)对于非数组类型的树指针,没法用qsort/sort排序,只能自己写算法比较,写在LayerOrder的最后!

(2)若把树改为结构体数组就能用qsort/sort,重写cmp函数实现二级排序!(这个暂时还没写,用数组比指针相对安全吧)

四、代码

#include <iostream>
#include <stdlib.h>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX=1000;
int arr[MAX][4]={0};
int n=0;
int dlmNum=1;
int coutData;

struct Node{
    int data;
    Node *lchild,*mchild,*rchild;
    int branch;//0,分支数
    int dept;//1,深度
    int dlmrNum;//1,先序遍历顺序号
    Node(){
        branch=0;
        dept=1;
        dlmrNum=1;
    }
};
typedef Node* Tree;

void CreateTree(Tree &T){//层序创建三叉树
    int i=0;
    //1.找出当前节点所在的行index,即i
    for(i=0;i<n;i++){//从第1行开始(index为0),因为第一行就是root节点,已经赋值了
        if(arr[i][0] == T->data){
            break;
        }
    }
    //2.对当前行的3个孩子分别进行赋值,若不是叶子则创建新子节点
    if(arr[i][1]!=0){
        Node* anode=new Node;
        T->lchild=anode;
        anode->data=arr[i][1];
        CreateTree(anode);
    }else{
        T->lchild=NULL;
    }
    if(arr[i][2]!=0){
        Node* anode=new Node;
        T->mchild=anode;
        anode->data=arr[i][2];
        CreateTree(anode);
    }else{
        T->mchild=NULL;
    }

    if(arr[i][3]!=0){
        Node* anode=new Node;
        T->rchild=anode;
        anode->data=arr[i][3];
        CreateTree(anode);
    }else{
        T->rchild=NULL;
    }
}

void DLMR(Tree &T){
    if(T){
        T->dlmrNum=dlmNum++;//这里的序号,使用了全局变量,才得以实现
        //cout<<T->data;
        //cout<<";序号:"<<T->dlmrNum<<endl;
        DLMR(T->lchild);
        DLMR(T->mchild);
        DLMR(T->rchild);
    }
}

void LayerOrder(Tree &T){
    //1.入根
    //2.出根,入左中右(若NULL则不入)
    //3.左(新根,循环2,直到队列空)
    queue<Tree> q;
    q.push(T);
    int maxBranch=0;
    int maxDept=1;
    int minDlmrNum=1;
    coutData=T->data;
    while(!q.empty()){
        Tree front=q.front();//获取队列头节点
        q.pop();//出队列
        //cout<<front->data<<"	";
        if(front->lchild){//指针非空,入队列
            front->branch+=1;//分支数+1
            front->lchild->dept=front->dept+1;
            q.push(front->lchild);
        }
        if(front->mchild){
            front->branch+=1;
            front->mchild->dept=front->dept+1;
            q.push(front->mchild);
        }
        if(front->rchild){
            front->branch+=1;
            front->rchild->dept=front->dept+1;
            q.push(front->rchild);
        }

        //以下为输出最大值,也就是比较/排序
        if(front->branch > maxBranch){
            maxBranch=front->branch;
            coutData=front->data;
        }else if(front->branch == maxBranch){
            if(front->dept > maxDept){
                maxDept=front->dept;
                coutData=front->data;
            }else if(front->dept == maxDept){
                if(front->dlmrNum < minDlmrNum){
                    minDlmrNum=front->dlmrNum;
                    coutData=front->data;
                }
            }
        }
        //cout<<";分支"<<front->branch<<";层"<<front->dept<<endl;
    }
    cout<<coutData<<endl;
}

int cmp(const void *a,const void *b){
    int result=(*(Tree)b).branch - (*(Tree)a).branch;
    if(result==0){
        result=(*(Tree)b).dept - (*(Tree)a).dept;
        if(result==0){
            result=(*(Tree)a).dlmrNum - (*(Tree)b).dlmrNum;
        }
    }
    return result;
}

void main(){
    freopen("G:/18_2.txt","r",stdin);
    //关于输入不是先序而是层序的问题:先用二维数组存储,再创建三叉树
    cin>>n;
    for(int i=0;i<n;i++){
        for(int j=0;j<4;j++){
            cin>>arr[i][j];    
        }
    }
    Tree root=new Node;
    root->data=arr[0][0];
    CreateTree(root);
    //先序遍历,目的是得到先序排序的顺序号
    DLMR(root);    
    //层序遍历,目的是得到子分支数和深度(以及最后的排序)
    LayerOrder(root);
    //最后一步排序,对于非数组类型的树指针,没法用qsort/sort排序,只能自己写算法比较,写在LayerOrder的最后!

    //若把树改为结构体数组就能用qsort/sort实现二级排序!
    /*Tree tree=new Node[n];
    root->data=arr[0][0];
    CreateTree(root);
    //先序遍历
    DLMR(root);    
    //层序遍历
    LayerOrder(root);
    qsort(root,n,sizeof(Node),cmp);
    delete[] tree;*/
}

 

以上是关于18_2的主要内容,如果未能解决你的问题,请参考以下文章

vscode代码片段建议bug

与另一个片段通信的片段接口

如何将列表视图中的数据从一个片段发送到另一个片段

这些 C++ 代码片段有啥作用?

[AndroidStudio]_[初级]_[配置自动完成的代码片段]

[AndroidStudio]_[初级]_[配置自动完成的代码片段]