树(二叉树)


-树没有节点—空树
-树的层次(根节点第一层)
-节点的度(节点的字数个数)----树的度(树中节点最大的度)

-树的节点是n,边数是n-1(每2个点连接1条边)
-节点的深度 (根节点(深度为1)自顶向下到该节点的深度值)
-节点的高度(最底层叶子结点(高度为1)自底向上逐层累加到该点的高度值)
-树的(节点最大)深度和树的(节点最大)高度,相等,但是某个具体节点不一定。

二叉树
递归定义:
二叉树没有根节点,空树
二叉树由根节点,左子树,右子树组成,左子树和右子树都是二叉树

二叉树和度为2的树的区别:
虽然每个节点的子节点个数都是不超过2的,
但是二叉树的左右子树是严格区分的,不能随意交换左子树和右子树的位置

满二叉树:
每1层的节点个数都到达了当层能到达的最大节点数

完全二叉树:
除了最下面一层,其余层的节点个数都到达了当层能到达的最大节点数

层次-----辈分
孩子/父亲/兄弟/祖先/子孙节点

二叉树的存储结构

struct node{
  typename data;//数据域
  node* lchild;//指向左子树根节点的指针
  node* rchile;//指向右子树节点的指针
}
//由于在二叉树建立树之前,节点不存在,因此其地址一般设为NULL
node* root=NULL
//创建新的节点(往二叉树中插入节点),使用下面的函数
node * newNode(int v){
//生成一个新节点,v为节点权值
	node * Node =new node;//申请一个node型变量的地址空间
	Node->data=v;//节点权值为v
	Node->lchild=Node->rchild=NULL;//初始状态下没有左右孩子
	return Node;//返回新建节点的地址
}
//二叉树节点的查找和修改
//插入:在给定数据域的条件下,在二叉树中找到所有数据域为给定数据域的节点
//并将它们的数据域修改为给定的数据域
//数据域为int例子
void search(node *root,int x,int newdata){
	if(root==NULL)
		return;//空树
	if(root->data==x)//找到数据域为x的节点,把他们修改为newdata
		root->data=newdatda;
	search(root->lchild,x,newdata);
	search(rooot->rchild,x,newdata);
}
//二叉节点的插入
//insert函数将在二叉树中插入一个数据域为x的新节点
//注意 根节点指针要用引用,否则插入不成
void insert(node* &root,int x){
	if(root==NULL){//空树 说明查找失败,插入位置是查找失败的位置
		root=newNode(x);//创建一个新节点,root指向新节点
		return;
	}
	if(由于二叉树的性质,x插在左子树){
		insert(root->lchild,x);
	}else{
		insert(root->rchild,x);
	}

}
//函数中需要新建节点,对二叉树结构做出修改,加引用
//修改原有节点内容/遍历树,不用加引用
//创建新节点之后,左右指针为NULL
//二叉树的创建
node* Create(int data[],int n){
		node* root = NULL;//新建空节点root
		for(int i=0;i<n;i++)
			insert(root,data[i]);//将data[0]-data[n-1]插入二叉树
		return root;//返回根节点 
}

在这里插入图片描述
层次遍历
从根节点向下逐层进行遍历,且对同一层的节点从左到右遍历
层次遍历相当于对二叉树从根节点开始的广度优先搜索BFS

void LayerOrder(node* root){
	queue<node*> q;//注意队列里面是存放地址
	q.push(root);//1.将根节点地址入队
	while(!q.empty()){
		node *now = q.front();//2.取出队首元素
		q.pop();
		printf("%d",now->data);//访问队首元素
		if(now->lchild!=NULL)q.push(now->lchild);
		if(now->rchild!=NULL)q.push(now->rchild);
	}
}
//广度优先(BFS)一般由队列实现,总是按层次的顺序进行遍历,基本写法如下(可作为模板)
void BFS(int s){
	queue<int> q;
	q.push(s);
	while(!q.empty()){
		取出队首元素top;
		访问队首元素top;
		将队首元素出队;
		将top的下一层节点未曾入队的节点全部入队,并设置为已经入队;
	}
}
//模板的每一个步骤的说明
//1.定义队列q,起点s入队
//2.写一个while循环,循环条件是q非空
//3.在while循环中,取出队首元素top,访问他(可以做任何事),访问完后将其出队
//4.将top的下一层节点中未曾入队的节点入队,并标记他们的层号为now的层号加一,并且设置这些入队的节点已经入过队
//5.返回2循环

在这里插入图片描述


//求给定矩阵中(1)块的个数
//枚举每一个位置的元素,如果是0,就跳过
//如果是1,就用BFS查询与该位置相邻的4个位置(前提是不过界)
	//判断他们是否是1(如果某个相邻元素时1,就同样去查询与该位置相邻的4个位置,直到1访问完毕)
	//为了防止走回头路,一般可以设置一个bool数组inq(in queue简写)来记录每一个位置是否在BFS中已经入过队




//广度搜索例子
#include <iostream>
#include <cstdio>
#include <queue>
using namespace std;

const int maxn=100;
int n,m;//矩阵大小n*m
int matrix[maxn][maxn];
bool inq[maxn][maxn]={false};//记录位置(x,y)是否已经入过队

struct node{
    int x,y;
}Node;

int X[4]={0,0,1,-1};
int Y[4]={1,-1,0,0};

    
    bool judge(int x,int y){//判断坐标(x,y)是否需要访问
        //越界返回false
        if(x>=n||x<0||y>=m||y<0)
            return false;
        //当时位置为0或者(x,y)已经入过队,返回false
        if(matrix[x][y]==0||inq[x][y]==true)return false;
        //以上条件不满足,返回true
        return true;
    }
    
   //BFS函数访问位置(x,y)所在的块,将该块所有1的inq设置为true
void BFS(int x,int y){
    queue<node> Q;//定义队列
    Node.x=x,Node.y=y;//当前节点坐标是(x,y)
    Q.push(Node);//将节点Node入队
    inq[x][y]=true;//设置(x,y)入过队 
    
    while(!Q.empty()){
        node top = Q.front();//取出队首元素
        Q.pop();//队首元素出队
        for(int i=0;i<4;i++){
            int newX=top.x+X[i];
            int newY=top.y+Y[i];
            if(judge(newX,newY)){//如果新位置(newX,newY)需要访问
                //设置Node的坐标是{newX,newY}
                Node.x=newX;
                Node.y=newY;
                Q.push(Node);//将节点Node加入队列
                inq[newX][newY]=true;
                
            }
        }  
    }

}

int main()
{
    scanf("%d%d",&n,&m);//6 7
    for(int x=0;x<n;x++){
        for(int y=0;y<m;y++){
            scanf("%d",&matrix[x][y]);//读入01矩阵//xy代表下标,真正的值是你输入的数字01
        }
    }
    int ans = 0;//存放块数
    for(int x=0;x<n;x++){//枚举每一个位置
        for(int y=0;y<m;y++){
             //如果元素为1,则还没有入队
             if(matrix[x][y]==1&&inq[x][y]==false){
                 ans++;//块数+1
                 BFS(x,y);//访问整个块,将该块所有1的inq都标记为true
             }
            
        }
    }
    printf("%d\n",ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值